4

In other words, is DRY (don't repeat yourself) applied at a class level a subset of SRP (single responsibilty principle)?

What I mean is that while SRP states that each class should have only a single responsibility ( ie. class should only have one reason to change ), is it the application of DRY at class level that prevents two classes from having the same responsibility ( thus it is DRY that prevents the repetition/duplication of same responsibility in two different classes )?

Thank you

  • 2
    DRY will avoid duplicating logic between classes, but it won't prevent putting two or more responsibilities into a single class. Is that what you mean? – MetaFight Dec 9 '13 at 18:21
  • @MetaFight: Yes, while DRY won't prevent putting two responsibilities into a single class ( that's the job of SRP ), I'm curious if it is DRY that prevents duplication of responsibilities between classes. In other words, is having several classes with same responsibility a violation of SRP? If it's not a violation of SRP, this would suggest that DRY is not a subset of SRP – bckpwrld Dec 9 '13 at 18:35
  • 1
    I see. I would say having several classes with the same single responsibility is not a violation of SRP. It is, however, a violation of DRY. I'm not sure how helpful I'm being here :) – MetaFight Dec 9 '13 at 18:40
  • You're being very helpful – bckpwrld Dec 9 '13 at 22:17
8

What I mean is that while SRP states that each class should have only a single responsibility ( ie. class should only have one reason to change ), is it the application of DRY at class level that prevents two classes from having the same responsibility ( thus it is DRY that prevents the repetition/duplication of same responsibility in two different classes )?

No. You can still not repeat yourself but violate single responsibility. Likewise, you can repeat yourself but classes only have a single (duplicated, but subtly different) responsibility.

While the two guidelines can and will tend to overlap, they are orthogonal concepts.

  • So you agree with MetaFight that having several classes with the same single responsibility is not a violation of SRP? – bckpwrld Dec 9 '13 at 19:24
  • @bckpwrld - No, because often those classes live in different assemblies - often written by different people. They didn't know the other implementation existed. It may violate DRY if written by the same group/company, but even that may be necessary if the implementation details differ enough. Consider all the different collection classes. Do HashSet<T> and List<T> violate DRY? Only at the most cursory of glances. – Telastyn Dec 9 '13 at 20:02
5

SRP means that your class should have only a single responsibility, so you can easily name your class, and you can tell only by reading the name, what it does.

DRY means that you should not repeat yourself, so by maintaining your code you don't have to override the same code twice or more.

They have certainly a connection, because both of them are about maintaining the code. DRY is a low abstraction level tool to do that, because it has no clue about what the code does. SRP is a high abstraction level tool to do that, because it is about responsibilities and not the code itself. So you should use both concepts together by developing your application. Based on every case I met until now, I recommend the SRP over DRY rule. So by any conflict between the two principles you can decide which one to use.

For example, where A and B are responsibilities:

If you have a DRY code which does not meet SRP:

class AB
    doSomethingArelated()
    doSomethingBrelated()

you can split it up the following way, so it will meet with DRY and SRP as well:

class A
    doSomethingArelated()

class B
    doSomethingBrelated()

If you have a DRY code, but A and B use the same properties:

class AB
    x
    y
    doSomethingArelatedToX()
    doSomethingBrelatedToXAndY()

then if you want to meet with DRY and SRP at once you should use polymorphism. You should use composition over inheritance by that, because it is easier to maintain.

class AB
    a
    b
    doSomethingArelatedToX()
        a.doSomethingArelatedToX()
    doSomethingBrelatedToXAndY()
        b.doSomethingBrelatedToXAndY()

class A
    c
    doSomethingArelatedToX()
        c.doSomethingGeneralToX()

class B
    c
    y
    doSomethingBrelatedToXAndY()
        c.doSomethingGeneralToX()
        doSomethingToY()
    doSomethingToY()

class C
    x
    doSomethingGeneralToX()

In really special cases SRP can override DRY:

class AB
    a
    b
    doSomethingArelatedToX()
    doSomethingBrelatedToXAndY()

class A
    x
    doSomethingArelatedToX()

class B
    x
    y
    doSomethingBrelatedToXAndY()

This happens by DDD when you have properties related to multiple bounded contexts. The most common thing is the aggregate id in here, but for example by a webshop the product size or weight can be important in the delivery and inventory contexts either.

2

Some design patterns could allow you to have simpler class by sharing the common routine.

If for example, you have to do a discount calculation on sales and in the sales report, instead of having the same code in both classes, you could have a third, more specific class, that does that calculation.

This way, your class that compute the sale, could rely on the third class to get the final price, as could the sale report class.

See the Strategy Pattern and Composite pattern as starter examples

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.