Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I read from the seminal Code Complete book that method statements that require to be executed in order passing parameter from one to the next is a code smell and is an example of a sequential cohesion. Why is this not a good idea?

A contrived example of a sequential cohesion:

public Part createPart(input) {
        PartOne partOne = computePartOne(input);
        PartTwo partTwo = computePartTwo(partOne);
        PartThree partThree = computePartThree(partTwo);
        PartsBuilder partsBuilder = new PartsBuilder();
        return partsBuilder.add(partOne).add(partTwo).add(partThree).build();
    }

Here is the exert:

Several other kinds of cohesion are normally considered to be less than ideal:

Sequential cohesion exists when a routine contains operations that must be performed in a specific order, that share data from step to step, and that don't make up a complete function when done together.

An example of sequential cohesion is a routine that, given a birth date, calculates an employee's age and time to retirement. If the routine calculates the age and then uses that result to calculate the employee's time to retirement, it has sequential cohesion. If the routine calculates the age and then calculates the time to retirement in a completely separate computation that happens to use the same birth-date data, it has only communicational cohesion.

How would you make the routine functionally cohesive? You'd create separate routines to compute an employee's age given a birth date and compute time to retirement given a birth date. The time-to-retirement routine could call the age routine. They'd both have functional cohesion. Other routines could call either routine or both routines.

share|improve this question
1  
Does the book actually say its a smell? It's one of the better kind of cohesion on wikipedia, apparently sourcing Steve McConnell. –  Dave Hillier Mar 3 '13 at 17:27
    
@DaveHillier it says "several kinds of cohesions are normally considered less than ideal" and then goes on to describe sequential cohesion. So yes, it implicitly says this is a code smell. –  Geek Mar 3 '13 at 17:29
    
"communicational and sequential cohesion are very good; and functional cohesion is superior." is it that incorrect on wikipeda? –  Dave Hillier Mar 3 '13 at 17:30
    
Had a look in the book. Your example doesn't really demonstrate sequential cohesion of the bad kind. –  Dave Hillier Mar 3 '13 at 17:37
1  
"It only happens to use the same birth date". Your example, is an example of functional cohesion as they inputs and outputs are the same. If the results and inputs where stored in member variables it would be an issue. –  Dave Hillier Mar 3 '13 at 17:46

5 Answers 5

up vote 8 down vote accepted

I think the example is actually Functionally Cohesive not Sequentially Cohesive. The inputs and outputs just happened to be related, but the methods could have been used independently. "Other routines could call either routine or both routines." - other routines could call any of the computePart methods.

Here is an example that I think better demonstrates the sequential cohesion.

public Part createPart(input) {
        setInput(input);
        computePartOne();
        computePartTwo();
        computePartThree();
        PartsBuilder partsBuilder = new PartsBuilder();
        return partsBuilder.add(this.PartOne).add(this.PartTwo).add(this.PartThree).build();
    }

Where as the above example has coupling between the stages here as the parts are inside the object and you can't really use them independently. They are tightly coupled - they actually "share data from step to step".

share|improve this answer
    
So you disagree with my "But why return data back to the caller only to require it back again a few calls later?" from my answer? Or are you just describing the terms, not advocating one over the other? If you think I'm wrong, I'm interested in your reasoning - maybe I'm being an idiot. –  Steve314 Mar 3 '13 at 18:34
    
Actually, if the context was pure-functional programming, I'd have probably mentioned referential transparency myself - but on the assumption that there's state within the object either way... –  Steve314 Mar 3 '13 at 18:37
    
@Steve314 - No I don't disagree. No advocacy. I think that the context free example is a little confusing, it could be good or bad. It really dependents on the usage of the parts. But I kept the same example to match the OP. –  Dave Hillier Mar 3 '13 at 19:07

I have no idea if this is what the authors had in mind, but...

If a set of methods are required to be executed in order passing parameter from one to the next, there's two possibilities...

  1. Static typing enforces the correct ordering due to the parameters required and return values.

  2. Static typing cannot enforce the ordering, perhaps because the same types recur in several places but the values aren't interchangeable.

In my view, the second case is pretty bad because either there's some run-time enforcement of the sequence (tracking state within the object) or there's no error checking at all. As far as possible, I'd prefer my coding errors to be detected at compile-time.

The first case is actually almost as bad for the same reason. OK, you can't get the sequence wrong without getting a compile-time error. But you can leave the sequence incomplete. Or call the same method twice, discarding the results from the first call. There's lots of ways to creatively do things wrong that static checks won't detect.

Of course if you're OK with run-time state checking within the class, that's fine. But why return data back to the caller only to require it back again a few calls later? Why not keep that with the state you're already tracking?

Also, what are the alternatives? One is to use a single call, which might mean supplying a huge list of parameters to that call, which is another code smell. To avoid that, perhaps you'd group those parameters - provide a parameter block to a single call.

Rather than an old C-style parameter block, you'd probably prefer a class. But once the data is provided to that class via method calls, you're back where you started - lots of methods vs. one with many parameters, and possibly needing to sequence the methods.

share|improve this answer

In my opinion above is an simple example of the sequential cohesion. If you look at the function you will notice that it contains functions which depends on the inputs and outputs of the other functions(pipeline). I don't know why there is a confusion regarding this concept.

share|improve this answer

I think a big part of this problem was the choice of words. "Less than ideal" does not necessarily imply bad code. If you look into Ed Yourdon and Larry Constantine's original book Structured Design, you will see that the authors attribute a subjective scale to the different levels of cohesiveness:

  • 0 - coincidental
  • 1 - logical
  • 3 - temporal
  • 5 - procedural
  • 7 - communicational
  • 9 - sequential
  • 10 - functional

Note that the scale is not linear, and sequential (9) is very close to functional (10). The authors also state that "the highest three suggest simple and inexpensive designs".

As you see, this doesn't support the claim that the code in your example "is not a good idea".

share|improve this answer

The cohesion hierarchy is very useful but you are straining at gnats in this instance. There are useful, if subtle distinctions, to be made at the high end of the spectrum. However, those distinctions do not amount to a "smell". When you get to the lower end, you can talk about smell (and even stench, in the worst cases).

The example is contrived. We could modify the example slightly by, for instance, making the age calculation process non-linear, with a set of interval calculations that require reading a database table. Therefore, from a functionality point of view, the age calculation is cohesive, and, by extension, the retirement calculation that depends on a correct age calculation are also functional.

There is still a sequential dependency between the two calculations -- the age MUST be calculated before the retirement date. Hence, one calculation must occur before the other, regardless if they are called from the same function or not. When ordering of function calls must be imposed, something must bear the responsibility for sequencing the calls.

In conclusion. No code smell. Just something that might be improved for very little benefit.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.