CSC/ECE 517 Summer 2008/wiki3 4 bk
Cohesion Explained
Cohesion is an element of object-oriented programming 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 important 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.
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 making a 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 [2].
- Utility cohesion refers to categorizing functionality based on very general properties. For instance, rounding...
Achieving a High Level of Cohesion
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
As previously noted, concepts like cohesion and coupling can sometimes be difficult or slightly ambiguous to quantify. Various methods for empirically determining cohesiveness exist. In a cohesive method proposed by Bieman et al, a component is broken down into is 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.