Encapsulation Principle - oop

There's some object-oriented engineering principle that states something along the lines of "a class should only know about the contracts of the classes that it takes as arguments, or any internal ones it uses."
The counter-example, in C++, is:
Foo::bar( Baz* baz)
{
baz()->blargh()->pants()->soil(); // this is bad, Foo knows about blarghs and pants
}
Does this principle have a name? Also, the actual principle rather than my paraphrase above would be nice to see.

The law of demeter thanks to Jim Burger says:
The Law of Demeter (LoD), or Principle of Least Knowledge, is a design guideline for developing software, particularly object-oriented programs. The guideline was invented at Northeastern University towards the end of 1987, and can be succinctly summarized as “Only talk to your immediate friends.” The fundamental notion is that a given object should assume as little as possible about the structure or properties of anything else (including its subcomponents).

That may or may not compile (due to the parentheses after the baz pointer), but your example breaks at least one principle that I can think of. It breaks the Law of Demeter (also called the Law of Parsimony, I believe). The main principles can be found here:
S.O.L.I.D. Principles
Aside from these, I'm not sure if there is a specific name for what you're describing. You can look up the Law of Demeter on wikipedia.

Look at Robert Martin's SOLID principles. Specifically, look at the Single responsibility Principle. The complex chain of dependencies in your example looks like it breaks the SRP.
Encapsulation -- itself -- isn't a principle. It's part of achieving the various principles. Along with inheritance, polymorphism and other more obscure OO features.

I would say here that good encapsulation helps to reduce coupling - - which is a good goal for any decent encapsulation apart from the obvious.

Related

Misunderstanding of a sentence in "UML Reference Manual" book (Booch, Rumbaugh, Jacobson)

Recently, i go back to read some parts of the "UML Reference Manual" book, second edition (obviously by: Booch, Rumbaugh, Jacobson).
(see: http://www.amazon.com/Unified-Modeling-Language-Reference-Manual/dp/020130998X)
Meanwhile, i have found these "strange" words in the first chapiter "UML overview" at "Complexity of UML" section:
There is far too much use of generalization at the expense of essential distinctions. The myth that inheritance is always good has been a curse of object orientation from earliest days.
I can't see how this sentence can be fully in line with Object Oriented Paradigm which states that inheritance is a fundamental principle.
Any idea/help please?
You seem to believe the two points are mutually exclusive. They are not. Inheritance is a fundamental and powerful principle of object-oriented programming, and it is overused.
It is overused typically by inexperienced developers who are so captivated with the idea of inheritance that they are more focused on the inheritance tree than solving the problem. They try to factor out as much code as possible to some parent base class so they can just reuse it throughout the tree, and as a result they have a brittle design.
One of the greatest evils of software engineering is tight coupling between classes. That's the sort of thing that causes you to have to work through the weekend after the customer asks for a simple change. Why? Because making a change in one class has an effect on another class, and fixing that class has an effect on another, and so on.
Well, there is no tighter coupling than inheritance.
When you factor too much out to the "top level," every derived class is coupled to it. And as you find more and more code you want to factor out to various levels, you eventually have these deep trees, and every change made at the top cascades throughout the tree. As a result, you start to have methods that return null or are empty. They're unnecessary for the class, but the inheritance contract demands they be there. This violates the Liskov Substitution Principle.
So use inheritance of course. But do it smartly. Favor delegation to inheritance if you have any doubt. And when you do use inheritance, make sure you aren't factoring commonalities to the top level (of the whole tree or a subtree) just to reuse common code, but rather do so because there is a commonality of behavior from top to bottom.
If your tree is more than two or three levels deep (and I think three is really pushing it), you are almost certainly setting yourself up for trouble.
Everything is good in moderation. Remember that the quote is not saying do not use it, or avoid, etc. Rather it is saying it is an overused principal when other OO abstractions or principals work better. Inheritance is powerful but it's coupling is tight.
Wisely or rather randomly the author of the UML book is saying pointing out this current truism that inheritance is often over-used and over-referenced. What about all the other principals and abstractions. I find that developers typically only hit the OO highlights (inheritance being one) and use that abstraction to excess.
For me in UML it is a good reminder that UML is OO generally, but it is not limited to Java or .Net OO features. Many languages only offer of the abstractions available across all languages. UML attempts to help you model and express many of them.
Remember the author only said 'too much use', not bad or incorrect. Also remember that maybe you are an expert developer who does not apply inheritance incorrectly.

OOP, class/objects overkill

What is a good gauge for knowing when a class is poorly designed or even necessary. In other words when to write a class and when no to.
SOLID might help if a class is poorly designed, but it won't help answer a question like "Is object-oriented programming the best approach for this problem?"
People have done a lot of very good work in programming for mathematics and science before object-oriented programming came into vogue. If your problem falls into those categories, perhaps object-oriented programming isn't for you.
Objects are state and behavior together; they tend to map onto problem domain objects one-to-one. If that's not true for your problem, perhaps object-oriented programming isn't for you.
If you don't know an object-oriented language well, perhaps object-oriented programming isn't for you.
If your organization doesn't know and can't support object-oriented solutions, perhaps object-oriented programming isn't for you.
A lot of people will say the "SOLID Principles" are a good guideline for class design.
There are a lot of articles/podcasts concerning the SOLID Principles, just do a quick search. Here's a good start:
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
rather than list a bunch of don't-do-this rules for recognizing a poorly-designed class, it is easier - and more efficient - to list the few rules governing a good class design:
a class is a collection of related state and behavior
the behavior should use only the state and method parameters
if you think about the state as a relation (i.e. as the columns in a relational database table), the object ID (pointer) is the primary (synthetic) key and the state comprises the non-key attributes. Is the object in third normal form? If not, split it into two or more objects.
is the lifecycle of the object complete? In other words, do you have enough methods to take the object from creation through use and finally to destruction/disposal? If not, what methods (or states/transitions) are missing?
is all of the state used by at least one method? If not, does it provide descriptive information useful to a user of the object? If the answer to both of these is no, then get rid of the extraneous state.
if the problem you're trying to solve requires no state, you don't need an object.
On top of the SOLID principles, have a look at Code Smells. They were mentioned first (IIRC) in Martin Fowler's "Refactoring" book, which is an excellent read.
Code smells generally apply to OO and also procedural development to some degree, including things like "Shotgun Surgery" where edits are required all over the codebase to change one small thing, or "Switch Case Smell" where giant switch cases control the flow of your app.
The best thing about Refactoring (book) is that it recommends ways to fix code smells and takes a pragmatic view about them - they are just like real smells - you can live with some of them, but not with others.

Main concepts in OOP

I was once asked in an interview 'What are the 3 main concepts of OOP?'.
I answered by saying that in my opinion there were 4 which are as follows:
Inheritance
Encapsulation
Abstraction
Polymorphism
Was I correct?
There are 3 requirements for a language to be object-oriented:
a language that supports only encapsulation (objects) is not object-oriented, but it is modular
a language that supports just encapsulation (objects) and message-passing (polymorphism) is not object-oriented, but it is object-based
a language that supports encapsulation (objects), message-passing (polymorphism), and inheritance (abstraction), is object-oriented
NOTE: Abstraction is a much more general concept; encapsulation et al are kinds of abstraction, just as a subroutine is a kind of abstraction. See Abstraction
I would say that abstraction is not solely an OOP concept, in that you can abstract to a large degree in many non-OOP languages.
The four pillars are as your correctly state
Encapsulation.
Abstraction
Inheritance
Polymorphism
Encapsulation deals with containing data, nothing more, nothing less.
Abstraction deals with data abstraction, i.e. is all this data really relevant. Think of a bank which contains information on name, age, address, eye colour, favourite tie, etc. Are eye colour and favourite tie really that relevant to the banks requirements? No. This is abstraction.
Inheritance deals with generalisation. Information which can apply to more than one thing. If something inherits from something then it can be said to be a more specific type of that thing. For example, Animal. A Dog is a type of Animal, so Dog inherits from Animal. Jack Russell is a type of Dog, so Jack Russell inherits from Dog.
Polymorphism deals with things having multiple forms, (poly - morph).
Two kinds in programming,
Late Binding,
You refer to something as it's general type and hence the compiler does not know what to bind at compile time. Think method Overriding.
Early Binding
You redefine a method using a different signature, i.e.
int add(int a, int b) vs double add(double a, double b)
These are essentially the basic principles of Object Orientation. There is a lot of overlap between these and so it is quite important to achieve a clear understanding of what each of these mean.
The problem with OOP is that nobody bothered to give a proper, concise, agreed-upon definition. Especially, I'd like to point out that all the aspects you mentioned can well be put into action without the use of object orientation!
Two type systems that do this are the Haskell type system, which, by consense, is generally not regarded to be object-oriented, and C++ templates with template subclassing. However, it could perhaps be argued that template subclassing emulates OOP.
Since template subclassing is not a widely known mechanism, let me give an example from the SeqAn library where it was invented.
String<Char> cstr = "This is a test";
String<Dna, Packed<> > dstr = "GATTACA";
cout << "length(" << cstr << ") = " << length(cstr) << endl;
cout << "length(" << dstr << ") = " << length(dstr) << endl;
Here, String<Char> and String<Dna, Packed<> > are inherited of the “abstract class” String<>. They encapsulate the concept of a string, using completely different methods. They share the polymorphic length method, implemented differently for both concrete types.
Those are the Four Horsemen as I know them. Maybe they mistakenly lump Inheritance and Polymorphism together.
Yes, those are the standard four.
Some people combine abstraction and encapsulation. I'm not sure why... they're not completely orthogonal, but maybe there's enough overlap? There's certainly overlap between inheritance and polymorphism, but it would be hard to combine them, in my mind.
Most people would consider that correct, my guess is if they were asking for three it would be Inheritance, Encapsulation and Polymorphism.
I personally find that those three concepts are the real "meat" if you will behind the definition of OOP. And most people take abstraction for granted and lum it in with the others, as really it could be considered part of any of the other three.
When I talk about OOP though I always mention the 4.
Probably the last three is what they were looking for - inheritance could be argued to be more of a mechanism to help achieve the others, which are higher level goals.
There is not really a correct answer anyway, especially if limited to 'top 3'.
That's correct.
If you had to provide only one, however, Abstraction it's got to be, for, one way or the other, the rest three is merely Abstraction in action.
3 main concepts in OOP:
Late binding
Concept reusing (not sure about this, anyway: re-using of concepts; avoiding the re-implementation of even the simplest concepts)
Abstraction
A proper answer to the question is: "Please clarify what you mean by Object-Oriented Programming." Oops, that would be telling, because the real question being asked is: "When I say OOP, what do I mean?"
There's no correct answer.
OOP
Abstraction (ignoring or hiding details that don't matter) - the situation in which a subject is very general and not based on real situations.
Encapsulation - Keeping properties and methods private onside the class, so they not accessible from outside the class.
! API - is essentially all the methods that are not private, not encapsulated.
Inheritance - Making all properties and methods of a certain class available to child class.
Polymorphism-gr: "many shapes" - a child class can overwrite a method it inherited from a parent class.
This [article][1] refers to the three pillars of good code. I found it to be an excellent article positing that encapsulation is the "first principle" of object-oriented design.
"First" principles are fundamental, underlying principles from which all else springs. The author uses the example of the Golden Rule. It's difficult to teach children all the finer points of civilized behavior but if you can get them to understand (and more importantly, practice) the Golden Rule of treating others as you would like to be treated, then they are more likely to "get" all the legal and moral standards we're held to on a daily basis.
So, it follows that if a developer understands encapsulation as a "First Principle" of object-oriented development, all of the other principles will follow in due course.
I don't do the author's content justice but I would definitely encourage people to read it.
For some reason I'm not showing the hyperlink as coming through so here's the URL: http://www.netobjectives.com/files/Encapsulation_First_Principle_Object_Oriented_Design.pdf
It could have been a trick question for the interview, but in Computer Science classes these days they teach the 4 Pillars of Object Oriented Programming.
It's generally believed that those are the main principles however they had very little to do with why OO was created.
One of the guiding principles was the direct manipulation metaphor. That is creating an object in the program that represented an object from the users mental model. Most of the motivation for creating OO was based in psychology not math/CS as is often believe to be the case these days.
If doubtfull of this take a look at some of the work by Trygve Renskauge. Father of MVC and DCI or James Coplien accomplish author and speaker.
So I'd say you likely gave them an answer close to what they expected whether it's correct depends on where you stand.

Are there any rules for OOP?

Recently I heard that there are 9 rules for OOP(Java). I know only four as Abstraction, Polymorphism, Inheritance and Encapsulation. Are there any more rules for OOP?
Seems like what you're looking for are the Principles of Object-Oriented Design.
Summarized from Agile Software Development Principles, Patterns, and Practices. These principles are the hard-won product of decades of experience in software engineering. They are not the product of a single mind, but they represent the integration and writings of a large number of software developers and researchers. Although they are presented here as principles of object-oriented design, they are really special cases of long-standing principles of software engineering.
SRP The Single Responsibility Principle A class should have only one reason to change.
OCP The Open-Closed Principle Software entities (classes, packages, methods, etc.) should be open for extension, but closed for modification.
LSP The Liskov Substition Principle Subtypes must be substitutable for their base types.
DIP The Dependency Inversion Principle Abstractions should not depend upon details. Details should depend upons abstractions.
ISP The Interface Segregation Principle
Clients shold not be forced to depend upon methods that they do not use. Interfaces belong to clients, not to hierarchies.
REP The Release-Reuse Equivalency Principle
The granule of reuse is the granule of release.
CCP The Common Closure Principle
The classes in a package should be closed together against the same kinds of changes. A change that affects a closed package affects all the classes in that package and no other packages.
CRP The Common Reuse Principle
The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all.
ADP The Acylcic Dependencies Principle
Allow no cycles in the dependency graph.
SDP The Stable Dependencies Principle
Depend in the direction of stability.
SAP The Stable Abstractions Principle
A package should be as abstract as it is stable.
Not sure about any rules. All these mentioned things are more like OO paradigms to me. There are few advices we follow like,
Separation of Concern
Single Responsibility per Class
Prefer Composition over Inheritance
Programming to Interface
Plus all mentioned by Billybob, already
These OO principles are straight from Head First Design Patterns:
Encapsulate what Varies
Program to an Interface, rather than an Implementation
Favour Composition over Inheritance
A Class should have only one reason to Change (Single Responsibility Principle)
Sub-Types must be substitutable for their Base (Liskov Substitition Principle)
Classes shoule be Open for extension, but Closed for Modification (Open-Closed Principle)
These are concepts, not rules. There are no rules really, just decisions to make, some designs are better than others, some much better than others :-)
There are plenty of guidelines though :-) Some are language specific (C++ is riddled with them) others are OO specific. Too many to list though :-)
Off the top of my head, important ones are:
Loose coupling, high cohesion
Write testable classes, which you test
Use inheritence sparingly and only where it makes sense (prefer composition)
Try stick to the open/close principle.
(most important) KISS
Plenty to expand upon and add :-)
EDIT: I should add, the rules which you listed are not unique to OO
According to the Pragmatic Programmers - the rules are:
Keep it DRY (Don't Repeat Yourself)
Keep it SHY (Ensure that your classes have high cohesion and low coupling)
and tell the other GUY (Separation of concerns)
http://media.pragprog.com/articles/may_04_oo1.pdf
There are no "Rules" to OOP.
There are 4 language properties that make a language object-oriented or not (these are the things you listed in your question).
The rest of the material out there are guidelines. The best/most helpful guidelines I've read are GRASP
Many of the suggestions are not readily understandable by laymen (non-CS majors). I thought GRASP was pragmatic and approachable.
I think GRASP is nice because it suggests the most critical part of OO in its name - Assignment of Responsibility (to objects not programmers).
The two most critical GRASP concepts from which everything else derives are coupling and cohesion. These two concepts/principals drive all other patterns and approaches.
BTW - did I just interview you? You transcribed the question incorrectly...

Coupling, Cohesion and the Law of Demeter

The Law of Demeter indicates that you should only speak to objects that you know about directly. That is, do not perform method chaining to talk to other objects. When you do so, you are establishing improper linkages with the intermediary objects, inappropriately coupling your code to other code.
That's bad.
The solution would be for the class you do know about to essentially expose simple wrappers that delegate the responsibility to the object it has the relationship with.
That's good.
But, that seems to result in the class having low cohesion. No longer is it simply responsible for precisely what it does, but it also has the delegates that in a sense, making the code less cohesive by duplicating portions of the interface of its related object.
That's bad.
Does it really result in lowering cohesion? Is it the lesser of two evils?
Is this one of those gray areas of development, where you can debate where the line is, or are there strong, principled ways of making a decision of where to draw the line and what criteria you can use to make that decision?
Grady Booch in "Object Oriented Analysis and Design":
"The idea of cohesion also comes from structured design. Simply stated, cohesion
measures the degree of connectivity among the elements of a single module (and
for object-oriented design, a single class or object). The least desirable form of
cohesion is coincidental cohesion, in which entirely unrelated abstractions are
thrown into the same class or module. For example, consider a class comprising
the abstractions of dogs and spacecraft, whose behaviors are quite unrelated. The
most desirable form of cohesion is functional cohesion, in which the elements of
a class or module all work together to provide some well-bounded behavior.
Thus, the class Dog is functionally cohesive if its semantics embrace the behavior
of a dog, the whole dog, and nothing but the dog."
Subsitute Dog with Customer in the above and it might be a bit clearer. So the goal is really just to aim for functional cohesion and to move away from coincidental cohesion as much as possible. Depending on your abstractions, this may be simple or could require some refactoring.
Note cohesion applies just as much to a "module" than to a single class, ie a group of classes working together. So in this case the Customer and Order classes still have decent cohesion because they have this strong relationshhip, customers create orders, orders belong to customers.
Martin Fowler says he'd be more comfortable calling it the "Suggestion of Demeter" (see the article Mocks aren't stubs):
"Mockist testers do talk more about avoiding 'train wrecks' - method chains of style of getThis().getThat().getTheOther(). Avoiding method chains is also known as following the Law of Demeter. While method chains are a smell, the opposite problem of middle men objects bloated with forwarding methods is also a smell. (I've always felt I'd be more comfortable with the Law of Demeter if it were called the Suggestion of Demeter .)"
That sums up nicely where I'm coming from: it is perfectly acceptable and often necessary to have a lower level of cohesion than the strict adherence to the "law" might require. Avoid coincidental cohesion and aim for functional cohesion, but don't get hung up on tweaking where needed to fit in more naturally with your design abstraction.
If you are violating the Law of Demeter by having
int price = customer.getOrder().getPrice();
the solution is not to create a getOrderPrice() and transform the code into
int price = customer.getOrderPrice();
but instead to note that this is a code smell and make the relevant changes that hopefully both increase cohesion and lower coupling. Unfortunately there is no simple refactoring here that always applies, but you should probably apply tell don't ask
I think you may have misunderstood what cohesion means. A class that is implemented in terms of several other classes does not necessarily have low cohesion, as long as it represents a clear concept, and has a clear purpose. For example, you may have a class Person, which is implemented in terms of classes Date (for date of birth), Address, and Education (a list of schools the person went to). You may provide wrappers in Person for getting the year of birth, the last school the person went to, or the state where he lives, to avoid exposing the fact that Person is implemented in terms of those other classes. This would reduce coupling, but it would make Person no less cohesive.
It’s a grey area.
These principals are meant to help you in your work, if you find you’re working for them (i.e. they’re getting in your way and/or you find it over complicates your code) then you’re conforming too hard and you need to back off.
Make it work for you, don’t work for it.
I don't know if this actually lowers cohesion.
Aggregation/composition are all about a class utilising other classes to meet the contract it exposes through its public methods.
The class does not need to duplicate the interface of it's related objects. It's actually hiding any knwowledge about these aggregated classes from the method caller.
To obey the law of Demeter in the case of multiple levels of class dependency, you just need to apply aggregation/composition and good encapsulation at each level.
In other words each class has one or more dependencies on other classes, however these are only ever dependencies on the referenced class and not on any objects returned from properies/methods.
In the situations where there seems to be a tradeoff between coupling and cohesion, I'd probably ask myself "if somebody else had already written this logic, and I were looking for a bug in it, where would I look first?", and write the code that way.