Is Single Responsibility Principle a rule of OOP? [closed] - oop

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
An answer to a Stack Overflow question stated that a particular framework violated a plain and simple OOP rule: Single Responsibility Principle (SRP).
Is the Single Responsibility Principle really a rule of OOP?
My understanding of the definition of Object Orientated Programming is "a paradigm where objects and their behaviour are used to create software". This includes the following techniques: Encapsulation, Polymorphism & Inheritance.
Now don't get me wrong - I believe SRP to be the key to most good OO designs, but I feel there are cases where this principle can and should be broken (just like database normalization rules). I aggressively push the benefits of SRP, and the great majority of my code follows this principle.
But, is it a rule, and thus implies that it shouldn't be broken?

Very few rules, if any, in software development are without exception. Some people think there are no place for goto but they're wrong.
As far as OOP goes, there isn't a single definition of object-orientedness so depending on who you ask you'll get a different set of hard and soft principles, patterns, and practices.
The classic idea of OOP is that messages are sent to otherwise opaque objects and the objects interpret the message with knowledge of their own innards and then perform a function of some sort.
SRP is a software engineering principle that can apply to the role of a class, or a function, or a module. It contributes to the cohesion of something so that it behaves well put together without unrelated bits hanging off of it or having multiple roles that intertwine and complicate things.
Even with just one responsibilty, that can still range from a single function to a group of loosely related functions that are part of a common theme. As long as you're avoiding jury-rigging an element to take the responsibilty of something it wasn't primarily designed for or doing some other ad-hoc thing that dilute the simplicity of an object, then violate whatever principle you want.
But I find that it's easier to get SRP correct then to do something more elaborate that is just as robust.

None of these rules are laws. They are more guidelines and best practices. There are times when it doesn't make sense to follow "the rules" and you need to do what is best for your situation.
Don't be afraid to do what you think is right. You might actually come up with newer and better rules.

To quote Captain Barbossa:
"..And secondly, you must be a pirate for the pirate's code to apply and you're not.
And thirdly, the code is more what you'd call "guidelines" than actual rules...."
To quote Jack Sparrow & Gibbs.
"I thought you were supposed to keep to the code."
Mr. Gibbs: "We figured they were more actual guidelines. "
So clearly Pirates understand this pretty well.
The "rules" could be understood via the patterns movement as "Forces"
So there is a force trying to make the class have a single responsibility. (cohesion)
But there is also a force trying to keep the coupling to other classes down.
As with all design ( not just code) the answer is that it depends.

Ahh, I guess this pertains to an answer I gave. :)
As with most rules and laws, there are underlying motives by which these rules are relevant -- if the underlying motive is not present or applicable to your case, then you are free to bend/break the rules according to your own needs.
That being said, SRP is not a rule of OOP per se, but are considered best practices to create OOP applications that are both easily extensible and unit-testable.
Both are characteristics that I consider as of utmost importance in enterprise application development, where maintenance of existing applications occupies more time than new development does.

As many of the other posters have said, all rules are made to be broken.
That being said, I do think that SRP is one of the more important rules for writing good code. It's not specific to Object Oriented programming, but the "encapsulation" part of OOP is very hard to do right if the class does not have a single responsibility.
After all, how do you correctly and simply encapsulate a class with multiple responsibilities? Usually the answer is multiple interfaces and in many languages that can help quite a bit, but it's still confusing to the users of your class that it may apply in completely different ways in different situations.

SRP is just another expression of ISP :-) .
And the "P" means "principle" , not "rule" :D

Related

How to use Type Classes in Haskell and difference with java interfaces [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I asked this question yesterday and the user #dfeuer advised me, that as a beginner I should not define my own classes. His comment:
Haskell beginners shouldn't define their own classes at all. Learn to define functions, and types, and instances. These are the vast majority of actual Haskell code. As you do this, you'll get a good feel for what makes some classes really useful and others less so. You'll learn what makes some classes easy to use and others full of booby traps. Then when you find a good reason to actually define your own class, you'll go through a slew of bad class designs before you get good enough at it that only most of your attempts go badly. Designing good classes is really hard and rarely necessary.
I am curious, why is defining my own classes usually (for a beginner) a bad idea? What are these "booby traps" and why is it so hard to design good classes?
I thought classes are used to define interfaces to data as I do in OOP. When I write java code, I try to write as much code as possible with abstract classes and especially interfaces, so that when I need to change the data, most of my code remains unchanged and that my methods are highly reusable. Another comment under that question by #Carl suggests, that this is not how classes should be used
Why did you create that class? It feels very weird to me - very much like something that someone used to OOP would do, rather than someone used to Haskell. It has too many parameters, they're connected in what feels like a very ad-hoc manner...
My fear is, that without this OOP use of classes, any change in data would break huge part of code. Is this fear unfunded? And if it is funded, why I should not use classes to define interface to data?
To be fair, I am self taught java programmer and I did not read others people code, so maybe I am doing java wrong also. I only read some books on how the language works and then built an application. I developed it for a year or so, and my whole style is consequence of this experience alone. My style seems to work well for my needs though, and thus I assume it is how java programming/OOP is indeed done.
I'm a relatively a new (and amateur) Haskell enthusiast.
I'd say: just stop thinking you can reuse OOP knowledge, patterns, and other things in Haskell. Even terminology is not "reusable". Classes are not the same thing in OOP languages vs Haskell (well, they are called typeclasses in Haskell, actually).
This is an answer to a question of mine. It starts more or less like this:
It's true that typeclasses can express what interfaces do in OO languages, but this doesn't always make sense.
i.e. stating the inherent difference between two similar (only apparently similar!) concepts in Haskell vs OOP languages.
Another interesting link is on Design Patterns in Haskell. It is very high level, and I still don't quite understand how some tools can be used in Haskell as an alternative to a specific OOP pattern. (Probably the fact that first-class function remove the need for the strategy pattern is the only thing that is totally clear to me, at the moment.) However, I think it is a good reading and, most of all, it should convince you that learning and coding in Haskell comes with a huge mental shift, and it is best approached by starting from zero. If you refuse that, you're not gonna learn Haskell.
I'm not saying that you shouldn't use your brain to notice similarities between OOP languages and Haskell. You should just assume that even trying to build on those observations will handicap your learning process.
As regards Haskell specifically, sitting down and studying LYAH as you were at school (with a laptop to try out examples) is a good way to learn very well the basics. It is an easy-ish to read book, and guides you by hand.
For what is worth, I think that Structure and Interpretation of Computer Programs is a good book that can accompany learning a functional language, as it gives you a practical background to the shift of philosophy I mentioned earlier. You must do the exercises. Doing them will force you towards that mental shift.
A final suggestion, that I would never apply before studying LYAH thoroughly, is to complete The Monad Challenges. But I have to say that LYAH does already a good job at teaching you what the Challenges ask you to think about. I found myself thinking "I already know this", "why is the challenge going so roundabout?".

OOP design of tool for teaching formal languages & automata [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I am thinking of using some spare time to play around with designing and implementing a teaching tool for a course on formal languages and automata theory. I am trying to decide whether an OOP implementation would be appropriate and, if so, whether anyone can suggest high-level improvements to the design I outline below.
There are lots of potential classes revealed in the linguistic analysis. Some (and please let me know if I've missed anything fundamental) are: grammar; nonterminal; terminal; production; regular grammar; context-free grammar; context-sensitive grammar; unrestricted grammar; automaton; state; symbol; transition; DFA; NFA; NFA-Lambda; DPDA; PDA; LBA; Turing machine.
Question 1: Should each kind of grammar get its own class in the implementation, or should an over-arching grammar class have methods to determine what kind of grammar it is (e.g., "isRegular()", "isContextFree()", etc.) (more generally, should classes which differ only a little in the domain model, and only in terms of behavior, be represented via inheritance in the implementation, or is it better to simply push different kinds of behavior into the parent class?)
Question 2: Should things like "Symbol", "State", "Nonterminal", etc. get their own classes in the implementation, or should these be dominated by their containers? (more generally, should very simple classes in the domain model be given their own classes in the implementation - e.g. for extensibility - or should that be pushed into the container class?)
Question 3: Should Transition be its own class in the implementation and, if so, will I need to subclass it in order to support each kind of automaton (since, besides differing in terms of the state, they also differ in terms of what happens during transitions)? (more generally, is it good practice to have two abstract parent classes where there is a bijection between the children of one and the children of another... coupling?)
I realize that, at the end of the day, a lot of these decisions are simply design decisions, but I would like to know what you guys think about best practices in OOP design. Moreover, and the reason I'm not just asking the "more generally" questions as pure OOP design questions is that I'd like special perspective from people who have experience with this kind of domain (languages & automata).
Any help is greatly appreciated.
more generally, should classes which differ only a little in the domain model, and only in terms of behavior, be represented via inheritance in the implementation, ...
Behavior is not "only". Behavior is most important part of objects.
or is it better to simply push different kinds of behavior into the parent class?
Certainly not. That would be violation of Liskov substitution principle.
Inheritance should not be used for "easier access to common stuff".
Content of parent class muss be completely ubiquitous with child classes, avoid inheritance and use composition if child does not comply w/ it.
more generally, should very simple classes in the domain model be given their own classes in the implementation - e.g. for extensibility - or should that be pushed into the container class?
It kind a depends on how "deep" Your logic is going to go.
Usually it's a good idea to start decomposition only when you hit some limits.
Some people call it evolutionary design.
E.g. - I have "class must not be larger than ~200 lines of code", "object must not talk with more than 5-7 other objects", "method should not be larger than ~10 lines of code", "same logic should be written once only" etc...
Also - it's easy to underestimate semantics. if order.isOverdue() is much more easily readable and understandable than if order.dueDate<date.Now(). Introducing classes that reflect concepts of domain greatly "humanizes" code - increases abstraction level (think "asm vs java").
But decomposition for the sake of decomposition leads to unnecessary complexity.
It always must be justified.
Should Transition be its own class in the implementation and, if so, will I need to subclass it in order to support each kind of automaton (since, besides differing in terms of the state, they also differ in terms of what happens during transitions)?
There is nothing wrong with that as long as it complies with Your domain.
Creation of abstractions is artistic activity that highly depends on Your domain (e.g. advises from experts at formal languages & automata might be severely over-complicated if requirement that Your code is supposed to be as a teaching tool for a course is forgotten).
Good Idea. Done similar stuff, first with Procedural programming, first, O.O., later.
Answer 1: Both. Some grammars or tokens will have a specific methods or attributes, while other should be shared among all grammars.
Answer 2: They should have their own classes, altought may share common ancestors.
Answer 3: It can be handled both ways, altought defining a specific class could be useful. I agree that intersection or association between other classes / objects exists, but, they are difficult to model. The "proxy" design pattern is an example of that.
Teaching language design with LEX, Bison, yacc are difficult. I "heard" that ANTLR is a good designing tool for teaching compiler related stuff.
What do you want to do ?
A object oriented parser / scanner ?
There are some already, I have trouble understanding how to use them. Some of them declare new grammars like defining new classes, but, in this case, I find functional programming (syntax) or logical programming (syntax) more suitable for declaring rules.
Visual related tools:
http://www.ust-solutions.com/ultragram.aspx
http://www.sand-stone.com/
http://antlr.org/
http://antlr.org/works/index.html
Good Luck ;-)
If you want to go with an existing solution instead of writing one, some friends of mine at NCSU wrote a tool called ProofChecker that might fit the bill.
It's written in Java, so that might satisfy your OO angle as well.

What is the difference between a software development pattern a methodology(agile, dsdm etc) and a paradigm(specifically object oriented)? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
What is the difference between a software development pattern?
A methodology such as agile DSDM etc how is OO classed as a methodology and a paradigm?
How can OO be applied to a methodology such as agile if itself is a methodology?
Whats the difference between a paradigm and a methodology or a development pattern?
Thanks for any replys.
"When I use a word," Humpty Dumpty
said, in a rather scornful tone, "it
means just what I choose it to mean -
neither more nor less." "The question
is," said Alice, "whether you can make
words mean so many different things."
"The question is," said Humpty Dumpty,
"which is to be master - that's all."
Through the Looking Glass.
Well, not my answer, Lewis Carroll's.
Looking at only one of the questions you asked: "...how is OO classed as a methodology and a paradigm?"
That, at least, has a fairly simple answer:
Object Oriented Design is an analysis methodology.
Object Oriented Programming is an implementation paradigm.
OOD involves analyzing a problem in terms of objects and their interactions. OOP involves implementing a solution as a set of interacting objects.
"Agile" (I hate that name -- though I'll admit "eXtreme Programming" is worse) is really about project management. Just for example, you can apply Pair Programming about equally to something like assembly language or C as to a language that explicitly supports object oriented programming (though being a relatively new idea, it's probably used most often in conjunction with relatively new languages).
Edit: How I'd separate "methodology" from "paradigm" is fairly simple (at least in theory).
Paradigm is really just a fancy word for "example". If I'm following that example to a meaningful degree, the source code (for example) to the program should contain direct, (fairly) clearly defined results from having followed that example. Just for the obvious one, a class publicly derived from another would be a pretty obvious indication of OOP.
A methodology, by contrast, doesn't necessarily show a direct, definable result in the source code. Just for example, there's unlikely to be much in the source code to indicate whether it was developed using "Agile" methodology. I might be able to take a guess if (for example) all the source code files contained comments indicating two authors, but (at best) it would a rather indirect indication of one specific piece of the methodology.
I said in theory, because things can get a bit "fuzzy" at times. If I try hard enough, I can probably write pretty close to pure procedural code, even in a language like Smalltalk that favors objects almost exclusively. Likewise, if I try hard enough I can write OO code in something like C that doesn't really support it. In a case like this, the indications of following the paradigm will usually be harder to find or define than in a more straightforward case.
Methodology is about people. Paradigm is about software.
A paradigm is a way of thinking about a problem - so objects, a relational database, lambda calculus are all models for getting a problem into your head
A methodology is a way of actualy building something based on the paradigm.
If you like, the paradigm is the architect, what are building? should it be a suspension bridge or an arch. The methodology is the engineering, how many cables, how thick, which subcontractors.

Good definition for "coherence" [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
I'm trying to tell someone his code is not "coherent" in the sense that it serves multiple purposes. I don't think I can explain it very well, so I'm looking for a good reference and/or definition.
I think the correct term is cohesion.
In computer programming, cohesion is a measure of how strongly-related and focused the various responsibilities of a software module are. Cohesion is an ordinal type of measurement and is usually expressed as "high cohesion" or "low cohesion" when being discussed.
Modules with high cohesion tend to be preferable because high cohesion is associated with several desirable traits of software including robustness, reliability, reusability, and understandability whereas low cohesion is associated with undesirable traits such as being difficult to maintain, difficult to test, difficult to reuse, and even difficult to understand.
I had Code Complete by Steve McConnell next to my computer (ie the programmers bible) with the page open explaining cohesion so I thought I'd share,
Cohesion arose from structured design
and is usually discussed in the same
context as coupling. Cohesion refers
to how closely all the routines in a
class or all the code in a routine
support a central purpose-how focused
the class is. Classes that contain
strongly related functionality are
described as having strong cohesion,
and the heuristic goal is to make
cohesion as strong as possible.
I use the term “separation of concerns” to explain this while refactoring. Often when code is fairly new, things will get lumped in together as the separate concerns are not clear at first.
One easy way to illustrate this to your co worker would be to ask them to write test cases for the code. This should illustrate that the code is not clear or coherent.
Another good phrase to use is that functions/objects “should do one thing, and do it well”, this has implications in everything from the object/method names to the overall architecture of the system.
In addition to the answers given so far, a simple way to think of high cohesion is lack of duplication of functionality, and clear seperation of related functionality into distinct modules, components or classes. Thus if you want a function similar to another function, and you cut and paste and subsequently modify a copy of the code, you are reducing cohesion. If you modify the the original to handle the new case, where the new case is clearly related to the existing functionality, you are increasing cohesion. Put another way, if your program has to do a given thing, no matter how times or in how many places, for maximum cohesion there should only be once piece of code that does that thing. At the same, a given class, module or component should have a single area of responsibility. Lumping unrelated functionality into a single class or component also reduces cohesion.
As CodeWiki says, cohesion is typically discussed with coupling, where the two can act in opposition to one another, particularly where strict interfaces aren't carefully planned. Many of the googled articles on cohesion relate to OO design, but cohesion and coupling are not restricted to OO.
Marked by an orderly, logical, and aesthetically consistent relation of parts; "a coherent argument" - from http://www.websters-online-dictionary.org/definition/coherent

How do I break my procedural coding habits? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I recently read an interesting comment on an OOP related question in which one user objected to creating a "Manager" class:
Please remove the word manager
from your vocabulary when talking
about class names. The name of the
class should be descriptive of its'
purpose. Manager is just another word
for dumping ground. Any
functionality will fit there. The word
has been the cause of many extremely
bad designs
This comment embodies my struggle to become a good object-oriented developer. I have been doing procedural code for a long time at an organization with only procedural coders. It seems like the main strategy behind the relatively little OO code we produce is to break the problem down into classes that are easily identifiable as discrete units and then put the left over/generalized bits in a "Manager" class.
How can I break my procedural habits (like the Manager class)? Most OO articles/books, etc. use examples of problems that are inherently easy to transform into object groups (e.g., Vehicle -> Car) and thus do not provide much guidance for breaking down more complex systems.
First of all, I'd stop acting like procedural code is wrong. It's the right tool for some jobs. OO is also the right tool for some jobs. So is functional. Each paradigm is just a different point of view of computation, and exists because it's convenient for certain problems, not because it's the only right way to program. In principle, all three paradigms are mathematically equivalent, so use whichever one best maps to the problem domain. IMHO, if using a multiparadigm language it's even ok to blend paradigms within a module if different subproblems are best modeled by different worldviews.
Secondly, I'd read up on design patterns. It's hard to understand OO without some examples of the real-world problems it's good for solving. Head First Design Patterns is a good read, as it answers a lot of the "why" of OO.
Becoming good at OO takes years of practice and study of good OO code, ideally with a mentor. Remember that OO is just one means to an end. That being said, here are some general guidelines that work for me:
Favor composition over inheritance. Read and re-read the first chapter of the GoF book.
Obey the Law of Demeter ("tell, don't ask")
Try to use inheritance only to achieve polymorphism. When you extend one class from another, do so with the idea that you'll be invoking the behavior of that class through a reference to the base class. ALL the public methods of the base class should make sense for the subclass.
Don't get hung up on modeling. Build a working prototype to inform your design.
Embrace refactoring. Read the first few chapters of Fowler's book.
The single responsibility principle helps me break objects into manageable classes that make sense.
Each object should do one thing, and do it well without exposing how it works internally to other objects that need to use it.
A 'manager' class will often:
Interogate something's state
Make a decision based on that state
As an antidote or contrast to that, Object-Oriented design would encourage you to design class APIs where you "tell don't ask" the class itself to do things itself (and to encapsulate its own state): for more about "tell don't ask" see e.g. here and here (and maybe someone else has a better explanation of "tell don't ask" but these are first two articles that Google found for me).
It seems like the main strategy the little OO code we produce is to break the problem down into classes that are easily identifiable as discrete units and then put the left over/generalized bits in a "Manager" class.
That may well be true even at the best of times. Coplien talked about this towards the end of his Advanced C++: Programming Styles and Idioms book: he said that in a system, you tend to have:
Self-contained objects
And, "transactions", which act on other objects
Take, for example, an airplane (and I'm sorry for giving you another vehicular example; I'm paraphrasing him):
The 'objects' might include the ailerons, the rudder, and the thrust
The 'manager' or autpilot would implement various commands or transactions
For example, the "turn right" transaction includes:
flaps.right.up()
flaps.left.down()
rudder.right()
thrust.increase()
So I think it's true that you have transactions, which cut across or use the various relatively-passive 'objects'; in an application, for example, the "whatever" user-command will end up being implemented by (and therefore, invoking) various objects from every layer (e.g. the UI, the middle layer, and the DB layer).
So I think it's true that to a certain extent you will have 'bits left over'; it's a matter of degree though: perhaps you ought to want as much of the code as possible to be self-contained, and encapsulating, and everything ... and the bits left over, which use (or depend on) everything else, should be given/using an API which hides as much as possible and which does as much as possible, and which therefore takes as much responsibility (implementation details) as possible away from the so-called manager.
Unfortunately I've only read of this concept in that one book (Advanced C++) and can't link you to something online for a clearer explanation than this paraphrase of mine.
Reading and then practicing OO principles is what works for me. Head First Object-Oriented Analysis & Design works you through examples to make a solution that is OO and then ways to make the solution better.
You can learn good object-oriented design principles by studying design patterns. Code Complete 2 is a good book to read on the topic. Naturally, the best way to ingrain good programming principles into your mind is to practice them constantly by applying them to your own coding projects.
How can I break my procedural habits (like the Manager class)?
Make a class for what the manager is managing (for example, if you have a ConnectionManager class, make a class for a Connection). Move everything into that class.
The reason "manager" is a poor name in OOP is that one of the core ideas in OOP is that objects should manage themselves.
Don't be afraid to make small classes. Coming from a procedural background, you may think it isn't worth the effort to make a class unless it's a thousand lines of code and is some core concept in your domain. Think smaller. A ten line class is totally valid. Make little classes where you see they make sense (a Date, a MailingAddress) and then work your way up by composing classes out of those.
As you start to partition little pieces of your codebase into classes, the remaining procedural code soup will shrink. In that shrinking pool, you'll start to see other things that can be classes. Continue until the pool is empty.
How many OOP programmers does it take to change a light bulb?
None, the light bulb changes itself.
;)
You can play around with an OO language that has very bad procedural support like Smalltalk. The message sending paradigm will force you into OO thinking.
i think you should start it with a good plan.
planning using CLASS Diagrams would be a good start.
you should identify the ENTITIES needed in the applicaiton,
then define each entitie's ATTRIBUTES, and METHODS.
if there are repeated ones, you could now re-define your entities
in a way that inheritance could be done, to avoid redundancy.
:D.
I have a three step process, this is one that I have gone through successfully myself. Later I met an ex-teacher turned programmer (now very experienced) who explained to me exactly why this method worked so well, there's some psychology involved but it's essentially all about maintaining control and confidence as you learn. Here it is:
Learn what test driven development (TDD) is. You can comfortably do this with procedural code so you don't need to start working with objects yet if you don't want to. The second step depends on this.
Pick up a copy of Refactoring: Improving the Design of Existing Code by Martin Fowler. It's essentially a catalogue of little changes that you can make to existing code. You can't refactor properly without tests though. What this allows you to do is to mess with the code without worrying that everything will break. Tests and refactoring take away the paranoia and sense that you don't know what will happen, which is incredibly liberating. You left to basically play around. As you get more confident with that start exploring mocks for testing the interactions between objects.
Now comes the big that most people, mistakenly start with, it's good stuff but it should really come third. At this point you can should reading about design patterns, code smells (that's a good one to Google) and object oriented design principles. Also learn about user stories or use cases as these give you good initial candidate classes when writing new applications, which is a good solution to the "where do I start?" problem when writing apps.
And that's it! Proven goodness! Let me know how it goes.
My eureka moment for understanding object-oriented design was when I read Eric Evans' book "Domain-Driven Design: Tackling Complexity in the Heart of Software". Or the "Domain Driven Design Quickly" mini-book (which is available online as a free PDF) if you are cheap or impatient. :)
Any time you have a "Manager" class or any static singleton instances, you are probably building a procedural design.