Here, I try to shed some light on two of those: cohesion and coupling
High Cohesion
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.Functional Cohesion
Functional cohesion is when parts of a module are grouped because they all contribute to a single well-defined task of the module.One way of looking at cohesion in terms of OO is if the methods in the class are using any of the private attributes. Below is one example of how a high-cohesion class would look like.
1: class HighCohesion 2: { 3: private int _elementA; 4: private int _elementB; 5: 6: public int MethodA() 7: { 8: var returnValue = SomeOtherMethod(_elementA); 9: return SomeVeryOtherMethod(_elementB); 10: } 11: 12: public void PrintValues() 13: { 14: Console.WriteLine(_elementA); 15: Console.WriteLine(_elementB); 16: } 17: }
The point is having a the classes as small as possible in terms of elements. The less elements we have the greater the possibility for them to be used in all the methods.
Loose Coupling
Coupling in simple words, is how much one component knows about the inner workings or inner elements of another one, i.e. how much knowledge it has of the other component.Correct and clear description of what 1:1 coupling is:
iPods are a good example of tight coupling: once the battery dies you might as well buy a new iPod because the battery is soldered fixed and won’t come loose, thus making replacing very expensive. A loosely coupled player would allow effortlessly changing the battery.
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…
Tight coupling is where components are so tied to one another, that you cannot possibly change the one without changing the other.
The image above shows us a relation between two classes that is called tight coupling. Class1 above directly instantiates objects of Class2, and even goes as far as accessing member variables and so on. This makes it very dependent on Class2. What if we decided we wanted to add extra parameter in Class2’s constructor and make the default one private? Then we would have to change every usage of Class2 everywhere.
1: class ClassA 2: { 3: private bool _elementA; 4: 5: public int MethodA() 6: { 7: if (_elementA) 8: return new ClassB()._elementB; 9: 10: return 0; 11: } 12: 13: public void PrintValues() 14: { 15: new ClassB().MethodB(); 16: } 17: } 18: 19: class ClassB 20: { 21: public int _elementB; 22: 23: public void MethodB() 24: { 25: Console.WriteLine(_elementB); 26: } 27: }
We can solve this is by so called inverting the dependencies, by adding another layer. Example in C# would be adding an interface. That’s way Class1 will only be dependent on the interface, and not the actual implementation of Class2. Image 4 ilustrates this point.
Instantiation of the actual implementation will take place somewhere else in the code. This is the one of the most important reasons why dependency injection frameworks are being used.
1: class ClassA 2: { 3: private readonly ISomeInterface _interfaceImpl; 4: 5: public ClassA(ISomeInterface interfaceImpl) 6: { 7: _interfaceImpl = interfaceImpl; 8: } 9: 10: public int MethodA() 11: { 12: return _interfaceImpl.MethodB(); 13: } 14: 15: public void PrintValues() 16: { 17: _interfaceImpl.PrintValues(); 18: } 19: } 20: 21: interface ISomeInterface 22: { 23: int MethodB(); 24: void PrintValues(); 25: } 26: 27: class ClassB : ISomeInterface 28: { 29: private int _elementB = 2 + 2; 30: 31: public int MethodB() 32: { 33: return _elementB; 34: } 35: 36: public void PrintValues() 37: { 38: Console.WriteLine(_elementB); 39: } 40: }
What is the reason behind this, you may ask yourselves???……..Change.
When we have the components this separate, then we can have separate implementation of different problem areas. With separate implementation we can change as much as we want without breaking some other greater process that is using it. Furthermore, when you can change components independently, there is nothing stopping you from developing them independently and even deploy them separately.
Law of Demeter
The Law of Demeter (LoD) or the principle of least knowledge is a object-oriented software design principle. In its general form, the LoD is a specific case of loose coupling.The formal object form of the law can be summarized as:
A method of an object may only call methods of:
- The object itself.
- An argument of the method.v
- Any object created within the method.
- Any direct properties/fields of the object.
The conclusion can be summarized in one sentence:
Don’t talk to strangers!An object A can request a service (call a method) of an object instance B, but object A should not “reach through” object B to access yet another object, C, to request its services. Doing so would mean that object A implicitly requires greater knowledge of object B’s internal structure. Instead, B’s interface should be modified if necessary so it can directly serve object A’s request, propagating it to any relevant subcomponents. Alternatively, A might have a direct reference to object C and make the request directly to that. If the law is followed, only object B knows its own internal structure.
In particular, an object should avoid invoking methods of a member object returned by another method , like for example:
var a = someObject.FirstMethod().SecondMethod();For many modern object oriented languages that use a dot as field identifier, the law can be stated simply as “use only one dot”. The above example breaks the law where for example:
var a = someObject.Method();does not. As an analogy(Wikipedia), when one wants a dog to walk, one does not command the dog’s legs to walk directly; instead one commands the dog which then commands its own legs.
The advantage of following the Law of Demeter is that the resulting software tends to be more maintainable and adaptable. Since objects are less dependent on the internal structure of other objects, object containers can be changed without reworking their callers.
my thanks to: http://thebojan.ninja/2015/04/08/high-cohesion-loose-coupling/