1

In the book UML 2 and the Unified Process from Arlow and Neustadt has been told: Analysis classes should have 3 to 5 responsibilities

But as you know we have the SRP that tells us something else!!

why so happend? I'm confused

Which of the following deductions is correct?

Case 1- The different definitition of responsibilty has been adopted by the authors

Case 2- the definitions adopted is the same and actually the purpose of them is the following: We can have multiple responsibilities in analysis classes but in design phase in regarding to SRP, we split the analysis classes to design classes with one responsibility

Please help me

flexibleHammer
  • 119
  • 1
  • 5
  • Does this answer your question? [What is the real responsibility of a class?](https://softwareengineering.stackexchange.com/questions/220230/what-is-the-real-responsibility-of-a-class) – gnat Apr 28 '20 at 05:47
  • 1
    I don't know that book, but I am pretty sure it is "case 2" - sort of (if you believe in the feasibility of waterfall like approaches with an "analysis phase", a "design phase" and an "implementation phase"). In reality, splitting classes into different responsibilities is often done **during a refactoring cycle** (and not during some analysis or design phase). – Doc Brown Apr 28 '20 at 05:56

4 Answers4

6

These are using these terms in a slightly different way, but they are trying to convey similar underlying ideas.

Here's a quote from the book you referenced (emphasis mine):

Going back to the ShoppingBasket example, you would expect this class to have responsibilities such as

  • add item to basket;
  • remove item from basket;
  • show items in basket.

This is a cohesive set of responsibilities [...]. It is cohesive because all the responsibilities are working toward the same goal [...]. In fact, we could summarize these three responsibilities as a very high-level responsibility called "maintain basket".

Now, you could also add [... some other ...] responsibilities to the ShoppingBasket [...]. But these responsibilities do not seem to fit with the intent or intuitive semantics of shopping baskets. [...] It is important to distribute responsibilities appropriately over analysis classes to maximize cohesion within each class.

Finally, good classes have the minimum amount of coupling to other classes.

They are essentially talking about achieving high cohesion and low coupling - the goal is for typical changes to be localized and low impact (e.g. in a single class, rather then spread out throughout the codebase, without cascading changes to seemingly unrelated code).

So they are saying that each class should have one "high level responsibility".

SRP captures a very similar set of ideas:

  • Parnas - separate based on the kind of changes that are likely
  • Dijkstra - the idea of separation of concerns
  • the notions of coupling and cohesion

SRP originally stated that a software module should have one responsibility; Bob Martin later decided to clarify "responsibility" as "reason to change".

As with all the principles, their single-sentence statements are really a neat way to remember them and talk about them; but to understand them, you have to go beyond that and dig a bit deeper into the underlying ideas.

The primary point of software design and its principles is to have some control over complexity that arises over time due to change. If the code never changed, design wouldn't matter all that much.

In any domain, there are things that cause change. E.g. a business for which the software is being made might need certain features; but businesses have their own way of doing things, and they want the software to support that. One set of users might need one set of features, and another set of users (maybe from another department) might need a different set of features. They might have certain business processes already in place, and they might want the software to automate some parts of that - and if the developer team didn't spend enough time to understand those processes (how they do things) and their business (why they do things, how they think about concepts) the software is going to be conceptualized and structured/developed in a way that makes it hard to make the kinds of changes that they'll need - because the code will be based on the wrong set of abstractions (these are hard to change), and it will therefore be coupled in the wrong kinds of ways. You can't have code that supports all imaginable kinds of changes. You make it support certain kinds of changes by making it rigid for other kinds. Design is about tradeoffs. The trick is to be conscious/intentional about this.

You can think about these factors that drive the direction of change as the "forces of change", or "axes of change". These are often driven by people, organizations, their policies and politics, etc. That's where and how humans come into the picture. To quote Martin's article: "who must the design of the program respond to?"

The idea is, initially, to understand the domain enough to recognize some of these axes of change, and design around that. This will in part be based on domain analysis, in part on experience. It is important, however, not to over-engineer at this point: don't consciously make assumptions about domain aspects you don't yet have a good understanding of.

But it doesn't stop there. Since agile development is an iterative process, you'll be learning about the domain and the system as you go along. You'll discover that there are axes of change you didn't account for, or that some of the ones you anticipated are not so important because they rarely cause change in practice. Or that you've made some wrong assumptions, and that they now give you trouble. You have to decide when, where and how to restructure your code based on this new knowledge - in a "wait for the last responsible moment" fashion (before the coupling and complexity goes out of control). This is why we have heuristics like YAGNI and "wait for three examples of something before you abstract it or DRY it up". Doing this is more important in those parts of the codebase that have proven to change the most over time, in other parts less so.

To quote Bob Martin again (emphasis mine):

When you write a software module, you want to make sure that when changes are requested, those changes can only originate from a single person, or rather, a single tightly coupled group of people representing a single narrowly defined business function. You want to isolate your modules from the complexities of the organization as a whole, and design your systems such that each module is responsible (responds to) the needs of just that one business function.

This is why "responsibility" in SRP has to be defined in a somewhat abstract way - you have to discover how to partition the code into classes (or other kinds of components) for the specific application you are developing.

Filip Milovanović
  • 8,428
  • 1
  • 13
  • 20
  • thank you for answer, I understand what you said but for more clarification of the terminology used by CE community I'm obsessed with this; so please take a look to the my next question: – flexibleHammer Apr 28 '20 at 20:35
  • until each operation is considered as responsibility, there is no problem; because the cohesive set of these operations(responsibilities) will be a high-level responsibility and we can make a new class with this only high-level responsibility (continue in the next comment) – flexibleHammer Apr 28 '20 at 20:38
  • (continue) now my what is my concern? please refer to summary part of chapter 8: "Finding analysis classes" of the mentioned book then you will find this definition: "a **RESPONSIBILITY** is a semantically cohesive set of operations"
    according to what was said we can conclude **RESPONSIBILITY** is a high-level responsibility now let's go back: based on the book, a good analysis class constitutes of 3-5 RESPONSIBILITIES* i.e. 3-5 high-level responsibilities; but I belive such a class can not functional cohesion and must be splitted please share your opinion with me
    – flexibleHammer Apr 28 '20 at 20:38
  • note that my intention of **RESPONSIBILITY** is to refer to what is come in definition – flexibleHammer Apr 28 '20 at 20:52
  • There's no true (formal) definition of responsibility in there; they are talking in a rather informal way, and they are being slightly inconsistent. They only mentioned the "high-level responsibility" concept once, in passing - don't make any other inferences about that, like "we can conclude RESPONSIBILITY is a high-level responsibility". Assume they don't change what they mean by that term on the fly throughout the text. The exact details don't matter anyway, the takeaway is to think in terms of relatively small classes that model "one specific element of the problem domain". – Filip Milovanović Apr 29 '20 at 00:27
  • They recommend 3-5 responsibilities in a class; the 3 they name for the ShoppingBasket are add, remove, and show items. Note, however, that these are closely related - a business would generally want to have all of these, not just one. But more importantly, if there's a change to one, the others will very often have to change as well. That's cohesion - put things that change together for the same underlying reason in the same class. If you notice that two sets of operations in the same class keep changing independently - separate them out. – Filip Milovanović Apr 29 '20 at 00:27
  • @flexibleHammer P.S. "We can have multiple responsibilities in analysis classes but in design phase in regarding to SRP, we split the analysis classes to design classes with one responsibility" - it's not exactly that; you're not going to split the ShoppingBasket class into 3 classes with one function each (they even say "beware of functoids"). But you are going to add concepts, change structure, shuffle data and relationships around, add, merge and split classes later on as you gain more understanding of the domain and of how to actually to put the system together. (continues below...) – Filip Milovanović Apr 29 '20 at 00:48
  • @flexibleHammer Basically, at different phases of the project, you'll have different amounts of information that you can base your decisions about what constitutes a responsibility on, and you'll be working at different levels of granularity - and you'll use that information to strategically restructure to gain something or solve a design issue. P.P.S. See also the comments above - i forgot to tag you. – Filip Milovanović Apr 29 '20 at 00:48
3

You’re attentive reading and analysis has helped you to spot a common misunderstanding. Congratulations!

The right case is 1: the authors use the same word with very different definitions:

  • For most authors in the OO domain, the responsibility refers to what a class has to do. The term probably finds its roots in Rebecca Wirfs-Brock pioneering work about responsibility driven design.
  • Uncle Bob, the author of the SRP, used the term as reference to the human responsibility for a class. He explains it as being a "reason to change” and explains that "(...) those changes can only originate from a single person, or rather, a single tightly coupled group of people representing a single narrowly defined business function." You’ll find the full explanation in his clarifying article.

In my view, Uncle Bob could have named his principle less ambiguously as “Single Concern Principle”, since the separation of concerns is its aim. The alternate wording proposed by Uncle Bob himself in his article clarifies this without any reference to a responsibility: "Gather together the things that change for the same reasons. Separate those things that change for different reasons".


Edit: Can we stay objective please ?

In view of the heated discussions (already 2 downvotes for an objective and documented answer) and speculations in some other answers, I'd like to go back to some definitions, since that's what the question is really about.

The question starts with UML. Grady Booch, Ivar Jacobson and James Rumbaugh, the fathers and inventors of UML published 1999 in the Unified Software Development Process:

Page 48: The responsibilities of a class are simply a compilation of all roles it plays in all of the use-case realizations. Taken together and removing the overlaps between the roles, we will get a specification of all the responsibilities and attributes of the class.

Page 182: An anlysis class (...) behavior is defined by responsibilities on a higher, less formal level. A responsibility is a textual description of a cohesive subset of the behavior defined by a class.

Another very commonly used definition of responsibilities comes from the CRC cards invented by Kent Beck and Ward Cunningham, two fathers of the agile movement, and published September 1989:

Responsibilities identify problems to be solved. The solutions will exist in many versions and refinements. A responsibility serves as a handle for discussing potential solutions. The responsibilities of an object are expressed by a handful of short verb phrases, each containing an active verb.

As you can see, there may be several such responsibilities for an object in their expert view. Note that this article refers explicitly to Wirfs-Brock's article, also published in September 1989.

Rebecca defined the responsibilities by analogy to contracts:

It focuses on the contract by asking:

  • What actions is this object responsible for?
  • What information does this object share?

Again, the objects are seen to naturally have several responsibilities. She continues by explaining that some of these responsibilities may be delegated to other objects.

Among other authors using Wirfs-Brock's concept of responsibility, you will find for example GoF, a reference for good software design. For every pattern in their book, they describe a list or participants with their responsibilities, as well as the collaboration between these participants. Take for example the desciption of a concrete decorator (I highlighted the plural):

  • adds responsibilities to the component

Now, on the other side, you have one author, who claims each object shall have a single responsibility. This contradicts the assumptions of all the other authors. Looking at Uncle's Bob's article I quoted in the beginning of my answer, it is clear that "a reason to change" as he himself defines a responsibility, is something very different definition from all the other authors.

In the comments, some disagree with my interpretation of what Uncle Bob really meant. I accept this: I'm not in R.C. Martin's head and my interpretation is a speculation. The other interpretation as well. However, objectively, one cannot negate that Uncle Bob's definition is (very) different from all the others. So it's case 1. Any other interpretation is pure speculation.

Christophe
  • 74,672
  • 10
  • 115
  • 187
  • 1
    Does not convince me. When Uncle Bob wrote "This principle is about people." he clearly did not mean "the human responsibility for a class" in the sense who is reponsible to maintain that class. The examples in that blog entry show clearly that he meant it in the sense of separating responsibilities in a way to make requirements of different stakeholders (=people) to be mapped to different classes. So Bob Martin's definition is still also one which fits under the term "what a class has to do". – Doc Brown Apr 28 '20 at 09:14
  • That does not necessarily mean that ^"case 1" is not the correct answer to the question, but to answer this, I guess one needs to have a look into that book mentioned by the OP. And it may turn out that "case 1" and "case 2" are both correct. – Doc Brown Apr 28 '20 at 09:46
  • @DocBrown Your comment has the advantage of seting the focus on the core of the terminology issu in SRP. Roughtly 50% of Uncle Bob's article is about who should decide about valid reasons to change. I used the term "human responsibility" to avoid Bob's full quote *"(...) those changes can only originate from a single person, or rather, a single tightly coupled group of people representing a single narrowly defined business function"*. – Christophe Apr 28 '20 at 10:03
  • @DocBrown Bob later proposes a much better alternate wording that is no longer tied to any kind of responsibility concept. Full quote: "Gather together the things that change for the same reasons. Separate those things that change for different reasons". And IMHO this alternate definition is closer to the concept of "same concern" rather than "single responsibility". – Christophe Apr 28 '20 at 10:05
  • I reworded the answer accordingly. – Christophe Apr 28 '20 at 10:19
  • I wrote my own answer to give a better explanation of why I think the answer is "case 2". – Doc Brown Apr 28 '20 at 10:53
  • @DocBrown I think there is a lot of speculation around what Uncle Bob could have meant. So let's go back to the root of the question: the objective definitions used by different OO thought streams. – Christophe Apr 28 '20 at 19:03
  • 1
    I think the important not what Uncle Bob really meant by "responsibilties". The point is what that book authors cited by the OP meant with "Analysis classes", and why the heck OP thinks those Analysis classes must follow the SRP. Why? Since when is the SRP a law every UML book must follow? Whatever defintion of responsibility Bob Martin meant, I don't see why it must apply to informal classes used in requirements analysis - because Bob Martin does not talk about "Analysis classes", he always talks about real code when it comes to the SRP. – Doc Brown Apr 28 '20 at 19:20
  • .. so I think the "different definitions of responsibilities" is a red herring, the different notions of classes (in analysis and in code) is more important. For me, that is nearer to what the OP listed under "case 2", but one might also say "neither case 1 or case 2" is correct". – Doc Brown Apr 28 '20 at 19:24
  • @DocBrown I think you misunderstand my answer. I fully agree with Martin’s idea behind SRP, which is sound SE. I even quoted his (better) alternate definition. The point here is that a “high level responsibility” is closer to a “concern” than the kind of low-level duties/actions/behaviors you find in design classes. Unfortunately the ambiguity of Martin’s chosen term mislead many developers to create an artificially high number of classes, just because they try to follow Martin’s advice on the wrong level of abstraction. And this is the whole point of my answer. – Christophe Apr 29 '20 at 06:57
1

Is there multiple definitions for responsibility of class?

In short, yes. That's true of most words, and while logical sciences often tend to be much more rigorous about its nomenclature, there are still some ambiguous namings. You have stumbled on one of them.

Responsibility can be defined at different granularities. You could say that waiter and cook are two separate responsibilities. Or you could further subdivide the omelette cook from the burger cook and consider them as separate responsibilities. For a large enough kitchen, you may even consider breaking the eggs and cooking the omelette as separate responsibilities.

What matters here is the boundary (granularity) of what is considered to be a responsibility. Different scenarios (e.g. a family owned restaurant versus an industrial kitchen) will favor different approaches.

Analysis classes should have 3 to 5 responsibilities

I don't have access to the book you have, but this seems founded on the CRC modeling approach. Here, you can see that a "responsibility" is not used to describe a class' reason for existing, but rather particular behaviors of a given class.

A class represents a collection of similar objects, a responsibility is something that a class knows or does, and a collaborator is another class that a class interacts with to fulfill its responsibilities.

Take a look at the included image. According to the CRC model, a customer has 5 responsibilities and an order has 6.

enter image description here

But as you know we have the principle SRP that tells us something else!!

This is where Uncle Bob's definition of a "responsibility" diverges. Uncle Bob's definition of a responsibility doesn't label particular behaviors of a class, but rather the class itself. According to Uncle Bob, the customer has 1 responsibility (identifying the order placer) and the order as 1 responsibility (containing the order information)

It's the same thing but described differently.

Consider what matters to you. Does your application consider every cook to be capable of making every dish? Of does your application expect that each cook can have a particular expertise? These kinds of considerations will lead you do define your responsibilities at the appropriate level, i.e. only as fine-grained as is meaningfully relevant for your scenario, not more.

Flater
  • 44,596
  • 8
  • 88
  • 122
  • i.e. in CRC modeling approach each operation is called a responsibility and in Robert Martin set of operations of a class is called responsibility? – flexibleHammer Apr 28 '20 at 21:01
  • @flexibleHammer: Each operation _and property_ (i.e. the "knows X" responsibilities), but your summary is correct, yes. – Flater Apr 29 '20 at 08:04
0

I did not read that book, but when I hear of "UML" "Analysis classes", I think of classes used by some business analyst for requirements modeling, nothing more, nothing less (if you who has read the book think I got this totally wrong, please leave a comment and I will delete my answer).

I take the freedom and cite an example from that blog article already mentioned by Christopher:

enter image description here

During a requirements analysis, it is perfectly fine to use a class like this in an UML diagram! So this is a valid "analysis class".

Applying the SRP already on this level of abstraction would often lead to lots of classes with just a single method and no difference between the class name and the method name, so no apparent value.

But when Robert Martin talks about the SRP, he has IMHO the kind of classes in mind which will really occur in code, when these requirements will be implemented. The "analysis class" above is something one would probably not find in Bob Marin's code after he applied the SRP.

Instead, I would expect to find classes in his code like

  • a PaymentCalculator class

  • a whole set of multiple classes for reporting the hours to an ERP system

  • a class EmployeeRepository for saving the employee data to a database, with an interface IEmployeeRepository and maybe mock implementations for testing

  • a sole Employee class for holding the data (and maybe some reusable member function which don't require anything but data members from that class).

Martin's article explains well why it is good idea to separate these different responsibilities into classes to allow maintenance and evolvement of the system, with a lower risk of breaking things when changes have to implemented afterwards. That is where the SRP makes most sense!

So in short,

  • when using UML during requirements analysis, the SRP (in Bob Martin's sense) is of minor importance, maybe even counterproductive.

  • separating reponsibilities in a design phase makes sense, since one can start here to group things together which belong together, and separate things which should be separated

  • but where it makes most sense is when you have added some code to an existing class, added some responsibilities, and then you refactor the code to separate classes to keep it maintainable

This is what I meant with my comment under your question, and why I think "case 2" is the correct answer. However, since I don't have your book, it is perfectly possible that the authors meant something different and case 1 applies as well, but that is not a necessary explanation.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565