I am supposed to write two versions of the same code. One with low coupling and high cohesion and another still with low coupling but this time with low cohesion. I don't really understand what the difference is? How can I have low coupling and low cohesion? They seem so related that this is impossible to do.
Can someone explain this? Perhaps with an example?
Thanks!
In short:
Cohesion in software engineering, as in real life, is how much the elements consisting a whole(in our case let's say a class) can be said that they actually belong together. Thus, it is a measure of how strongly related each piece of functionality expressed by the source code of a software module is.
One way of looking at cohesion in terms of OO is if the methods in the class are using any of the private attributes.
Now the discussion is bigger than this but High Cohesion (or the cohesion's best type - the functional cohesion) is when parts of a module are grouped because they all contribute to a single well-defined task of the module.
Coupling in simple words, is how much one component (again, imagine a class, although not necessarily) knows about the inner workings or inner elements of another one, i.e. how much knowledge it has of the other component.
Loose coupling is a method of interconnecting the components in a system or network so that those components, depend on each other to the least extent practically possible…
In long:
I wrote a blog post about this. It discusses all this in much detail, with examples etc. It also explains the benefits of why you should follow these principles. I think it could help...
Coupling and cohesion are two different measures of software modules.
Coupling is a description of how two classes interact. If two classes are interdependent on each other, they exhibit tight coupling; if two classes can be used independently of one another, they exhibit loose coupling. Loose coupling is preferred, as it lends itself to reusable components and high maintainability.
Cohesion is a description of how the components of a single class belong together. A class containing methods that have nothing to do with each other exhibits low cohesion; a class containing methods that are logically similar exhibits high cohesion. High cohesion leads to focused classes that serve a well-defined purpose.
The relationship between coupling and cohesion is symbiotic. If two classes are tightly coupled, then there's a high probability that they don't have clear responsibilities and therefore will exhibit low cohesion. Conversely, if a class is highly cohesive, its purpose is well-defined and it is easier to use with other classes in a way that avoids coupling to them.
For your particular assignment, start by writing "good" code - low coupling and high cohesion. To morph that into something with low coupling and low cohesion, keep the classes independent of one another but shuffle the functionality around. Create a Utility class with a whole bunch of unrelated methods. Put all of the methods that start with a vowel into another class. Do something that prevents any class from having a well-defined purpose.
As long as you keep the classes from depending on each other, you're creating code that exhibits low coupling but also has low cohesion.
Cohesion and coupling are properties of how you organize your items.
Let's take a physical example. Now suppose you had a baseball, tennis ball, cricket ball, croquet ball, lacrosse ball, and a billiard ball. Suppose you also had a baseball bat, tennis racquet, cricket bat, croquet mallet, lacrosse stick, and a pool cue. If you were to randomly sort these twelve objects into six bagged pairs of objects, you would probably have an organization with low coupling and low cohesion. To be concrete, let's say the six bags contained:
baseball, pool cue
lacrosse ball, tennis racquet
billiard ball, cricket bat
tennis ball, baseball bat
croquet ball, lacrosse stick
cricket ball, croquet mallet
This organization has low cohesion because the objects in each bag are unrelated. This organization has moderate coupling because the density of relationships between the content of different bags is medium (but spaghetti-like) -- six links (one for each sport ball-bat pair) of a possible 21. If you wanted an example of even lower coupling you could start with a higher number of pairs of sports objects
The obvious organization of the objects into bags of
baseball, baseball bat
tennis ball, tennis racquet
cricket ball, cricket bat
croquet ball, croquet mallet
lacrosse ball, lacrosse stick
billiard ball, pool cue
has even lower coupling (zero coupling) because none of the bag contents are related to the content of other bags. It has high cohesion because the contents within a bag are related to each other.
Coupling and Cohesion are somehow two close concepts but are not the same. Your design should have:
Low Coupling: It means your classes should not be dependent on other classes (esp. concrete classes) too much. You must decouple them as much as possible. Decoupling helps reusability ( the goal of OO software engineering). Because when you reuse such classes, you don't need to bring any other class with your class to make it work. Many design patterns such as Facade fulfill this goal.
High Cohesion: It means your class should not include many unrelated tasks. When you increase cohesion, code comprehension becomes easier since the class is doing some coherent tasks. This also increases reusability. Some design patterns such as Visitor have this goal.
In continue, I give 3 class example that may make more sense :
#include <Document>
#include <Printer>
#include <SpellCheker>
class HighCoupling{
// This class need other class to be usable
Document *doc;
Printer *activePrinter;
CretaeDocument() { /*...*/ }
SaveDocument() { /*...*/ }
PrintDocument() { /*...*/ }
CheckSpell() { /*...*/ }
};
#include <Document>
class LowCouplingHighCohesion {
// This class don't need other classes
// This class is a specialist on some task
CretaeDocument() { /*...*/ }
SaveDocument(Format *) { /*...*/ }
LoadDocument() { /*...*/ }
};
#include <Document>
class LowCouplingLowCohesion {
// This class don't need other classes
// This class do many unrelated things
CretaeDocument() { /*...*/ }
SaveDocument() { /*...*/ }
OpenDocument() { /*...*/ }
Undo() { /*...*/ }
ChangeDocumentBackground() { /*...*/ }
SearchInDocument() { /*...*/ }
};
Say for example that you have two classes which will only work if both classes are there. The similarity of functionality within a class is called cohesion, how things belong together, but how they interact is called coupling.
So if you write a program that has low coupling and high cohesion it means that the classes of the program are easy to use and reuse and that the internals of the class belong together. So the classes are filled with methods that show similarity.
In this manner it is rather easy to change a part of a program without having to change your entire code on multiple places. So coupling in general is the term that describes how easy or hard it is to implement and cohesion is used to measure the similarity between methods in a class. So if you want to build something with low coupling and low cohesion, you would have to build something that is easy to implement into a program, but messes up the encapsulation.
The difference is in the meaning.
Coupling is referred to something that has a negative meaning. So, according to SOLID rules you have to try to build your application in such way, that it is Loosely Coupled.
For example, Gof patterns (e.g., Abstract Factory) and DI containers (such as MS Unity or NInject in .NET world) can help you to achieve this.
Loosely Coupled code means that if you need to insert new class into your application (or, let's say in this way - if you need to change one class to another), then you can do it easily without big efforts.
Cohesion is referred to something that has a positive meaning. So, as you probably guessed, you have to try to build your application in such way, that it will implement High Cohesion. What does it mean? It is referred to interaction between different modules of your application.
For example, let's assume that your app has two modules:
Export module - exports some data into an xml file
Import module - imports some data from an xml file
If the Import module can successfully import almost everything that is exported by the Export module, then it means that you set up a good interaction between them and a cohesion between them is high.
Related
What exactly is abstraction whether it is hiding unwanted information or the entire implementation.
Two examples
.hpp
class {
int do_something();
}
by not exposing the actual code inside it.
or like calling more private functions and just exposing the outer function.
int do_something() {
do_something_private();
do_some_otherthing_private();
}
In simple words abstraction is data hiding. We don't want the end user to know what's an integer indexNo or float serialId so we just encapsulate it with a class and give it as a simple variable name like student.rollNumber or employee.empId.
Abstraction is a means of hiding details in order to simplify an interface.
So, using a car as an example, all of the controls in a car are abstractions. This allows you to operate a vehicle without understanding the underlying details of the steering, acceleration, or deceleration systems.
A good abstraction is one that standardizes an interface broadly, across multiple instances of a similar problem. A great abstraction can change an industry.
The modern steering wheel, brake pedal, and gas pedal are all examples of great abstractions. Car steering initially looked more like bicycle steering. And both brakes and throttles were operated by hand. But the abstractions we use today were so powerful, they swept the industry.
Refer to this thread for more detail :-link
I have problems understanding the statement low in coupling and high in cohesion. I have googled and read a lot about this, but still finding it hard to understand.
To what I understand is High cohesion means, that we should have classes that are specialized to perform a particular function. Hope this is correct? Like a credit card validation class, which is specialized to validate credit cards only.
And still don't understand what low Coupling means?
What I believe is this:
Cohesion refers to the degree to which the elements of a module/class belong together, it is suggested that the related code should be close to each other, so we should strive for high cohesion and bind all related code together as close as possible. It has to do with the elements within the module/class.
Coupling refers to the degree to which the different modules/classes depend on each other, it is suggested that all modules should be independent as far as possible, that's why low coupling. It has to do with the elements among different modules/classes.
To visualize the whole picture will be helpful:
The screenshot was taken from Coursera.
Cohesion in software engineering, as in real life, is how much the elements consisting a whole(in our case let's say a class) can be said that they actually belong together. Thus, it is a measure of how strongly related each piece of functionality expressed by the source code of a software module is.
One way of looking at cohesion in terms of OO is if the methods in the class are using any of the private attributes.
Now the discussion is bigger than this but High Cohesion (or the cohesion's best type - the functional cohesion) is when parts of a module are grouped because they all contribute to a single well-defined task of the module.
Coupling in simple words, is how much one component (again, imagine a class, although not necessarily) knows about the inner workings or inner elements of another one, i.e. how much knowledge it has of the other component.
Loose coupling is a method of interconnecting the components in a system or network so that those components, depend on each other to the least extent practically possible…
I wrote a blog post about this. It discusses all this in much detail, with examples etc. It also explains the benefits of why you should follow these principles.
In software design high cohesion means that class should do one thing and one thing very well. High cohesion is closely related to Single responsibility principle.
Low coupling suggest that class should have least possible dependencies. Also, dependencies that must exist should be weak dependencies - prefer dependency on interface rather than dependency on concrete class, or prefer composition over inheritance .
High Cohesion and low coupling give us better designed code that is easier to maintain.
Short and clear answer
High cohesion: Elements within one class/module should functionally belong together and do one particular thing.
Loose coupling: Among different classes/modules should be minimal dependency.
Low coupling is in the context of two or many modules. If a change in one module results in many changes in other module then they are said to be highly coupled. This is where interface based programming helps. Any change within the module will not impact the other module as the interface (the mean of interaction ) between them has not changed.
High cohesion- Put the similar things together. So a class should have method or behaviors to do related job. Just to give an exaggerated bad example: An implementation of List interface should not have operation related to String. String class should have methods, fields which is relevant for String and similarly, the implementation of List should have corresponding things.
Hope that helps.
Cohesion - how closely related everything is with one another.
Coupling - how everything is connected to one another.
Let's take an example - We want to design a self-driving car.
(1) We need the motor to run properly.
(2) We need the car to drive on its own.
All of the classes and functions in (1) starting the motor and making it run work great together, but do not help the car steer. So we place those classes behind an Engine Controller.
All of the classes and functions in (2) work great to make the car steer, accelerate and brake. They do not help the car start or send gasoline to the pistons. So we place these classes behind its own Driving Controller.
These controllers are used to communicate with all of the classes and functions that are available. The controllers then communicate only with each other. This means I can't call a function in the piston class from the gas pedal class to make the car go faster.
The pedal class has to ask the Driving Controller to talk to the Engine Controller which then tells the piston class to go faster. This allows us programmers to be able to find issues and allows us to combine large programs without worrying. This is because the code was all working behind the controller.
Take the example of an old PC motherboard.
Mouse had its own PS/2 port.
Printer had its own Printer port.
Monitor had its own VGA port.
This meant that a particular port was meant only for a particular device, and for none other.
This is Strong / High Coupling
Since a mouse is used only for operating the cursor and related functionalities, a keyboard for typing keys, etc i.e they perform only the task they are intended for, this is High Cohesion
If a mouse had a few buttons 'a' 'b' 'c' to enter, then it is doing more than what it should, since a keyboard is already performing them, this is Low Cohesion
The outdated usage of exclusive ports was thankfully replaced by a standard (interface) we call USB. This is Loose / Low Coupling
Looking at these physical attributes, it looks obvious that this is how it is supposed to be, but while writing software it is very easy to lose track of what functionality is to be put where, etc. and hence as a reminder, in everything in life, always stick to:
'High Cohesion and Loose Coupling'
Metaphorically, if your cat barks, it has poor cohesion, and if your dog needs a cat by his side to bark, it is highly coupled.
"Dogs bark and cats purr, if they barf your pull request will be rejected"
Long story short, low coupling as I understood it meant components can be swapped out without affecting the proper functioning of a system. Basicaly modulize your system into functioning components that can be updated individually without breaking the system
Do you have a smart phone? Is there one big app or lots of little ones? Does one app reply upon another? Can you use one app while installing, updating, and/or uninstalling another? That each app is self-contained is high cohesion. That each app is independent of the others is low coupling. DevOps favours this architecture because it means you can do discrete continuous deployment without disrupting the system entire.
When I was reading about a microservice. I came across the following things:
Cohesion is a measure of the number of relationships that parts of a component have with each other. High cohesion means that all of the parts that are needed to deliver the component's functionality are included in the component
Coupling is a measure of the number of relationships that one component has with other components in the system. Low coupling means that components do not have many relationships with other components
Inheritance or generalization is an example of high coupling (i.e. high interdependence). What I meant by this is that in inheritance often the parent class defines base functionalities that is used by its child class and change in methods of parent class directly impact its child classes. Hence we can say that there is a greater degree of interdependence between classes.
Realization or using interface is an example of high cohesion (i.e. low interdependence). What this means is that an interface put forward a contract for any class that implements it but each class has the right to implement methods declared in interface in its own way and changes in method declared in one class doesn't affect any other class.
Low Coupling:--
Will keep it very simple.
If you change your module how does it impact other modules.
Example:-
If your service API is exposed as JAR, any change to method signature will break calling API (High/Tight coupling).
If your module and other module communicate via async messages. As long as you get messages, your method change signature will be local to your module (Low coupling).
Off-course if there is change in message format, calling client will need to make some change.
Low Coupling and High Cohesion is a recommended phenomenon.
Coupling means to what extent various modules are interdependent and how the other modules are affected on changing some/considerable functionality of a module. Low coupling is emphasized as the dependency has to be maintained low so that very least/negligible changes are made to other modules.
An example might be helpful. Imagine a system which generates data and puts it into a data store, either a file on disk or a database.
High Cohesion can be achieved by separate the data store code from the data production code. (and in fact separating the disk storage from the database storage).
Low Coupling can be achieved by making sure that the data production doesn't have any unnecessary knowledge of the data store (e.g. doesn't ask the data store about filenames or db connections).
Here is an answer from a bit of an abstract, graph theoretic angle:
Let's simplify the problem by only looking at (directed) dependency graphs between stateful objects.
An extremely simple answer can be illustrated by considering two limiting cases of dependency graphs:
The 1st limiting case: a cluster graphs .
A cluster graph is the most perfect realisation of a high cohesion and low coupling (given a set of cluster sizes) dependency graph.
The dependence between clusters is maximal (fully connected), and inter cluster dependence is minimal (zero).
This is an abstract illustration of the answer in one of the limiting cases.
The 2nd limiting case is a fully connected graph, where everything depends on everything.
Reality is somewhere in between, the closer to the cluster graph the better, in my humble understanding.
From another point of view: when looking at a directed dependency graph, ideally it should be acyclic, if not then cycles form the smallest clusters/components.
One step up/down the hierarchy corresponds to "one instance" of loose coupling, tight cohesion in a software but it is possible to view this loose coupling/tight cohesion principle as a repeating phenomena at different depths of an acyclic directed graph (or on one of its spanning tree's).
Such decomposition of a system into a hierarchy helps to beat exponential complexity (say each cluster has 10 elements). Then at 6 layers it's already 1 million objects:
10 clusters form 1 supercluster, 10 superclusters form 1 hypercluster and so on ... without the concept of tight cohesion, loose coupling, such a hierarchical architecture would not be possible.
So this might be the real importance of the story and not just the high cohesion low coupling within two layers only. The real importance becomes clear when considering higher level abstractions and their interactions.
I think you have red so many definitions but in the case you still have doubts or In case you are new to programming and want to go deep into this then I will suggest you to watch this video,
https://youtu.be/HpJTGW9AwX0
It's just reference to get more info about polymorphism...
Hope you get better understanding with this
What is the difference between cohesion and coupling?
How can coupling and cohesion lead to either good or poor software design?
What are some examples that outline the difference between the two, and their impact on overall code quality?
Cohesion refers to what the class (or module) can do. Low cohesion would mean that the class does a great variety of actions - it is broad, unfocused on what it should do. High cohesion means that the class is focused on what it should be doing, i.e. only methods relating to the intention of the class.
Example of Low Cohesion:
-------------------
| Staff |
-------------------
| checkEmail() |
| sendEmail() |
| emailValidate() |
| PrintLetter() |
-------------------
Example of High Cohesion:
----------------------------
| Staff |
----------------------------
| -salary |
| -emailAddr |
----------------------------
| setSalary(newSalary) |
| getSalary() |
| setEmailAddr(newEmail) |
| getEmailAddr() |
----------------------------
As for coupling, it refers to how related or dependent two classes/modules are toward each other. For low coupled classes, changing something major in one class should not affect the other. High coupling would make it difficult to change and maintain your code; since classes are closely knit together, making a change could require an entire system revamp.
Good software design has high cohesion and low coupling.
High cohesion within modules and low coupling between modules are often regarded as related to high quality in OO programming languages.
For example, the code inside each Java class must have high internal cohesion, but be as loosely coupled as possible to the code in other Java classes.
Chapter 3 of Meyer's Object-Oriented Software Construction (2nd edition) is a great description of these issues.
Cohesion is an indication of how related and focused the responsibilities of an software element are.
Coupling refers to how strongly a software element is connected to other elements.
The software element could be class, package, component, subsystem or a system. And while designing the systems it is recommended to have software elements that have High cohesion and support Low coupling.
Low cohesion results in monolithic classes that are difficult to maintain, understand and reduces re-usablity. Similarly High Coupling results in classes that are tightly coupled and changes tend not be non-local, difficult to change and reduces the reuse.
We can take a hypothetical scenario where we are designing an typical monitor-able ConnectionPool with the following requirements. Note that, it might look too much for a simple class like ConnectionPool but the basic intent is just to demonstrate low coupling and high cohesion with some simple example and I think should help.
support getting a connection
release a connection
get stats about connection vs usage count
get stats about connection vs time
Store the connection retrieval and release information to a database for reporting later.
With low cohesion we could design a ConnectionPool class by forcefully stuffing all this functionality/responsibilities into a single class as below. We can see that this single class is responsible for connection management, interacting with database as well maintaining connection stats.
With high cohesion we can assign these responsibility across the classes and make it more maintainable and reusable.
To demonstrate Low coupling we will continue with the high cohesion ConnectionPool diagram above. If we look at the above diagram although it supports high cohesion, the ConnectionPool is tightly coupled with ConnectionStatistics class and PersistentStore it interacts with them directly. Instead to reduce the coupling we could introduce a ConnectionListener interface and let these two classes implement the interface and let them register with ConnectionPool class. And the ConnectionPool will iterate through these listeners and notify them of connection get and release events and allows less coupling.
Note/Word or Caution: For this simple scenario it may look like an overkill but if we imagine a real-time scenario where our application needs to interact with multiple third party services to complete a transaction: Directly coupling our code with the third party services would mean that any changes in the third party service could result in changes to our code at multiple places, instead we could have Facade that interacts with these multiple services internally and any changes to the services become local to the Facade and enforce low coupling with the third party services.
simply, Cohesion represents the degree to which a part of a code base forms a logically single, atomic unit. Coupling, on the other hand, represents the degree to which a single unit is dependent on others. In other words, it is the number of connections between two or more units. The fewer the number, the lower the coupling.
In essence, high cohesion means keeping parts of a code base that are related to each other in a single place. Low coupling, at the same time, is about separating unrelated parts of the code base as much as possible.
Types of code from a cohesion and coupling perspective:
Ideal is the code that follows the guideline. It is loosely coupled and highly cohesive. We can illustrate such code with this picture:
God Object is a result of introducing high cohesion and high coupling. It is an anti-pattern and basically stands for a single piece of code that does all the work at once:
poorly selected takes place when the boundaries between different classes or modules are selected poorly
Destructive decoupling is the most interesting one. It sometimes occurs when a programmer tries to decouple a code base so much that the code completely loses its focus:
read more here
Increased cohesion and decreased coupling do lead to good software design.
Cohesion partitions your functionality so that it is concise and closest to the data relevant to it, whilst decoupling ensures that the functional implementation is isolated from the rest of the system.
Decoupling allows you to change the implementation without affecting other parts of your software.
Cohesion ensures that the implementation more specific to functionality and at the same time easier to maintain.
The most effective method of decreasing coupling and increasing cohesion is design by interface.
That is major functional objects should only 'know' each other through the interface(s) that they implement. The implementation of an interface introduces cohesion as a natural consequence.
Whilst not realistic in some senarios it should be a design goal to work by.
Example (very sketchy):
public interface IStackoverFlowQuestion
void SetAnswered(IUserProfile user);
void VoteUp(IUserProfile user);
void VoteDown(IUserProfile user);
}
public class NormalQuestion implements IStackoverflowQuestion {
protected Integer vote_ = new Integer(0);
protected IUserProfile user_ = null;
protected IUserProfile answered_ = null;
public void VoteUp(IUserProfile user) {
vote_++;
// code to ... add to user profile
}
public void VoteDown(IUserProfile user) {
decrement and update profile
}
public SetAnswered(IUserProfile answer) {
answered_ = answer
// update u
}
}
public class CommunityWikiQuestion implements IStackoverflowQuestion {
public void VoteUp(IUserProfile user) { // do not update profile }
public void VoteDown(IUserProfile user) { // do not update profile }
public void SetAnswered(IUserProfile user) { // do not update profile }
}
Some where else in your codebase you could have a module that processes questions regardless of what they are:
public class OtherModuleProcessor {
public void Process(List<IStackoverflowQuestion> questions) {
... process each question.
}
}
best explanation of Cohesion comes from Uncle Bob's Clean Code:
Classes should have a small number of instance variables. Each of the methods of a class should manipulate one or more of those variables. In general the more variables a method manipulates the more cohesive that method is to its class. A class in which each variable is used by each method is maximally cohesive.
In general it is neither advisable nor possible to create such maximally cohesive classes; on the other hand, we would like cohesion to be high. When cohesion is high, it means that the methods and variables of the class are co-dependent and hang together as a logical whole.
The strategy of keeping functions small and keeping parameter lists short can sometimes lead to a proliferation of instance variables that are used by a subset of methods. When this happens, it almost always means that there is at least one other class trying to get out of the larger class. You should try to separate the variables and methods into two or more classes such that the new classes are more cohesive.
Cohesion in software engineering is the degree to which the elements of a certain module belong together. Thus, it is a measure of how strongly related each piece of functionality expressed by the source code of a software module is.
Coupling in simple words, is how much one component (again, imagine a class, although not necessarily) knows about the inner workings or inner elements of another one, i.e. how much knowledge it has of the other component.
I wrote a blog post about this, if you want to read up in a little bit more details with examples and drawings. I think it answers most of your questions.
cohesion refers all about how a single class is designed. Cohesion is the Object Oriented principle most closely associated with making sure that a class is designed with a single, well-focused purpose.
The more focused a class is, the cohesiveness of that class is more. The advantages of high cohesion is that such classes are much easier to maintain (and less frequently changed) than classes with low cohesion. Another benefit of high cohesion is that classes with a well-focused purpose tend to be more reusable than other classes.
In the above image, we can see that in low cohesion only one class is responsible to execute lots of job which are not in common which reduces the chance of re-usability and maintenance. But in high cohesion there is a separate class for all the jobs to execute a specific job, which result better usability and maintenance.
Cohesion (Co-hesion) : Co which means together, hesion which means to stick. The System of sticking together of particles of different substances.
For real-life example:
img Courtesy
Whole is Greater than the Sum of the Parts -Aristotle.
Cohesion is an ordinal type of measurement and is usually described as “high cohesion” or “low cohesion”. 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. In contrast, low cohesion is associated with undesirable traits such as being difficult to maintain, test, reuse, or even understand. wiki
Coupling is usually contrasted with cohesion. Low coupling often correlates with high cohesion, and vice versa. Low coupling is often a sign of a well-structured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability. wiki
I think the differences can be put as the following:
Cohesion represents the degree to which a part of a code base forms a logically single, atomic unit.
Coupling represents the degree to which a single unit is independent from others.
It’s impossible to archive full decoupling without damaging cohesion, and vice versa.
In this blog post I write about it in more detail.
Cohesion is an indication of the relative functional strength of a module.
A cohesive module performs a single task, requiring little
interaction with other components in other parts of a program. Stated
simply, a cohesive module should (ideally) do just one thing.
Conventional view:
the “single-mindedness” of a module
OO view:
cohesion implies that a component or class encapsulates only attributes and operations that are closely related to one another and to the class or component itself
Levels of cohesion
Functional
Layer
Communicational
Sequential
Procedural
Temporal
utility
Coupling is an indication of the relative interdependence among modules.
Coupling depends on the interface complexity between modules, the
point at which entry or reference is made to a module, and what data
pass across the interface.
Conventional View :
The degree to which a component is connected to other components and to the external world
OO view: a qualitative measure of the degree to which classes are connected to one another
Level of coupling
Content
Common
Control
Stamp
Data
Routine call
Type use
Inclusion or import
External #
The term cohesion is indeed a little counter intuitive for what it means in software design.
Cohesion common meaning is that something that sticks together well, is united, which are characterized by strong bond like molecular attraction. However in software design, it means striving for a class that ideally does only one thing, so multiple sub-modules are not even involved.
Perhaps we can think of it this way. A part has the most cohesion when it is the only part (does only one thing and can't be broken down further). This is what is desired in software design. Cohesion simply is another name for "single responsibility" or "separation of concerns".
The term coupling on the hand is quite intuitive which means when a module doesn't depend on too many other modules and those that it connects with can be easily replaced for example obeying liskov substitution principle .
Coupling = interaction / relationship between two modules...
Cohesion = interaction between two elements within a module.
A software is consisting of many modules. Module consists of elements. Consider a module is a program. A function within a program is a element.
At run time, output of a program is used as input for another program. This is called module to module interaction or process to process communication. This is also called as Coupling.
Within a single program, output of a function is passed to another function. This is called interaction of elements within a module. This is also called as Cohesion.
Example:
Coupling = communication in between 2 different families...
Cohesion = communication in between father-mother-child within a family.
Simply put, cohesion means that a class should represent a single concept.
The public interface of a class is cohesive if all the class features are related to the concept that the class represents.
For example, instead of having CashRegister class, having CashRegister and Coin features cohesion makes it into 2 classes - CashRegister and Coin class.
In coupling, one class depends on another as it uses the objects of the class.
The problem with high coupling is that it can create side effects. One change in one class could cause an unexpected error in the other class and could break the whole code.
Generally, high cohesion and low coupling is considered high quality OOP.
Theory Difference
Cohesion
Cohesion is an indication of relative functional strength of module.
A cohesive module performs a single task, requiring little interaction with other
components in other parts of program.
A module having high cohesion and low coupling is said to be functionally independent
of other module.
Classification of Cohesion
1.Coincidental 2.Logical 3.Temporal 4.Procedural 5.Communication 6.Sequential 7.Functional
Coupling
Coupling is indication of relative interdependence among modules.
Degree of coupling between two modules depends on their interface complexity.
What are Cohesion and Decoupling? I found information about coupling but not about decoupling.
That article from Aaron is very good for understanding, also I'd recommend that you read manning publications Spring in Action book, they give very good examples on how the spring solves that problem it will definitely improve your understanding of this.
EDIT :
I came accross this in this great book called Growing object oriented software guided by tests :
Coupling :
Elements are coupled if a change in
one forces a change in the other. For
example, if two classes inherit from a
common parent, then a change in one
class might require a change in the
other. Think of a combo audio system:
It’s tightly coupled because if we
want to change from analog to digital
radio, we must rebuild the whole
system. If we assemble a system from
separates, it would have low coupling
and we could just swap out the
receiver. “Loosely” coupled features
(i.e., those with low coupling) are
easier to maintain.
Cohesion:
An element’s cohesion is a measure
of whether its responsibilities form a
meaningful unit. For example, a class
that parses both dates and URLs is not
coherent, because they’re unrelated
concepts. Think of a machine that
washes both clothes and dishes—it’s
unlikely to do both well.2 At the
other extreme, a class that parses
only the punctuation in a URL is
unlikely to be coherent, because it
doesn’t represent a whole concept. To
get anything done, the programmer will
have to find other parsers for
protocol, host, resource, and so on.
Features with “high” coherence are
easier to maintain.
Cohesion - related to the principle that a class/method should be responsible for one thing only i.e there are no stray methods that don't belong in the encapsulation; a method only does one thing. High/Low cohesion is the degree to which this holds.
Coupling - how interdependent different parts of the system are. e.g how and where there are dependencies. If two classes make calls to methods of each other then they are tightly coupled, as changing one would mean having to change the other. Decoupling is the process of making something that was tightly coupled less so, or not at all.
Flexible systems have High Cohesion and Loose Coupling.
For coupling, this Wikipedia article should answer all your questions. This article deals with cohesion.
"Decoupling" is just another name for "little/low coupling".
So these terms answer these questions:
How much does each part of your project depend on another part?
If you wanted to use just a part of your project (like to solve a specific problem) how much do you need to know about all the rest of the project?
Is every part of your project focused on a single solution to a specific problem or do solutions "leak" to other parts?
Here are my thoughts on cohesion. Imagine there is a module. Inside that module, we have some tasks. When those tasks are highly related to each other, we say it has high cohesion. When those tasks are not related, we say it has low cohesion. My best attempt to explain decoupling is that decoupling is the act of removing coupling.
Low Coupling helps us get to high cohesion! Remember that we want our module to have related tasks and one single responsibility. But what is coupling? Coupling is the degree of dependency on other modules to achieve our single responsibility for that module. So by low coupling, we are saying that we are not very dependent on external modules hence we have high cohesion.
However, if we have many dependencies to external modules, we would have high coupling and low cohesion. Get it?
Other more decorated thinkers and groups say:
Cohesion is the degree to which the tasks performed by a single module are functionally related." IEEE, 1983 "Cohesion is the "glue" that holds a module together. It can be thought of as the type of association among the component elements of a module. Generally, one wants the highest level of cohesion possible." Bergland, 1981
A software component is said to exhibit a high degree of cohesion if the elements in that unit exhibit a high degree of functional relatedness. This means that each element in the program unit should be essential for that unit to achieve its purpose. Sommerville, 1989
decoupling allows the separation of object interaction from classes and inheritance into distinct layers of abstraction used to polymorphic-ally decouple the encapsulation which is the practice of using re-usable code to prevent discrete code modules from interacting with each other.
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.