Question

I've recently read an article that describes how they clearly may break the SRP. And now I'm totally confused, because I wrote single classes with setters and getters for a long time.

Also, I've found this, but it has nothing to do with the SRP

Well, at first glance, both getters and setters do not break the Single Responsibility Principle because they have logic which "belongs" only to the current class. They can access/write the class members which "serves" a single purpose. Fine.

But wait, let's define the basic terms first:

Data Access = both setters and getters

Data Handling = Data handling, operations such as CRUD, validation etc

If so, then we have two different responsibilities within a single class, thus breaking the SRP.


Let's assume for a moment, that in order not to break the SRP, we'll define Data Access and Data Manipulation in different classes.

class DA { // <- Data Access
  public string getName() {
      return this.name;
  }

  public string setName(name) {
     this.name = name;
  }
}

class DataHandler {
     public DataHandler(da) { // <- Inject an instance of DA
         this.da = da;
     }

     public bool validate() {
          // validation stuff
     }
}

It looks fine, because we do not violate said SRP. But here I have only one setter and only getter in the DA class.


Now the questions:

1) Should I always create another DA class even if I have only one setter and getter, just so that it does not break the SRP?

2) Do setters and getters really break the SRP, and should they never be used within any class?

3) And, if so, is Dependency Injection always the answer!?

Was it helpful?

Solution

Do setters and getters break the SRP?

Setters and getters are not the point. The point of the SRP is that a class should have only one responsibility.

Representing a domain object is a big responsibility. An object that does this is often called a "data object". It is common for data objects to have setters and getters due to language design or conventions, but they're not a separate responsibility themselves; they're just plumbing.

Getting data objects in and out of a persistent store is another big responsibility. An object that does this is often called a "data access object" (DAO). A DAO that isn't also a data object probably doesn't need setters and getters for attributes of the type of data object that it manages, although I can imagine a really terrible framework that would require them. Like DAOs, other kinds of objects that do things with data objects (displaying them, serializing and deserializing them, performing calculations on them, etc.) and are not data objects themselves probably don't need setters and getters that mirror the data objects.

So having setters and getters is a sign that your object is a data object. If it's a data object, and it's also a DAO or has some other big responsibility, it probably does violate the SRP.

Side note: you mention validation. In typical applications validation, at least of an individual data object, belongs in the data object itself, because representing a domain object and enforcing the individual correctness and relations among a domain object's attributes are pretty much the same responsibility.

Should I always create another DA class even if I have only one setter and getter?

Generally, yes. The point is not the number of attributes; the point is that representation and access are two different responsibilities and belong in different classes.

Typical applications have many domain objects, so if it makes sense to separate domain objects from their access at all, it makes sense to do it consistently for all domain objects, even single-attribute ones.

Is dependency injection always the answer?

It depends on your architecture and framework. You might have immutable data objects and DAOs whose methods take them as parameters; there is no DI there (although you might inject the DAOs into higher-level components that use them). You might have DAOs that are instantiated with a data object or a data object that has a reference to a DAO (both patterns that I've seen but dislike); you might need DI there. Either way, it doesn't have much to do with the rest of the discussion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top