I'm trying to understand the SRP but, whilst I understand the reasoning behind how to apply it, I'm not really seeing the benefit of doing so. Consider this example, taken from Robert Martin's SRP PDF:
interface IModem
{
void Dial(string number);
void Hangup();
void Send(char c);
char Recv();
}
He proposes separating this into two interfaces:
interface IModemConnection
{
void Dial(string number);
void Hangup();
}
interface IModemDataExchange
{
void Send(char c);
char Recv();
}
I've also been reading this article, which takes this one step further:
interface IModemConnection : IDisposable
{
IModemDataExchange Dial(string number);
}
interface IModemDataExchange
{
void Send(char c);
char Recv();
}
At this point, I understand what is meant by functional (Send / Recv
) and non-functional (Dial / Hangup
) aspects, but I don't see the benefit of separating them in this example. Considering this basic implementation:
class ConcreteModem : IModemConnection
{
public IModemDataExchange Dial(string number)
{
if (connection is successful)
{
return new ConcreteModemDataExchange();
}
return null;
}
public void Dispose()
{
//
}
public bool IsConnected { get; private set; }
}
At this point, let me quote Robert Martin again, even though he's talking about a different example from that PDF:
Secondly, if a change to the GraphicalApplication causes the Rectangle to change for some reason, that change may force us to rebuild, retest, and redeploy the ComputationalGeometryApplication. If we forget to do this, that application may break in unpredictable ways.
This is what I don't understand. If I had to create a second implementation of IModemDataExchange
, and I wanted to make use of that, I would still have to change the Dial
method, meaning the class also needs to be recompiled:
public IModemDataExchange Dial(string number)
{
if (some condition is met)
{
return new ConcreteModemDataExchange();
}
else if (another condition is met)
{
return new AnotherConcreteModemDataExchange();
}
return null;
}
I can't see what this has done to reduce the effects of change on the class. It still needs to be recompiled, so what's the benefit? What do you gain from doing this that is so important to producing quality code?
The Single Responsibility Principle (SRP) is the concept that any single object in object-oriented programing (OOP) should be made for one specific function. SRP is part of SOLID programming principles put forth by Robert Martin. Traditionally, code that is in keeping with SRP has a single function per class.
The Single Responsibility Principle (SRP) states that a class should have only one reason to change. It was first cited in this form by Robert C. Martin in an article that later formed a chapter in his Principles, Patterns, and Practices of Agile Software Development book.
Single Responsibility states that an Object be responsible for a single unit of work. Seperation of Concerns states that applications should be split in to modules whose functionalities overlap as little as possible.
The single responsibility principle is a software design guideline which states that every module, class or function in your code should have only one responsibility and only one reason to change. It helps to transform a large block of code into well-defined, well-labelled, high cohesive, clean and robust components.
To me the modem example above always seemed like a case for the interface segregation principle rather than SRP, but that's besides the point.
In the part you called out regarding the Rectangle
, I think you're just misinterpreting it. Martin is using the Rectangle as an example of a shared library. If the GraphicalApplication
requires a new method or change in semantics in the Rectangle
class, then that affects the ComputationalGeometryApplication
since they both "link" to the Rectangle
library. He's saying it violates SRP because it is responsible for defining rendering bounds and also an algebraic concept. Imagine if the GraphicalApplication
changed from DirectX to OpenGL where the y-coordinate is inverted. You may want to change some things around on the Rectangle
to facilitate this, but you're then potentially causing changes in ComputationalGeometryApplication
.
In my work, I try to follow the SOLID principles and TDD, and I've found that SRP makes writing tests for classes simple and also keeps the classes focused. Classes that follow SRP are typically very small, and this reduces complexity both in code and dependencies. When stubbing out classes, I try to make sure a class is either "doing one thing", or "coordinating two (or more) things". This keeps them focused and makes their reasons for change only dependent on the one thing they do, which to me is the point of SRP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With