Thursday, February 10, 2011

Cohesion

Cohesion

Meilir Page-Jones

© Copyright 1998, Wayland Systems Inc. All rights reserved.
As we saw in the previous chapter, an important way to evaluate the partitioning of a system is by how cleanly the modules are separated from one another. That is the criterion of coupling, Another way to determine partitioning is to look at how the activities within a single module are related to one another. This is the criterion of cohesion. Since coupling and cohesion are both ways of measuring partitioning, you’d expect them to be interdependent. Indeed, they are, in that the cohesion of a module often determines how tightly it will be coupled to other modules in a system.
As an illustration, look at the map of a pair of cities in . The heavy traffic between Sidtown and Fredborough arises because of the way in which the Better Mousetrap Company and the Zokko Soda Company have distributed themselves. Every morning, Better Mousetrap workers leave their homes in Fredborough and beat a path to the door of the Better Mousetrap factory in Sidtown. In the evening, they all return. Day and night, trucks full of bottles rumble from Fredborough to Sidtown to be filled with sparkling, lowcalorie Zokko soda. But what if these two companies rearranged their facilities as shown in ? Now, each company has restricted itself to one city, resulting in two very boring cities, but also — more importantly — resulting in little or no traffic between the cities. (There may be some traffic if Better Mousetrap workers occasionally pause to refresh themselves with Zokko soda.)


<IMG SRC="images/pgssd_ch06_F6-1.gif" WIDTH=396 HEIGHT=288 BORDER=0>

Figure 6.1



<IMG SRC="images/pgssd_ch06_F6-2.gif" WIDTH=396 HEIGHT=288 BORDER=0>
Figure 6.2

The moral of this tale of two cities is that putting strongly associated things in the, same city reduces the traffic between the cities. The cities are, of course, thinly disguised modules, and the traffic between them is coupling. The term for “putting strongly associated things in the same module” is cohesion, which brings us to this definition:
Cohesion is the measure of the strength of functional relatedness of elements within a module.
Element means an instruction, a group of instructions, a data definition or a call to another module; that is, any piece of code that accomplishes some work or defines some data.
Designers should create strong, highly cohesive modules, modules whose elements are strongly and genuinely related to one another.1 On the other hand, the elements of one module should not be strongly related to the elements of another module, because that would lead to tight coupling between the modules.
Cohesion, then, is the second way to tell how well we’ve partitioned a system into modules. Indeed, making sure that all modules have good cohesion is the best way to minimize coupling between the modules. It also ensures that the functions of the system reflect the functions of the original problem.
The idea of cohesion came to Larry Constantine in the mid-1960s (Yourdon and Constantine, 1978, pp. 95—126). He was interested in learning why people create certain types of modules and in examining the relative merits and ills of each of the types. The term itself was borrowed from sociology, where it means the relatedness of humans within groups,
From these early studies and later refinements, Stevens, Myers, Constantine, and Yourdon developed a scale of cohesion (Table 6.1) as a measure of the black boxness of a module and, it turns out from experiments, as a good measure of the maintainability of a module. (For references, see Stevens et al (1974) and Yourdon and Constantine (1978).)
Sections 6.1 to 6.7 will show the good and bad characteristics of each level of cohesion.

6.1 FUNCTIONAL COHESION

A functionally cohesive module contains elements that all contribute to the execution of one and only one problem-related task. Examples of functionally cohesive modules are
   COMPUTE COSINE OF ANGLE
   VERIFY ALPHABETIC SYNTAX
   READ TRANSACTION RECORD
   DETERMINE CUSTOMER MORTGAGE REPAYMENT
   COMPUTE POINT OF IMPACT OF MISSILE
   CALCULATE NET EMPLOYEE SALARY
   ASSIGN SEAT TO AIRLINE CUSTOMER


TABLE 6.1  SCALE OF COHESION
  BEST
MAINTAINABILITY
 
Functional Black box
Sequential Not-quite-so-black box
Communicational Gray box
Procedural WORST
MAINTAINABILITY
White or transparent box
Temporal
Logical
Coincidental
Notice that each of these modules has a strong, single-minded purpose. When its boss calls it, it carries out just one job to completion without getting involved in any extracurricular activity. For example, DETERMINE CUSTOMER MORTGAGE REPAYMENT must do just that; it must not, for instance, print out page headings.
Some of these functionally cohesive modules are very simple and would probably be found low on the structure chart (such as verify ALPHABETIC SYNTAX or READ TRANSACTION RECORD), while others are complicated and would be found quite high on the structure chart (for instance, COMPUTE POINT OF IMPACT OF MISSILE).READ TRANSACTION RECORD is obviously doing a single function, but how can CALCULATE NET EMPLOYEE SALARY be doing only one job when everyone knows that it’s computing gross salary, FICA deductions, federal income tax, state income tax, and so on? The point is that however complicated a module, and however many subfunctions make up its total job, if you can sum up everything that it accomplishes for its boss as one problem-related function, then that module is functionally cohesive.2
Systems built chiefly of normally coupled, functionally cohesive modules are by far the easiest (and thus cheapest!) systems to maintain. It is tempting to think that any module can be summed up as performing one function, but don’t be fooled. There are many kinds of modules whose bosses regard them as doing different jobs that cannot be summed up as a single problem-related function. The crucial factor in deciding the level of cohesion of these nonfunctional modules is how the different activities they perform are related to one another.

6.2 SEQUENTIAL COHESION

A sequentially cohesive module is one whose elements are involved in activities such that output data from one activity serves as input data to the next. To illustrate this definition, imagine that you’re about to repaint your bright orange Corvette a classy silver color. The sequence of steps might be something like this:
  1. CLEAN CAR BODY
  2. FILL IN HOLES IN CAR
  3. SAND CAR BODY
  4. APPLY PRIMER
This group of four activities cannot be summed up as a single function, which means the “module” is not functionally cohesive. (If we added a fifth step, PUT ON FINAL COAT, we would have a functionally cohesive module called REPAINT CAR.) To determine the “module’s” level of cohesion, therefore, we must ask: How are these activities related to one another? The answer is that the output from one activity serves as input to the next — just like on an assembly line. And that fits the definition of a sequentially cohesive module.
Here’s another example of a sequentially cohesive module, described first in pseudocode and then shown on a structure chart.
   module format and cross-validate record
      uses raw record
      format raw record
      cross-validate fields in raw record
      returns formatted cross-validated record
   endmodule



<IMG SRC="images/pgssd_ch06_F6-3.gif" WIDTH=133 HEIGHT=120 BORDER=0>

Figure 6.3

In , the output from the first activity (formatting) is the input to the second (cross-validation).
A sequentially cohesive module usually has good coupling and is easily maintained. Indeed, it is almost as maintainable as a functionally cohesive module. The only real disadvantage of a sequentially cohesive module is that it is not so readily reusable in the same system (or in other systems) as is a functionally cohesive module, because it contains activities that will not in general be useful together.

6.3 COMMUNICATIONAL COHESION

A communicationally cohesive module is one whose elements contribute to activities that use the same input or output data. Suppose we wish to find out some facts about a book: For instance, we may wish to
  1. FIND TITLE OF BOOK
  2. FIND PRICE OF BOOK
  3. FIND PUBLISHER OF BOOK
  4. FIND AUTHOR OF BOOK
These four activities are related because they all work on the same input data, the book, which makes the “module” communicationally cohesive.
Another example of a communicationally cohesive module is
   module determine customer details
      use customer account no
      find customer name
      find customer loan balance
      return customer name, customer loan balance
   endmodule

In , the two activities of finding the customer’s name and finding his loan balance use the input of CUSTOMER ACCOUNT NO. The coupling between a communicationally cohesive module and its caller is usually acceptable; typically, it’s narrow on one side and arbitrarily broad on the other, depending on the number of functions in the module.


<IMG SRC="images/pgssd_ch06_F6-4.gif" WIDTH=120 HEIGHT=144 BORDER=0>

Figure 6.4

Communicationally cohesive modules are quite maintainable, although there can be problems. In , it’s possible that another module in the system would need to find out a customer’s name but wouldn’t be interested in his loan balance. That module would either have to discard the loan balance data (dirty and redundant coupling) or would need its own code for finding the customer name (duplication of function).


<IMG SRC="images/pgssd_ch06_F6-5.gif" WIDTH=114 HEIGHT=294 BORDER=0>

Figure 6.5

Another potential problem with a communicationally cohesive module is the temptation to share code among the activities within it; that can make it tough to change one activity without destroying another. For example, the upper module in is communicationally cohesive. With EMPLOYEE SALARY TABLE, it both generates a report on all of the employees’ salaries and calculates their average salary. Because both functions need access to every salary, a programmer may be tempted to put them inside the same loop. It’s possible, however, that at some later date a report on only the first 20 employees might need to be generated. To generate this new report, a maintenance programmer would need to change CALCULATE AVERAGE SALARY by inserting a test in the loop to determine when the 20th employee had been passed. However, a better solution would be to create a separate loop for each activity. But in that case, there would no longer be any point in keeping the two activities in the same module.


<IMG SRC="images/pgssd_ch06_F6-6.gif" WIDTH=396 HEIGHT=144 BORDER=0>

Figure 6.6

Almost always, you’ll improve maintainability if you split a communicationally cohesive module into separate, functionally cohesive ones, as in .
Modules with communicational and sequential cohesion seem similar since they both contain activities organized around the data in the original problem. They also have quite clean coupling, because few of their elements are related to elements in other modules. The main difference between them is that a sequentially cohesive module operates like an assembly line; its individual activities must be carried out in a specific order. But in a communicationally cohesive module, order of execution is unimportant. In the module depicted in , it doesn’t matter whether the employee’s report is generated before, after, or at the same time as the average salary is calculated.


<IMG SRC="images/pgssd_ch06_F6-7.gif" WIDTH=396 HEIGHT=348 BORDER=0>

Figure 6.7

Sequentially and communicationally cohesive modules can be illustrated in data flow terms, as shown in . This illustration highlights the fact that the activities are strongly related by the data in the problem. Chapter 8 will examine the partitioning of a system by means of a data flow diagram. Chapter 10 will look at the strategy of transform analysis, which is used to derive a good structure chart from a DFD. We’ll see that this strategy tends to produce modules of the top three levels of cohesion. If you don’t mind my making a slight forward reference to the DFD, I can depict sequential and communicational cohesion in data-flow terms as shown in .

6.4 PROCEDURAL COHESION

As we reach procedural cohesion, we cross the boundary from the easily maintainable modules of the higher levels of cohesion to the less easily maintainable modules of the middle levels of cohesion. A procedurally cohesive module is one whose elements are involved in different and possibly unrelated activities in which control flows from each activity to the next. (Remember that in a sequentially cohesive module data, not control, flows from one activity to the next.) Here is a list of steps in an imaginary procedurally cohesive module.
  1. CLEAN UTENSILS FROM PREVIOUS MEAL
  2. PREPARE TURKEY FOR ROASTING
  3. MAKE PHONE CALL
  4. TAKE SHOWER
  5. CHOP VEGETABLES
  6. SET TABLE
SET TABLE is the last step listed for this “module.” But GET DRESSED or MAKE ANOTHER PHONE CALL would be equally valid candidates for step 6, because the activities on this list are related only in that they may well happen in this order during a particular day. They make up a piece of someone’s daily flowchart. They are related by order of execution rather than by any single problem-related function.
Another example of a procedurally cohesive module is shown in as part of a structure chart.


   module write read and edit somewhat
      uses out record
      write out record
      read in record
      pad numeric fields of in record with zeros
      return in record
   endmodule


<font face="Verdana,Arial,Helvetica,Helv,Swiss,Sans Serif"><font size="-1"><IMG SRC="images/pgssd_ch06_F6-8.gif" WIDTH=108 HEIGHT=144 BORDER=0></font></font>

Figure 6.8

Procedurally cohesive modules tend to be composed of pieces of functions that have little relationship to one another (except that they’re carried out in a specific order at a certain time). However, these pieces of functions probably have quite a lot to do with pieces of functions in other modules. WRITE, READ, AND EDIT SOMEWHAT finishes dealing with the last transaction (by writing OUT RECORD) and starts to deal with the next one (by reading and somewhat editing IN RECORD). It’s typical of a procedurally cohesive module that the data sent to it and the data it sends back have little relationship. It’s also typical that such a module passes around partial results (e.g., a partially edited IN RECORD), flags, switches, and so on.
Section 6.3, on communicational cohesion, showed an example of a tricky programmer using a single loop to do two distinct activities: to compute employees’ salaries and to report them. With procedural cohesion, such nasty tricks become rife — and often with no basis whatsoever in the problem itself. As an example, look at , which shows a procedurally cohesive module that averages two completely unrelated tables, TABLE-A and TABLE-B, which both just happen to have 100 elements each.


   module compute table-A-avg and table-B-avg
      uses table-A, table-B
      returns table-A-avg, table-B-avg
         table-A-total : = 0
         table-B-total : = 0
         for i = i to 100
            add table-A (i) to table-A-total
            add table-B (i) to table-B-total
         endfor
         table-A-avg : = table-A-total/100
         table-B-avg : = table-B-total/100
   endmodule


<font face="Verdana,Arial,Helvetica,Helv,Swiss,Sans Serif"><font size="-1"><IMG SRC="images/pgssd_ch06_F6-9.gif" WIDTH=108 HEIGHT=168 BORDER=0></font></font>

Figure 6.9

This piece of coding has tied table-A and table-B together, although the tables are unrelated in the original problem. As an exercise in maintenance, I leave it to you to figure out what to do to the module in if the length of table-B changes to 120 or if the elements in table-B become in some way dependent on table-A-avg.

6.5 TEMPORAL COHESION

A temporally cohesive module is one whose elements are involved in activities that are related in time. Picture this late-evening scene:
  1. PUT OUT MILK BOTTLES
  2. PUT OUT CAT
  3. TURN OFF TV
  4. BRUSH TEETH
These activities are unrelated to one another except that they’re carried out at a particular time. They’re all part of an end-of-day routine.
The classic example of temporal cohesion is an initialization module, as shown in . Temporally cohesive modules, like procedurally cohesive ones, tend to be composed of partial functions whose only relationship to one another is that they all happen to be carried out at a certain time. The activities are usually more closely related to activities in other modules than they are to one another, a situation that leads to tight coupling.
In , the module INITIALIZE initializes many different functions in a mighty sweep, causing it to be broadly related to several other modules in the system — a condition that is reflected by broad coupling to its caller. A temporally cohesive module also has some of the same difficulties as a procedurally cohesive one. The programmer is tempted to share code among activities related only by time, and the module is difficult to reuse, either in this system or in others.3


   module initialize
      updates a-counter, b-counter, items table,
         totals table, switch-a, switch-b
      rewind tape-a
      set a-counter to 0
      rewind tape-b
      set b-counter to 0
      clear items table
      clear totals table
      set switch-a to off
      set switch-b to on
   endmodule


<font face="Verdana,Arial,Helvetica,Helv,Swiss,Sans Serif"><font size="-1"><IMG SRC="images/pgssd_ch06_F6-10.gif" WIDTH=72 HEIGHT=108 BORDER=0></font></font>

Figure 6.10

For instance, if a maintenance change later requires you to put out the cat in the middle of the afternoon, you’d be obliged to put out the milk bottles, brush your teeth, and turn off the TV, all of which may be highly inconvenient. In , if you want to re-initialize TAPE B elsewhere in the system, then you’re faced with two unfortunate choices. To avoid resetting the whole system to zero, you could either introduce flags indicating to INITIALIZE which part(s) of it should be executed, or write another piece of code for dealing with TAPE B. Both of these solutions degrade maintainability.
Procedural and temporal modules are quite similar. They can be created by taking scissors to a flowchart. The degree of their black boxness, or coloring, varies from dark gray to light gray, since it is not very easy to state simply the function of such a module without listing its internal details. They are similar as well in that the coupling to procedural and temporal modules ranges from mediocre to poor. The difference between them is like the difference between sequential and communicational cohesion. The order of execution of activities is more important in procedurally cohesive modules. In addition, procedural modules tend to share loops and decisions between functions, whereas temporal modules tend to contain more straight-line code.

6.6 LOGICAL COHESION

A logically cohesive module is one whose elements contribute to activities of the same general category in which the activity or activities to be executed are selected from outside the module. Keeping this definition in mind, consider the following example. Someone contemplating a journey might compile the following list:
  1. GO BY CAR
  2. GO BY TRAIN
  3. GO BY BOAT
  4. GO BY PLANE
What relates these activities? They’re all means of transport, of course. But a crucial point is that for any journey, a person must choose a specific subset of these modes of transport. It’s unlikely anyone would use them all on any particular journey.
A logically cohesive module contains a number of activities of the same general kind. To use the module, we pick out just the piece(s) we need. Thus, a logically cohesive module is a grab bag of activities. The activities, although different, are forced to share the one and only interface to the module. The meaning of each parameter depends on which activity is being used; for certain activities, some of the parameters will even be left blank (although the calling module still needs to use them and to know their specific types).
The activities in a logically cohesive module fall into roughly the same category, having some similarities as well as differences. Unfortunately, this leads the programmer into knotting together the code of the activities by allowing activities to share common lines of code. So not only does a logically cohesive module have an ugly exterior with maybe a dozen different parameters fighting to use four accesses, but its inside resembles a plate of spaghetti mixed with noodles and worms. The resulting module is neither easy to understand nor to maintain.
Try understanding the code for the logically cohesive module in . (This is an example from real life rewritten to eliminate the original GOTOs, which made it totally incomprehensible.)


   module general io routine
      uses input flag /* to choose which function */
      updates record-A
      define record-B as 80 char /* working */
      define record-C as 120 char /* storage*/
      if input flag = 1
      then write record-A to new master file
         read tran file 1 into record-B
      elseif input flag = 2
      then if record-A = all spaces
         then read tran file1 into record-B
         endif
         read tran file2 into record-C
      elseif input flag = 3
      then read tran file1 into record-B
         read master file1 into record-C
         read master file2 into record-A
      endif
      return record-B, record-C
   endmodule


<font face="Verdana,Arial,Helvetica,Helv,Swiss,Sans Serif"><font size="-1"><IMG SRC="images/pgssd_ch06_F6-11.gif" WIDTH=130 HEIGHT=168 BORDER=0></font></font>

Figure 6.11

The example represents not so much the sharing of code as the sharing of buffer space, exploiting such facts as TRAN FILE2 and MASTER FILE1 records are both 120 characters long and are never read together. Notice that RECORD-A sometimes is read, sometimes is written, and sometimes acts as a flag — a ghastly piece of hybrid coupling.
Have you got that? Or would you like some clarification?
/* Clarification of GENERAL IO ROUTINE:
   RECORD-B and TRAN FILE records are 80 chars
   RECORD-C, TRAN FILE2 and MASTER FILE1 records are 120 chars
   RECORD-A, MASTER FILE1 and NEW MASTER FILE records are 142 chars
The effect of the module depends on the value in INPUT FLAG:
   when INPUT FLAG = 1
      RECORD-A is written to NEW MASTER FILE
      RECORD-B is set to the next TRAN FILE1 record
      RECORD-C is undefined

   when INPUT FLAG = 2
      RECORD-A is used as an auxiliary input flag
      RECORD-B is set to the next TRAN FILE1 record
         (But only if RECORD-A had been set to SPACES;
         otherwise RECORD-B is undefined)
      RECORD-C is set to the next TRAN FILE2 record

   when INPUT FLAG = 3
      RECORD-A is set to the next MASTER FILE2 record
      RECORD-B is set to the next TRAN FILE1 record
      RECORD-C is set to the next MASTER FILE1 record

*/
If you understand this module, then you’re doing better than I did when I had to maintain it. But let’s see how you fare with a few changes.
First, can you modify GENERAL IO ROUTINE so that if INPUT FLAG = 3, TRAN FILE2 instead of TRAN FILE1 is read? Sorry, can’t do it. A TRAN FILE2 record (120 chars) won’t fit into RECORD-B (80 chars), into which the TRAN FILE1 record is currently being placed. RECORD-C (120 chars), which would fit, is already in use for the MASTER FILE1 record.
Can you change the module so that if INPUT FLAG = 2, RECORD-C is written to NEW MASTER FILE? No go, I’m afraid. Remember that RECORD-C is being used as a funny flag when INPUT FLAG = 2? It can’t be used to hold “real” information.
Is it possible to lengthen a TRAN FILE2 record (120 chars) to 132 chars? I hate to be difficult, but where on earth would we put it? The only possibility is RECORD-A (142 chars) with a 10-space padding (ugly), but we can’t even do that because RECORD-A is being used for so many other weird things.
The only reason that people create logically cohesive modules is to overlap parts of functions that happen to have the same lines of code or the same buffers — but are not even executed at the same time! You can imagine, I’m sure, that if code as well as buffers had been shared in the above example, the result would have been functions so inextricably intertwined that Harry Houdini himself would have had difficulty untangling them. And if nothing can be overlapped between functions, then logically cohesive modules have no point whatsoever. A better name for logical cohesion would be illogical cohesion!

6.7 COINCIDENTAL COHESION

A coincidentally cohesive module is one whose elements contribute to activities with no meaningful relationship to one another; as in
  1. FIX CAR
  2. BAKE CAKE
  3. WALK DOG
  4. FILL OUT ASTRONAUT-APPLICATION FORM
  5. HAVE A BEER
  6. GET OUT OF BED
  7. GO TO THE MOVIES
A coincidentally cohesive module is similar to a logically cohesive one. Its activities are related neither by flow of data nor by flow of control. (One glance at the above list should convince you that you’d be unlikely to carry out all seven activities at one time!) However, the activities in a logically cohesive module are at least in the same category; in a coincidentally cohesive module, even that is not true.
The pseudocode and structure chart in will illustrate why coincidental cohesion is considered to be the worst level of cohesion.


   module miscellaneous functions
      uses func flag, operator message
      updates matnum, acc
      define trans record as 80 char
      define error switch as switch
      if func flag = 1
      then clear matnum to 0 /* matnum is a matrix */
         set acc to 1
      elseif func flag = 2
      then rewind tape-B
         print customer headings
      elseif func flag = 3
      then rewind tape-B
      elseif func flag = 4
      then read trans record
         if eof
         then set error switch to on
         endif
      else display operator message
      endif
      return trans record, error switch
   endmodule


<font face="Verdana,Arial,Helvetica,Helv,Swiss,Sans Serif"><font size="-1"><IMG SRC="images/pgssd_ch06_F6-12.gif" WIDTH=126 HEIGHT=202 BORDER=0></font></font>

Figure 6.12

If you think that the module shown in has very little going for it, you are absolutely right. All the nasty things I described about logically cohesive modules hold true for coincidentally cohesive modules, and then some!
For instance, if, while you were attempting to debug a piece of code, you saw a call to a logically cohesive module like this

CALL GENERAL IO ROUTINE USING 3, RECORD-A, RECORD-B, RECORD-C
you’d at least get the feeling that it was doing some kind of input and/or output, and you might be able to continue debugging without having to look at the actual code of GENERAL IO ROUTINE. But if you stumbled across the following call while doing midnight maintenance, you might think you were asleep and having a nightmare:4

CALL MISCELLANEOUS FUNCTIONS USING 4, BLANKS, DUMMY 1, DUMMY 2, TRANS RECORD, ERROR SWITCH
The only way you could possibly figure out what’s going on is to dig down among the actual code of MISCELLANEOUS FUNCTIONS and work out just which activity the module is carrying out on this occasion. MISCELLANEOUS FUNCTIONS, like all coincidentally cohesive modules, is a joke module, a white box whose insides are glaringly visible. Such modules make systems less understandable and less maintainable than systems with no modularity at all!
Coincidental cohesion, fortunately, is rare. Among its causes are the misguided attempts of morons to save time or memory (both usually unsuccessful); the shoveling of existing monolithic code arbitrarily into modules; and the illconsidered maintenance changes to modules with mediocre (typically temporal) cohesion, leading to the addition of flags.
Logical and coincidental modules are similar in their schizophrenia. Such modules have no well-defined function, so the boss module must send a completely artificial flag to tell them what to do. This violates the principle of independent black boxes, since the boss needs to know the internal details of the subordinates. The coupling to both kinds of module is horrendously obscure because of the use of a single parameter for multiple purposes.
Both logical and coincidental modules are such white boxes that to distinguish between them is quite subjective. But you could say that a coincidental module is a box of a whiter shade of pale.

6.8 DETERMINING MODULE COHESION

This chapter has defined, described, and given examples of each level of cohesion. But how do you actually set about determining the level of cohesion of a particular module? One good way is to write a short sentence that accurately, honestly, and fully names the module and describes its function. Usually, the structure of the sentence reveals fairly accurately the level of cohesion of the module.
Let’s take a look at some examples:
Functional cohesion. A module doing one function can be summed up by a precise verb-object name; for example,

Strong imperative verb Specific singular direct object
READ CUSTOMER TRANSACTION RECORD
CALCULATE NORMAL AUTO INSURANCE PREMIUM
DEDUCT FEDERAL TAXES
Sequential cohesion. A number of assembly-line functions show sequential cohesion, as in

VALIDATE TRANSACTION AND [USE IT TO] UPDATE MASTER RECORD
Communicational cohesion. A number of nonsequential functions working on the same data are the clue here; for example,

CALCULATE AVERAGE AND MAXIMUM EMPLOYEE SALARY
Procedural cohesion. Look for procedural or “flowcharty” names; for example,

LOOP ROUTINE or SWITCH MODULE
or, in worse cases, even less meaningful names.
Temporal cohesion. Time-related names are a giveaway; for example,

START UP, END OF JOB, or BEFORE...
Logical cohesion. The name is an umbrella or general-purpose one; for example,

INPUT ALL or EDIT MODULE
and to use the module, a flag is needed.
Coincidental cohesion. The name is silly or meaningless; for example,

FRUNK-MODULE, PROCESS-ROUTINE, ROUTINE-X9721-p
and to use the module, a flag is needed.

6.9 A DECISION TREE FOR MODULE COHESION

Some people prefer to use a decision tree in order to determine the level of cohesion of a module. To use the tree in , start at the left and proceed toward the right. When you answer a question about the module, follow the path indicated by your answer. You will eventually arrive at the level of cohesion for that module.


<IMG SRC="images/pgssd_ch06_F6-13.gif" WIDTH=396 HEIGHT=339 BORDER=0>

Figure 6.13

6.10 FINDING THE LEVEL OF COHESION

Cohesion is a measure of module strength and acts somewhat like a chain, holding together the activities in the module. If all the activities of a module are related by more than one level of cohesion, the module has the strength of the strongest level of cohesion. This is the chains-in-parallel rule.5 If activities within a module are held together by different levels of cohesion, the module has the strength only of the weakest. This is the chains-in-series rule.6
For example, a module may contain some activities related procedurally, while other activities may be merely coincidentally related. In this case, the module as a whole is only coincidentally cohesive.
However, what about the case of a module called GET RECORD, FORMAT IT, AND EDIT IT? This appears to indicate that the module is sequentially cohesive. But if it’s renamed GET VALID RECORD, it suddenly appears to be functionally cohesive, because all those activities make up the single problemrelated function of getting a valid record. But the same chains-in-parallel rule applies. The best that we can say of this module as a whole is that it’s functionally cohesive.
The level of cohesion of a module depends on the activities it carries out for its boss and is independent of where the module appears on the structure chart. For example, see . There is normally not any tradeoff between cohesion and coupling; they work together. Better (more) cohesion leads to better (less) coupling, which leads to better (more maintainable) systems.


<IMG SRC="images/pgssd_ch06_F6-14.gif" WIDTH=396 HEIGHT=788 BORDER=0>

Figure 6.14

6.11 COMPARISON OF LEVELS OF COHESION

presents a summary of the specific qualities of each type of cohesion. I would like to add a footnote to this section on the comparative virtues of each level of cohesion, a footnote based on my experiences as a consultant in evaluating the worthiness of modules in both commercial and scientific systems. It turns out that the severity of problems that a module in practice may cause falls into ranges, one range for each level of cohesion. Where a particular module lies within the range for its cohesion depends on a number of factors (e.g., size and degree of factoring, as discussed in Chapter 7). shows these ranges for each level of cohesion:
shows the lifetime cost that modules of each type of cohesion contribute to overall system maintenance. It indicates that you would not be excommunicated from the Structured Designers’ Union for creating an occasional small, clean, well-factored, logically cohesive module. But, if your system as a whole were filled with modules of dubious cohesion, then it would become obscure, inflexible, and expensive at the system level. If you find yourself regularly creating modules of below communicational cohesion, then I suggest that you hang up your template and take up a profession less challenging than Structured Design, lion-taming, for instance.


<IMG SRC="images/pgssd_ch06_F6-15.gif" WIDTH=306 HEIGHT=315 BORDER=0>

Figure 6.15

SUMMARY

Cohesion is the measure of the functional relatedness of elements (instructions, data definitions, etc.) within a single module. In a good design, the cohesion of every module is high. Together with coupling, cohesion is one of the best measures of the quality of a design.
A module may exhibit any of seven levels of cohesion depending on how the activities within the module are related. In sequence from best to worst, these seven levels are: functional (elements contribute to a single, problemrelated activity); sequential (activities within the module are connected in that the output from one serves as the input to another); communicational (activities share the same input or output); procedural (activities share the same procedural implementation); temporal (activities can be carried out at the same time); logical (activities appear to belong to the same general category); coincidental (activities have no relationship to one another).
The maintainability of modules with functional, sequential, and communicational cohesion tends to be significantly higher than that of modules of the four lowest levels of cohesion.

TABLE 6.2
Cohesion level Coupling Clean-
liness
of Imple-
mentation
Modifi-
ability
Understand-
ability
Effect on
overall
system
maintain-
ability
Functional Good Good Good Good Good
Sequential Good Good Good Good Fairly Good
Communicational Medium Medium Medium Medium Medium
Procedural Variable Poor Variable Variable Bad
Temporal Poor Medium Medium Medium Bad
Logical Bad Bad Bad Poor Bad
Coincidental Bad Poor Bad Bad Bad

EXERCISE

Each of the modules below is accompanied by a short sentence describing its activities. Determine as well as you can (without seeing each module on a structure chart) each module’s level of cohesion:

AFTIN1 after input, add control items and verify totals
AFTIN2 after input, write proof tape, add control items, verify totals
GENREPT produce report: either a sales report, a project status report, or a customer transaction report
SYNCH check syntactic correctness of space-vehicle guidance parameters
OUTTRAN print transaction and copy it to tape
UPCREDOUT update current credit record and write it to disk
STARTIT open files, obtain first transaction and first master record, and print page headings
NEWTRAN update record on file and get next transaction
CIRCDISP from an electrical connection matrix, produce a circuit diagram

Answer

AFTIN1 Sequential (if the added control items are the totals being verified)
AFTIN2 We know that AFTIN1 was sequential, but “write proof tape” is an activity whose strongest relationship to the other two is that it’s done at the same time (that is, “after input”]. Since “write proof tape” could be done either before or after the other two activities, the strongest cohesion for the whole module is temporal. This is an example of the chains-in-series rule.
GENREPT Logical
SYNCH Functional
OUTTRAN Communicational, also temporal, but since these two types of cohesion apply to the module as a whole, the stronger applies. This provides an example of the chains-in-parallel rule.
UPCREDOUT Sequential
STARTIT Temporal (not coincidental, because the activities are all done at one time)
NEWTRAN Procedural
CIRCDISP Functional (a complicated function high in the structure chart, no doubt, but a single problem-related function nonetheless)

No comments:

Post a Comment