Rethink code cohesion

Emergent Design: time to relate

Beginner's guide to SSL certificates

The methods reverseCharacters() and isMightyMouse() are easy to name because they each do a single, identifiable thing. It also helps with debugging. If the characters are not reversing properly, I know exactly where to look to find the bug, because the responsibility for doing this is clearly assigned to the properly named method, and only that method.

Cohesion of perspective level

Another aspect of cohesion you should be aware of is the level of perspective at which a method operates. Put simply, methods tend to accomplish their functionality by either of the following:

  • Code logic directly in the method
  • Calling other methods

The preceding process() method has a little bit of logic in it, but it is purely for sequencing the other methods and organizing the results of their actions. Mostly, process() calls reverseCharacters() and isMightyMouse(), where the actual work is done. This aggregation of behavior that process() does is at a level of perspective we call specification.

Levels of perspective

In UML Distilled: A Brief Guide to the Standard Object Modeling Language, Martin Fowler refers to the levels of perspective that Steve Cook and John Daniels identified in their book Designing Object Systems. The three types of perspective are conceptual, specification, and implementation.

  • The conceptual perspective deals with the system objects, which ideally represent entities in the problem domain I am writing for. If I am designing an application for a bank, these might be account, transaction, statement, customer, and the like.
  • Specification means the public methods that form the interface of each object, but also the private methods to which they are delegated (see the example code on this page). So, process(), being the only public method of Application, is decidedly a specification-level issue, but from the point of view of process(), so are reverseCharacters() and isMightyMouse(). This is because process() is concerned with what they do (how they are called, what they return), but not how they do it.
  • Implementation is concerned with the code that does the actual work. Nice that we still have that, eh?

The reverseCharacters() and isMightyMouse() methods are implementation-level methods; they have the code that does the dirty work.

It would be overstating things to suggest that I always write methods that are purely at one level of perspective or another-even here, process() has a little bit of logic in it, not just a series of method calls. But my goal is to be as cohesive as possible in terms of levels of perspective, mostly because it makes the code easier to read and understand.

It would not be overstating things to suggest that I always strive to write methods that are cohesive in the general sense, that they contain code that is all about the same issue or purpose. When I find poorly cohesive methods, I am going to change them, every time, because I know that method cohesion is a principle that will help me create maintainable code, and that is something I want for myself, let alone my team and my customer.

Class cohesion

Classes themselves also need to be cohesive. The readability, maintenance, and clarity issues that, in part, drive the need for method cohesion also motivate class cohesion.

In addition, we know we want our classes to define objects that are responsible for themselves, that are well-understood entities in the problem domain. A typical mistake that developers who are new to object orientation make is to define their classes in terms of the software itself, rather than in terms of the problem being solved. For instance, consider the following code:

public class BankingSystem {
  // No "method guts" are provided; this is just a 
  // conceptual example
  public void addCustomer(String cName, String cAddress, 
                          String accountNumber, 
                          double balance) {}
  public void removeCustomer(String accountNumber) {}
  public double creditAccount(String accountNumber, 
                              double creditAmount) {}
  public double debitAccount(String accountNumber, 
                             double debitAmount) {}
  public boolean checkSufficientFunds(String accountNumber, 
                                      double checkAmount) {}
  public void sendStatement(String accountNumber) {}
  public boolean qualifiesForFreeToaster(String accountNumber){}
  public boolean transferFunds(String fromAccount, 
                               String toAccount, 
                               double transferAmount) {}

It is easy to imagine the thought process that leads to code like this: "I am writing a banking system, and so I will name the class for what it is, a BankingSystem. What does a banking system do? Well, I need to be able to add and remove customers, manage their accounts by adding to them and withdrawing from them," and so on.

Top 5 reasons to deploy VMware with Tegile

More from The Register

next story
Nexus 7 fandroids tell of salty taste after sucking on Google's Lollipop
Web giant looking into why version 5.0 of Android is crippling older slabs
Be real, Apple: In-app goodie grab games AREN'T FREE – EU
Cupertino stands down after Euro legal threats
Download alert: Nearly ALL top 100 Android, iOS paid apps hacked
Attack of the Clones? Yeah, but much, much scarier – report
Microsoft: Your Linux Docker containers are now OURS to command
New tool lets admins wrangle Linux apps from Windows
Bada-Bing! Mozilla flips Firefox to YAHOO! for search
Microsoft system will be the default for browser in US until 2020
prev story


Why and how to choose the right cloud vendor
The benefits of cloud-based storage in your processes. Eliminate onsite, disk-based backup and archiving in favor of cloud-based data protection.
A strategic approach to identity relationship management
ForgeRock commissioned Forrester to evaluate companies’ IAM practices and requirements when it comes to customer-facing scenarios versus employee-facing ones.
Reg Reader Research: SaaS based Email and Office Productivity Tools
Read this Reg reader report which provides advice and guidance for SMBs towards the use of SaaS based email and Office productivity tools.
Mitigating web security risk with SSL certificates
Web-based systems are essential tools for running business processes and delivering services to customers.
Storage capacity and performance optimization at Mizuno USA
Mizuno USA turn to Tegile storage technology to solve both their SAN and backup issues.