

The Single Responsibility Principle - marcbarbosa
http://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html

======
tel
This is nice and drives home something particularly important to me. In
Parnas' quote he suggests _modularizing_ such that "things that change
together stay together". I think this is highly sensible. Another way of
saying it is that your _API_ s should be fixed.

But often this gets conflated in OO because objects are the hearth of
modularization (via encapsulation) along with _state_ and _interaction_ and
any number of other things.

\---

As a comparison point, you might examine ML modules. They look a bit like this

    
    
        module counter(X)
          count : X -> Int
          incr  : X -> X
    

and they specify nothing more than the fact that some unknown type X satisfies
the interface `(count, incr)`. We can then create a concrete implementation of
such a counter

    
    
        incCounter : counter
        incCounter = structure(Int)
          count n = n
          incr n = n + 1
    

The incCounter internally uses `Int` to represent `X`, but externally it's
completely impossible to tell. This means that modules define exactly two
things: encapsulation and interface.

\---

So why does this fall down in OO? Because objects lend themselves to being
thought of as entities which move through time and space in a stateful
fashion. This means you're also likely to encapsulate differences of entity
without regard for how they might change together or apart.

Returning to Parnas' quote: it's a bad idea to decompose into modules based on
a flowchart. Flowcharts allow you to emphasize the entities of your system,
but they are not demonstrating the boundaries of change.

So you can probably get better OO design by being clear when you're using
objects as entities (and thus perhaps you do not need encapsulation at all!)
and when you're using them as modules. Once this distinction is made it can be
clear when objects will derive from flowcharts and when objects will derive
from selections of choices made by people.

------
stiff
While he might understand what he is talking about, based on a corpus of
experience, people who learn about this "principle" as they learn to program
do not typically understand it and tend to draw only the wrong conclusions
from it. What makes for coupling, and how to avoid it, you simply learn with a
lot of practice, and there are not many clearcut guidelines you can formulate,
it all varies depending on the problem. At best you can read SICP and see how
they decouple everything by doing lots of data-driving and dynamic dispatch
and things of this sort.

This is too vague to be a "principle", and only causes confusion. It is about
as precise, and as useful, as the "write good code" principle.

~~~
mattgreenrocks
A lot of people seem to chafe at these principles because they convey truths
about a intangible reality they may not even be able to perceive. They only
see more work for little payoff. They don't have the body of knowledge and
experience (nor the intuition) to know when when to abstract more. We're also
in a post-enterprise era, where any sort of deliberate design is often mocked
by way of strawman AbstractComposerFactorySingleton references. Rhetoric
masquerades as honest intellectual debate for self-promotional purposes.

I consider myself fortunate to have written enough C++ to learn coupling and
cohesion. When you screw these up in C++, you pay for it, over and over,
through increased compile times and link times.

~~~
spion
They don't chafe because they convey truths about a intangible reality they
may not even be able to perceive. They chafe because nothing is actually being
conveyed. Its a bunch of words removed from any actual meaning - from the
concrete problems that caused the person to arrive to the truth being
"conveyed". They're like the conclusion part of an essay with all the rest
left out. They tell nothing to people that don't already know, and nothing new
to people that do.

Its no wonder people either tend to discard them or to apply them incorrectly.

~~~
mattgreenrocks
Yeah, the actual context is rarely ever delivered. And that matters a lot.
Sometimes I wonder how well it would be received, though. Not to mention many
books on software engineering tend to be written in a more abstract style than
most blog posts. I'm not sure of the precedent for this is there; it would
certainly help.

The GoF book does a decent job balancing context with theory, IMO.

~~~
spion
I liked the GOF book. But what I'd really _love_ to read about are the
descriptions and (architectural) histories of complete, real software systems,
especially about the design decisions and the reasons behind those decisions.

I think such information will be received with great interest - it would be
like receiving a shot of condensed experience in readable form. Not exactly
the same with actual experience of course, but way better than just abstract
principles that leave me unconvinced.

~~~
icebraining
Have you seen the Architecture of Open Source Applications[1]? I think it fits
very well with what you just described. It explains not only the what, but
also the why, with real examples of successful applications.

[1] [http://aosabook.org/en/index.html](http://aosabook.org/en/index.html)

~~~
spion
I remember seeing it and promptly forgetting about it. Thats precisely what I
needed. Thank you.

------
sunir
I personally find it easier to think of it as Conway's Law:

"organizations which design systems ... are constrained to produce designs
which are copies of the communication structures of these organizations" \- M.
Conway

More on [http://c2.com/cgi/wiki?ConwaysLaw](http://c2.com/cgi/wiki?ConwaysLaw)
and
[http://en.wikipedia.org/wiki/Conway's_law](http://en.wikipedia.org/wiki/Conway's_law)

However, I also hate this mental model of software engineering because I have
often found it easier to refactor the organization. Maybe because I'm a prima
donna and only like working at startups.

I think it's better to require each portion of code has a narrow interface so
you can reason in your mind easily about what that code segment does and
should do into the future. A function or a class must promise what it should
deliver given some inputs and not violate that expectation. If you ever had to
reason about code using invariants, you'll grok this.

More on
[http://c2.com/cgi/wiki?NarrowTheInterface](http://c2.com/cgi/wiki?NarrowTheInterface)

------
Arnor
My team and I have been working on a problem over the last week or so that
screams modularity problems. Each time we think we have it solved, someone
says "Wait, there's this report only 2 of us have ever heard about that
doesn't work because X, Y, Z." The discussion has lasted a couple weeks and is
starting to push deployment times back.

Essentially, we have a distributed set of `devices` which interact with
`customers`. Each customer has a `session` with the device. During the
session, the `customer` may make various types of `payments` (coin or credit
card) for various types of `fees`. Additionally, the customer may receive one
or more `tickets`. The data model is getting pretty big with:

* Devices

* Sessions

* Line Items

* Allocations

* Payments

* Adjustments

* Violations

* Fees

For accounting purposes, we need to be able to map our payments to the fees
and violations they are paying for. Customers might make a single payment to
cover multiple violations and those violations may be across multiple
sessions.

The number of times I've heard "this new solution fixes X but breaks π" is
frustrating, but I don't see how this could be separated out. Perhaps others
have insights that would simplify all of this, but it seems to me that the
essential fact of our system is that the payment/line item/allocation system
is responsible for many tasks/reports. I read articles like this and pine for:

A) A project where true modularity is achievable.

B) The skills to make my current project truly modular.

~~~
thibauts
I'd say code a raw draft to gain a better understanding of the problem space,
then talk about it again. If you're close enought to something workable
refactor iteratively and let the concepts emerge.

------
gone35
(Warning: bikeshedding/off-topic angry rant ahead. Please ignore.)

"The Single Responsibility Principle (SRP) states that each software module
should have one and only one reason to change. This sounds good, and seems to
align with Parnas' formulation. _However it begs the question_ : What defines
a reason to change?" (emphasis added)

Ok I realize that languages evolve and all; and I see how the nearly universal
appeal of using the phrase "begging the question" in this way will ensure it
will soon make its way into the dictionary; but I think people should at least
know the original meaning of the phrase [1] and that, in some pedantic or
predominantly academic circles today, it is considered as incorrect usage.
That is all.

[1] [http://begthequestion.info/](http://begthequestion.info/)

~~~
jdminhbg
I don't think you're right here. In this case, the fact that "a reason to
change" is central to the definition and itself undefined means that the
definition is begging the question in the original sense.

------
slantedview
The most important principle in software design. Follow SRP and so many other
things just fall into place.

------
josephschmoe
Prior to reading this article, I always took the "single responsibility
principle" literally, but largely do this in practice whenever possible.

Thank you.

