Last week (4th week of September 2004) a question was raised on abstraction and encapsulation at ITtoolbox.com C++ mailing list. Based on discussion this article explains the principles of abstraction, encapsulation, cohesion and coupling. These concepts are useful in design stage of software development to reduce the maintenance cost of the software.
Abstraction and Encapsulation
Abstraction is hiding the "implementation details". There are three levels of abstraction:
- Little abstraction, at this level an application level view of the system under design is represented. At this level we find classes representing user-level concepts, example cars, trucks and classes representing generalizations of user-level concepts example vehicles.
- Good abstraction, at this level an view of the machine on which the model runs is represented. At this level we find classes representing hardware resources and system resources, example breaks, speedometer, clutches, gears, types and number of gears.
- High abstraction, at this level a low level view of implementation is represented. At this level we find classes used to implement other classes, built in data types and control structures, examples data types used to store number of gears and types of gears. Control structures used to modify the stored information.
I present one example of Bus which will have class
Driver at little level of abstraction. To put more abstraction we can represent the system by class Vehicle and class
Bus is of type class
Vehicle and class
Driver is of type
Humans. We can break down this little abstraction more to achieve good abstraction. Good abstraction is represented by class
Break and class
Steering. Further, we can break down good abstraction to achieve high abstraction by using data structure to represent range of speed the Bus has (one can use array or link list), built-in data types to represent number of gears (one can use integer i.e. int) and controls structure to manipulate
Speedometer class and
Encapsulation is enclosing an information. C++ class is a result of encapsulation. Each class in the system has a specific role to play. Example, class
Driver drives the class
Bus and class
Passenger travels in the bus. Encapsulation is just the result of abstraction. Passenger has his role, Driver has his role. They encapsulate information they need (and only they know) and expose interface methods that are required to get the system work as expected. A good design always achieve "low coupling", and "high cohesion". We use access control along with good abstraction to get "low coupling" interfaces. C++ supports access control by providing keyworks private, public and protected.
Coupling and Cohesion
We can define coupling factor of class A or group of related class in a system as "amount of change in implementation of class A" / "amount of change in implementation of all classes excluding class A". Coupling needs to be reduced to achieve low cost for maintenance by avoiding getter/setter functions. When coupling is the lowest changes in one of the class in the system or group of classes in system results in less amount of changes in other classes in the system or group of classes in system. Example, depending on the gear level certain speed should be maintained in the system. We can have methods in class Gear to manipulate the cutoff speed stored in class Speedometer. Due to tremendous research one more gear level gets added then to maintain the software up to date we modify class Gear but, if there are other classes in the system which has methods that uses gear level information from class Gear then these classes needs to be modified. The amount of modification required is coupling.
Cohesion is the bond or relation that exists between two classes. Every class must play a significant role. That is to say, take one class away and the system will stop working. This is what is meant by high cohesion. This is also called "Law of subtraction". You can imagine classes to be circles in a Venn diagram. Some of the circles overlap others. Degree of overlap is the coupling factor. At the same time, every circle would always overlap some other circle due to cohesion. The amount of cohesion in the system should be high, so that there are no useless classes in the system. Example, we can one more class in the system class Tree, one of the Passenger in the Bus counts the number of trees passing while travelling. When we remove class
Tree Bus does not stop, the system functions as expected. After representing class
Tree in our system we reduce the cohesion, as class
Tree does not have any relation with any other classes in the system.
Good design has little abstraction, low coupling, high cohesion and sufficient amount of information encapsulated.