CSC/ECE 517 Summer 2008/wiki3 4 bk
Cohesion Explained
Cohesion is an element of object-oriented design related to how well or how poorly a component of a program is compartmentalized. Put another way, cohesion represents the degree to which the individual parts of a component belong together 1. Strong (high) cohesion is the preferable state in which a component's implementation and "awareness" is contained within the respective component. Weak (low) cohesion is the undesirable state in which the implementation crosses over the boundaries of the component into the rest of the program. In short, the component encapsulates its implementation. By adhering to the principle of encapsulation and forcing a program's components to remain compartmentalized, the process of implementing, testing, and maintaining the application become much more straightforward [Pressman]. Cohesion should not be confused with the closely related object-oriented design concept of coupling. Coupling is the degree to which modules interact with one another. While a high level of cohesion is desirable, a minimal level of coupling in which modules intercommunicate as little as possible is the goal of a well thought out design. To further understand the concept of cohesion, it is useful to look at the various types of cohesion, how to achieve high cohesion when developing an application, and finally to measure the level of cohesiveness of components present in a given application.
Levels of Cohesion
Cohesion can be broken down into seven main levels [Pressman]:
Most Desirable
- Functional cohesion is the highest level in which a component performs one operation and then returns its result. An example would be a simple method which takes two values, sums them, and then returns the result. Although insuring that a component focuses on a specific operation is important, it is necessary to note that done incorrectly, it is possible to end up with a great number of individual components that only consist of a few lines of code 1.
- Layer cohesion occurs when components are functionally layered and the higher layers can access lower layers in a downward fashion, but lower layers cannot in turn access higher layers. This could be illustrated by levels of security clearance. Top secret can view all levels of secrecy which exist below. But lower security levels can only look at their level and those possessing lower security clearance.
- Communicational cohesion exists where operations accessing a particular type of data are contained within the same class. This is apparent in any properly planned and implemented class in which all mutator and accessor methods are available only to objects of the given class. An undesirable effect of communicational cohesion is that it sometimes involves returning more information than is needed in some cases due to the reuse of the same accessor for multiple purposes 1.
Least Desirable
- Sequential cohesion occurs when components are chained together where one component's output becomes the input of the next and so forth. The latter components are dependent on those which have come before. While sequential cohesion generally promotes good coupling, it does not lend itself well to reuse, as the functionality will be very specific to the sequence of which it is a part 1.
- Procedural cohesion takes place when component A that shares no common data with component B causes B to become active simply because A was invoked. An example of this would be serving a meal. The main course is served prior to the dessert course. Procedurally, once the main course is complete, the dessert course is then served. This takes place even though the two courses share nothing in common (such as ingredients) or depend upon each other for their preparation.
- Temporal cohesion deals with components which are executed at a given time based on some specific occurrence. A simple example would be tasks/programs to be performed/run as part of a Unix CRON. Upon the CRON's execution time, all operations listed in the file are performed even though the operations may not necessarily have anything in common with each other. Temporally cohesive modules tend to be highly coupled and do not lend themselves well to reuse 1.
- Utility cohesion refers to categorizing functionality based on very general properties. For instance, a function for formatting currency would be generalized in the sense that it could be applied to any number of unrelated monetary values.
Achieving a High Level of Cohesion through Careful Design
As previously noted, concepts like cohesion and coupling can sometimes be difficult or slightly ambiguous to quantify. While it is important to make sure that elements of a component are closely related, it is equally important to make sure that the functionality of a component is not duplicated from other components 1. Pressman offers a seven step process to aid in the achievement of an overall well-implemented component-level design [Pressman].
- Identifying all classes which correspond to the problem's domain
- Identifying all classes which correspond to the infrastructure's domain
- Identifying all classes which will have reusable components
- Specifying message details where components collaborate or overlap
- Identifying interfaces for each component
- Elaborating on the internal workings necessary to implement the components
- Describing flow of control within each component
- Describing persistent databases and files and their respective utility classes
- Developing behavioral representations for components
- Using deployment diagrams to elaborate on implementation details
- Iterate through every component-level representation and refactor if necessary
Although not always practical in real-world development environments, the methodical process helps to insure that the necessary forethought and planning have taken place to foster a favorable end result.
Measuring Cohesiveness
Aside from following a good design plan, various methods for empirically determining cohesiveness exist. Components can be broken down into their simplest elements consisting of methods, variables, etcetera. When plugged into the proposed formulae, the degree of connectedness among components is determined, and this yields an indication of the overall level of class cohesion achieved. Examples of proposed methods for determining levels of cohesion include:
- Lack of Cohesion of Methods looks at the linkage of method calls within classes to determine the level of cohesion and to help provide an indication of what class components can be separated out into their own classes. This is done by looking at the number of methods within a class which reference a specific instance variable 2. When interpreting LCOM values, low values indicate a high level of cohesion while high LCOM values are undesirable.
- Most Cohesive Component measures cohesion by looking at a connectivity factor and structure factor as they relate to an application's classes. As the names imply, the connectivity factor measures the connection between class components and the cohesion factor measures the level of cohesiveness.
- Tight Class Cohesion and Loose Class Cohesion looks at the number of direct and indirect graph connections of non-private methods when determining cohesiveness. The loose class cohesion method is useful for determining the number of overall connections while the tight class cohesion method is useful for determining the density of the connections present.
- There are a number of Cohesion Diagrams of various types which allow cohesiveness to be graphically observed. Dependencies, instantiations, recursions, and declarations are just a few operations which can be effectively viewed via cohesion diagrams in order to get a clearer picture of what is taking place.
- Another visualization method proposed by Churcher et al, makes use of the Angle 3D engine to render the relationships of components to more accurately quantify the degree of cohesion and coupling present. Connections of classes can be visualized in a 3D environment for a richer presentation of how the various components interrelate.
- Non-Cohesive Class Reports offer a means of determining if a class can be separated into two or more classes due to the class containing unrelated methods.
Conclusion
By looking at cohesion as it relates to coupling in object-oriented design, it is clear that successful management of the two are key to a well designed application. Following a good software engineering design framework can help the designer/programmer to develop an application which will insure high cohesion with low coupling among components. Due to the complexity of cohesion, it is difficult if not impossible to name a specific metric as an absolute for determining whether or not a strong level of cohesion has been achieved. By using an aggregate of the many diverse methods available, a reasonably sound indication of overall cohesiveness can be determined.
References and Further Reading
- Object-Oriented Metrics
- Design Principles: Cohesion
- Cohesion Metrics
- A Cohesion Measure for Classes in Object-Oriented Systems
- What Does Object-Oriented Design Mean to You?
- Visualizing Class Cohesion with Virtual Worlds, Churcher, Neville et al, Australian Computer Society, 2003.
- Software Engineering: A Practitioner's Approach, Pressman, Robert, McGraw-Hill.