Code Complete is one of those books every developer should read. There is a section in chapter 5 of this book which talks about coupling. Although coupling between software entities is not totally avoidable in all of its flavors in even simple programs, there is a special kind of coupling that we developers should all condemn: Semantic coupling. According to Code Complete:
“The most insidious kind of coupling occurs when one module makes use, not of some syntactic element of another module, but of some semantic knowledge of another module’s inner workings”
I have written some semantically coupled code, I must confess. Not a very shocking confession, though. I have found out that pretty much all the developers I have worked with, have semantic coupling in their criminal records. With the aim of making the programming world a bit more lawful, let me show you two basic examples of semantic coupling I found in my own code:
Disclaimer: Class and method names have been changed to protect the author’s customers and the author’s customers’ customers.
Example 1. Avoiding calling a method because another method does it.
class SomeUIComponent {
 public void init() {
  setSizefull();
  ...
 }
 public setSizefull() {
  ...
 }
}
class AnotherClass {
 public void smartassMethod() {
  SomeUIComponent c = new SomeUIComponent();
  c.init();
  // I know I need to call c.setSizeFull() but I also know
  // SomeUIComponent.init() will call that, so it's fine :D
 }
}
No, that is not fine. And stop smiling. I have also done this while thinking, “I know this is not very good, but most of the instances of SomeUIComponent
will be full size, so let’s put that in the init method.” Even if the reason sounds okay, that is still semantic coupling, my friend.
Example 2. Downcasting.
class User {
 ...
}
class MightyUser extends User {
 public mightyMethod() {
  ...
 }
}
class AnotherClass {
 public void method() {
  MightyUser u = new MightyUser();
  doThatThing(u);
 }
 public void doThatThing(User u) {
  // I know they will pass a Mighty one, so let's cast it :D
  MightyUser u2 = (MightyUser) u;
  u2.mightyMethod();
  ...
 }
}
Let’s cast it? You cynical developer. That is downcasting. And stop smiling again. Sometimes I catch myself thinking, “I should change the method’s signature,” but I find a reason no to do it. Maybe it’s impossible to change the signature due to external constraints (the method is declared in an interface or superclass, for example). It might sound like a good reason, but again, still semantic coupling.
If you find something like the above while coding, look at it as an opportunity to think of a better design. There is plenty of room for improvement when you face that phenomenon called semantic coupling, a disgusting flavor of coupling you don’t really want to taste. Then you can smile if you want.
Enjoyed this post? I can help your team implement similar solutions—contact me to learn more.