Saturday, 31 March 2018

Coupling and Cohesion-OOP



Name:                       Saad Aslam
Roll No:                    0043-BSCS-16
Section:                    E2
Subject:                    Object Oriented Programming

Topics :
Ø Coupling
Ø Reduce Coupling
§  Calling Separate Methods
§  Encapsulation
§  Responsibilty driven design
§  Localizing Changes
Ø Implicit Coupling
Ø Cohesion
Ø Refactoring
§  Refactoring and testing
§  Refactoring for language independence





 
CH #6                            Coupling and Cohesion
REDUCE COUPLING
Ø  By calling separate methods:
If same code is used in different methods again and again than instead of writing  the same code in different methods ,we can implement a separate method and write that code which is similar in different methods and then call that code in that methods where the code was used.


Ø  Encapsulation:
To avoid tight coupling ,we need to use encapsulation by making all public fields to public .This will help us in decoupling the classes and hence decrease in tight coupling.
(“Never make fields public!”)
Proper
encapsulation in
classes reduces
coupling and thus
leads to a better

The encapsulation guideline (hiding implementation information from view) suggests that only information about what a class can do should be visible to the outside, not about how it does it.This has a great advantage: if no other class knows how our information is stored, then we can easily change how it is stored without breaking other classes.

Ø  Responsibility-driven design:
Responsibility-driven design expresses the idea that each class should be responsible for handling
its own data. Often, when we need to add some new functionality to an application, we
need to ask ourselves in which class we should add a method to implement this new function.
Which class should be responsible for the task? The answer is that the class that is responsible
for storing some data should also be responsible for manipulating it.

Ø  Localizing Changes:
Another aspect of the decoupling and responsibility principles is that of localizing change. We
aim to create a class design that makes later changes easy by localizing the effects of a change.
Ideally, only a single class needs to be changed to make a modification. Sometimes several
classes need change, but we then aim at this being as few classes as possible. In addition, the
changes needed in other classes should be obvious, easy to detect, and easy to carry out.
To a large extent, we can achieve this by following good design rules such as using
responsibility-driven design and aiming for loose coupling and high cohesion. In addition, however,
we should have modification and extension in mind when we create our applications. It is important
to anticipate that an aspect of our program might change, in order to make this change easy.

WORSE FORM OF COUPLING
Implicit Coupling:
          There is an even worse form of coupling: implicit coupling.
          Implicit coupling is a situation where one class depends on the internal information of another,but this dependence is not immediately obvious. The tight coupling in the case of the public fields was not good, but at least it was obvious. If we change the public fields in one class and forget about the other, the application will not compile any more and the compiler will point out the problem. In cases of implicit coupling, omitting a necessary change can go undetected.
          This is a fundamental problem, because every time a command is added, the help text needs to be changed, and it is very easy to forget to make this change. The program compiles and runs, and everything seems fine. A maintenance programmer may well believe that the job is finished and release a program that now contains a bug.
This is an example of implicit coupling.

THINKING AHEAD

Q:What is Model View Controller Pattern?

COHESION
A unit of code should always be responsible for one, and only one, task. The principle of cohesion can be applied to classes and methods: classes should display a high degree of cohesion, and so should methods.

Ø  Cohesion in Methods:
When we talk about cohesion of methods, we seek to express the ideal that any one method should be responsible for one, and only one, well-defined task.We can see an example of a cohesive method in the Game class. This class has a private method named printWelcome to show the opening text, and this method is called when the game starts in the play method.

Ø  Cohesion in Classes:
The rule of cohesion of classes states that each class should represent one single, well-defined entity in the problem domain.

BENEFITS OF COHESION

There are several ways in which high cohesion benefits a design. The two most important ones
are readability and reuse

REFACTORING

        Refactoring is the activity of restructuring existing classes and methods to adapt them to
changed functionality and requirements. Often in the lifetime of an application, functionality is
gradually added. One common effect is that, as a side-effect of this, methods and classes slowly
grow in length.
     Refactoring is the rethinking and redesigning of class and method structures. Most commonly,the effect is that classes are split in two or that methods are divided into two or more methods.
Refactoring can also include the joining of multiple classes or methods into one, but that is less
common than splitting.

Ø  Refactoring and testing:
Before we provide an example of refactoring, we need to reflect on the fact that, when we
refactor a program, we are usually proposing to make some potentially large changes to something
that already works. When something is changed, there is a likelihood that errors will be
introduced. Therefore, it is important to proceed cautiously; and, prior to refactoring, we should establish that a set of tests exists for the current version of the program. If tests do not exist, then we should first decide how we can reasonably test the functionality of the program and record those tests (for instance, by writing them down) so that we can repeat the same tests later.

Refactoring will follow the following two steps:

 The first step is to refactor in order to improve the internal structure of the code, but without
making any changes to the functionality of the application. In other words, the program should,
when executed, behave exactly as it did before. Once this stage is completed, the previously
established tests should be repeated to ensure that we have not introduced unintended errors.

 The second step is taken only once we have reestablished the baseline functionality in the refactored version. Then we are in a safe position to enhance the program. Once that has been
done, of course, testing will need to be conducted on the new version.

               Doing good refactoring is as much about thinking in a certain mindset as it is about technical skills. While we make changes and extensions to applications, we should regularly question whether an original class design still represents the best solution. As the functionality changes, arguments for or against certain designs change. What was a good design for a simple application might not be good any more when some extensions are added.

Recognizing these changes and actually making the refactoring modifications to the source
code usually saves a lot of time and effort in the end. The earlier we clean up our design, the
more work we usually save.

Ø  Refactoring for language independence:

          If we want to have language independence in the program, then ideally we should have just one place in the source code where the actual text of command words is stored and have everywhere else refer to commands in a language-independent way. A programming language feature that makes this possible is enumerated types, or enums.

           In its simplest form, an enumerated type definition consists of an outer wrapper that uses the word enum rather than class and a body that is simply a list of variable names denoting the
set of values that belong to this type. By convention, these variable names are fully capitalized.
We never create objects of an enumerated type. In effect, each name within the type definition
represents a unique instance of the type that has already been created for us to use. We refer to these instances as CommandWord.GO, CommandWord.QUIT, etc. Although the syntax for using them is similar, it is important to avoid thinking of these values as being like the numeric class constants Despite the simplicity of their definition, enumerated type values are proper objects and are not the same as integers.

SUMMARY

Ø  Good class design can make a huge difference when an application needs to be corrected, modified,or extended. It also allows us to reuse parts of the application in other contexts (for example, for other projects) and thus creates benefits later.
Ø  There are two key concepts under which class design can be evaluated: coupling and cohesion.
Ø  Coupling refers to the interconnectedness of classes, cohesion to modularization into appropriate units. Good design exhibits loose coupling and high cohesion.
Ø  One way to achieve a good structure is to follow a process of responsibility-driven design. Whenever we add a function to the application, we try to identify which class should be responsible for which part of the task.
Ø  When extending a program, we use regular refactoring to adapt the design to changing requirement and to ensure that classes and methods remain cohesive and loosely coupled.


CONCEPT SUMMARY

 Coupling The term coupling describes the interconnectedness of classes. We strive for loose
coupling in a system—that is, a system where each class is largely independent and communicates with other classes via a small, well-defined interface.

 Cohesion The term cohesion describes how well a unit of code maps to a logical task or entity.In a highly cohesive system, each unit of code (method, class, or module) is responsible
for a well-defined task or entity. Good class design exhibits a high degree of cohesion.

 Code duplication Code duplication (having the same segment of code in an application more
than once) is a sign of bad design. It should be avoided.

 Encapsulation Proper encapsulation in classes reduces coupling and thus leads to a better
design.

 Responsibility-driven design Responsibility-driven design is the process of designing
classes by assigning well-defined responsibilities to each class. This process can be used to
determine which class should implement which part of an application function.

  Localizing change One of the main goals of a good class design is that of localizing change:
making changes to one class should have minimal effects on other classes.

 Method cohesion A cohesive method is responsible for one, and only one, well-defined task.

 Class cohesion A cohesive class represents one well-defined entity.

 Refactoring Refactoring is the activity of restructuring an existing design to maintain a good
class design when the application is modified or extended.

 Switch statement A switch statement selects a sequence of statements for execution from
multiple different options.

                                                                                        

0 comments:

Post a Comment