CSC/ECE 517 Summer 2008/wiki2 c6 CohCoupling: Difference between revisions
Line 60: | Line 60: | ||
===Advantages=== | ===Advantages=== | ||
* Cohesion is the idea that a given thing (be it a system, and object,or a method) does a single, clearly definable thing. This has the benefit of making your code easier to follow, and it also reduces the possibility that a method will semantically change, and therefore require an [http://en.wikipedia.org/wiki/API API] adjustment, which reduces the ripple effect and hence reduces maintenance costs. | * Cohesion is the idea that a given thing (be it a system, and object,or a method) does a single, clearly definable thing. This has the benefit of making your code easier to follow, and it also reduces the possibility that a method will semantically change, and therefore require an ''[http://en.wikipedia.org/wiki/API API]'' adjustment, which reduces the ripple effect and hence reduces maintenance costs. | ||
* Promotes code reuse, since small atomic blocks are easier to reuse then larger blocks. | * Promotes code reuse, since small atomic blocks are easier to reuse then larger blocks. | ||
* Single system failure won't bring down all connected systems. | * Single system failure won't bring down all connected systems. |
Revision as of 21:50, 24 June 2008
Introduction
Cohesion and Coupling are two terms often used in object-oriented software development. They sound similar, but have very different meanings. Cohesion is the “act or state of sticking together” or “the logical agreement". It is the basic idea that a class has a focused set of responsibilities or behaviors from a particular perspective. In contrast to cohesion, Coupling refers to the physical connections between elements of the OO design (eg: the number of collaborations between classes or the number of messages passed between objects) within an OO system. In a simple way, it gives the measure of the interdependence of one module to another.
Problem Definition
Cohesion and coupling are concepts that are reasonably easy to understand, but nonetheless, it is worthwhile to gather readable illustrations of where they apply. Browse the hundreds of Web pages that attempt to explain these concepts, picking your favorite examples. Categorize these examples, so that the reader will see the big picture, rather than just a set of redundant illustrations. Many of these pages mention related concepts; list some of them and explain how they relate to cohesion and coupling.
Cohesion
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. An object with high cohesion is defined for one purpose and it performs only that purpose. An object with low cohesion tends to try to do a lot of different things. For example, if our Card object was responsible for drawing itself, sending messages back to the server, and executing game logic, it would have low cohesion because that one class is attempting to do too much. A system can also have low cohesion if too many objects are attempting to do the same thing. For example, if a system has objects to implement a NetRunner game and every card has a unique class with a rendering method and that method is nearly identical in all classes, then the system has low cohesion. A good software design is always designed to achieve high cohesion. An example of a high cohesive EmailMessage class is given below [1].
class EmailMessage { private string sendTo; private string subject; private string message; public EmailMessage(string to, string subject, string message) { this.sendTo = to; this.subject = subject; this.message = message; } public void SendMessage() { // send message using sendTo, subject and message } }
The above class was originally designed to send an email message. Suppose if it is modified in the future in a way that the user needed to be logged in to send an email which is implemented by adding a Login method to the EmailMessage class.
class EmailMessage { private string sendTo; private string subject; private string message; private string username; public EmailMessage(string to, string subject, string message) { this.sendTo = to; this.subject = subject; this.message = message; } public void SendMessage() { // send message using sendTo, subject and message } public void Login(string username, string password) { this.username = username; // code to login } }
The Login method and username class variable really have nothing to do with the EmailMessage class and its main purpose which makes it a low cohesive class.
Types of Cohesion
- Coincidental cohesion- A module has oincidental cohesion if its elements have no meaningful relationship to one another. It is explained with an example here [2].
- Logical cohesion- A module has Logical cohesion when parts of a module are grouped together as they are logically categorized to do the same thing, even if they are different by nature (e.g. grouping all I/O handling routines). Diagram
- Temporal cohesion- A temporally cohesive module is one whose elements are functions that are related in time. It is explained with an example here [3].
- Procedural cohesion-A procedurally cohesive module is one whose elements are involved in different activities, but the activities are sequential.Diagram
- Communicational cohesion- A communicationally cohesive module is one whose elements perform different functions, but each function references the same input information or output.Diagram
- Sequential cohesion- A sequentially cohesive module is one whose functions are related such that output data from one function serves as input data to the next function. Diagram
- Functional cohesion- A functionally cohesive module is one in which all of the elements contribute to a single, well-defined task. Object-oriented languages tend to support this level of cohesion better than earlier languages do.
Advantages
- Cohesion is the idea that a given thing (be it a system, and object,or a method) does a single, clearly definable thing. This has the benefit of making your code easier to follow, and it also reduces the possibility that a method will semantically change, and therefore require an API adjustment, which reduces the ripple effect and hence reduces maintenance costs.
- Promotes code reuse, since small atomic blocks are easier to reuse then larger blocks.
- Single system failure won't bring down all connected systems.
- The higher the cohesion the less chance there will be for inconsistencies to develop or for the underlying process to break because the supporting systems are not sufficiently aligned.So cohesion, which is a business goal is a necessary and good thing, while tight coupling of the technology should be avoided.
Coupling
Coupling is a qualitative measure of the degree to which the classes, modules or subsystems are connected to one another. It can be defined as the amount of interaction of one object with another object, or one module with another module. For a good software design, it is always advisable to minimize coupling. Low coupling does not mean no coupling, the goal is reduction rather than elimination of coupling. A system with no coupling is, by definition, not a system. Low coupling indicates that each object or module performs independent tasks. In general, low coupling can be well explained by Law of demeter. It states that classes within a module or subsystem should have only limited knowledge of classes in other modules or subsystems. In simple terms, 'Law of Demeter' says "Each unit should only talk to its friends; don't talk to strangers". Strong coupling means that one object or module is dependent on other object or module to perform an operation or task. It simply means that the object or module is strongly coupled with the implementation details of another object or module.
An example of a two highly coupled objects an iPod object and a Song object is given below [4]. Song class might look something like this (Ruby style).
class Song def do(action) if action == 1 # code to play song… elsif action == 2 # code to pause elsif action == 3 # code to skip endif end end
In the above program, programmer who wants to interface the iPod object with the Song object is now dependent on the special meaning of 1, 2, & 3 to use the Song object correctly. The iPod object and the Song object are highly coupled. We can implement these objects in another way which also makes these objects more cohesive is given below.
class Song def new(path_to_song) #code to get the song from the filesystem end def self.play #code to play song end def self.pause # code to pause song end end #This would allow the iPod object to call currentSong = Song.new(”/home/user/Music/1812_Overture.mp3″) currentSong.play currentSong.pause
With the above code, other objects that wish to interact with it can do so in a uniform way regardless of how the Song object is implemented on the backend. They just know that Song object does what it is supposed to do.
Types of Coupling
- No Direct Coupling - These are independent modules and so are not really components of a single system.
- Data Coupling - Two modules are data coupled if they communicate by passing parameters or data arguments. Increase in data coupling results in increased complexity of interfaces, because the bandwidth of communication between classes increase Diagram.
- Stamp Coupling - Two modules are stamp coupled if they communicate via a passed data structure that contains more information than necessary for them to perform their functions Diagram.
- Control Coupling - Two modules are control coupled if they communicate using at least one "control flag" Diagram.
- Common Coupling - Two modules are common coupled if they both share the same global data area. It is useful to establish values that are comman to entire application, however, it can lead to uncontrolled error propagation that can be difficult to trace. Diagram
- Content coupling - Content coupling is when one module modifies or relies on the internal workings of another module (e.g. accessing local data of another module). Therefore changing the way the second module produces data (location, type, timing) will lead to changing the dependent module. This violates information hiding - a basic object oriented design concept.
In object-oriented programming, Subclass coupling describes a special type of coupling between a parent class and its child. It describes the relationship between a class and its parent. The class is connected to its parent, but the parent isn't connected to the child.
To achieve low coupling
- Strive for low message coupling.
- Reduce the number of messages passed between objects.
- Simplify messages to a few parameters.
- Avoid requiring multi-message sequences.
car.pushPedal(CLUTCH); car.shiftToGear(PARK); ---> car.start(carKey); car.insertKey(carKey); car.pushPedal(GAS); car.turnKeyInIgnition();
- Strive for low association coupling.
- Reduce extent to which objects depend on the internal structure of each other.
- Reduce the use of superclass' instance variables by subclasses (strong form of the Law of Demeter).
class Person { String first, last; class Doctor : Person { getName { first + last } getName { } ^ -----> "Dr" + Person::getName(); | } | } class Doctor : Person { getName { "Dr" + first + last; } }
- Strive for moderate inheritance coupling.
- Abstract so that subclasses depend on the methods (but not the structure!) of their superclasses.
- Use or refine as many of superclass' operations as possible in the child classes.
class Person { hello { print "Hi!" class Doctor : Person { } greetings { } ^ ----> hello(); | } | } class Doctor : Person { greetings { print "Hi!"; } }
Advantages
- Coupling enables objects or modules to collaborate with each other.
- It enables the physical connection between elements of the OO design.
Disadvantages of strong coupling
- Decreases the flexibility of the application software. Developers / maintenance programmers need to understand potentially the whole system to be able to safely modify a single component.
- Decreases the scalability of the application software. Changing requirements that affect the suitability of some component will potentially require wide ranging changes in order to accommodate a more suitable replacement component.
- Decreases the maintainability of the application software. More thought need to go into choices at the beginning of the lifetime of a software system in order to attempt to predict the long term requirements of the system because changes are more expensive.
Measuring the degree of coupling
It is difficult to come to a common consensus to decide the appropriate amount of coupling. Object oriented metrics can be useful for measuring the right level of coupling. In languages like Java, coupling can be measured in 3 different ways Java Tutorial.
- Coupling Between Objects (CBO): CBO is defined as the number of non-inherited classes associated with the target class. It is counted as the number of types that are used in attributes, parameters, return types, throws clauses, etc. Primitive types and system types (e.g. java.lang.*) are not counted.
- Data Abstraction Coupling (DAC): DAC is defined as the total number of referred types in attribute declarations. Primitive types, system types, and types inherited from the super classes are not counted.
- Method Invocation Coupling (MIC): MIC is defined as the relative number of classes that receive messages from a particular class.
MIC = nMIC / (N -1 ) Where N = total number of classes defined within the project. nMIC = total number of classes that receive a message from the target class.