Modularity: (Not) Re-Inventing the Wheel, One Spoke at a Time

Modularity and loose coupling are indications of good software design. In fact, breaking complex problems into sets of more easily solved subproblems is a a strategy that good computer scientists employ when designing algorithms to solve computationally difficult problems. But the real advantage of software modularity, from a developer’s perspective, is that it reduces the amount of work we have to do when maintaining our code.

For example: say your business logic suddenly dictates that you add two numbers in a certain way. You have two options. You can either go through thousands of lines of code and implement the special addition function in every place that the addition is required, or you could create a function that would accept two parameters, apply the correct addition logic, and then return the result to the calling function.

Using a function here means that:

  1. The logic only has to be coded once.
  2. If the logic ever changes, it only needs to be changed in one place.
  3. The business logic is encapsulated inside the function; the caller need not be aware of any implementation details.

To developers with any experience, the advantages to modularization may seem obvious. Yet even veterans fall into the trap of programming convenience: sometimes, it’s easier to simply make a data member public rather than go through the hassle of creating accessor methods or properties. This is almost always a mistake. Why? Because every time a developer makes a method or data member public, he signs a contract to support that method for the rest of eternity, or else risk breaking dependencies whenever a client class depends on the public member. When you make a method public, you are saying to client classes “this is okay to access; it will always return this result.” It’s like a wedding vow: don’t go through with it unless you’re sure! (Weddings are expensive, and so is reworking large amounts of code due to broken dependencies).

The key question to ask oneself when designing classes is: “What should I hide?” Make public only what you absolutely have to.

Employing this strategy when developing classes and functions has many advantages. When classes are loosely coupled (i.e., they do not depend on one another), this adds extensively to code reusability. Say, for instance, that your company does a lot of work with Excel, and you often have to read in CSV. You could either write a CSV parser for every application that you develop, or you could generate a single class to take care of CSV parsing and re-use it in every project where it’s required. Yes, CSV is trivially easy to parse, but that isn’t the point. The point is: avoid re-inventing the wheel! If you ever feel that the code you’re working on might be useful in other projects, make it independent of whatever program you’re writing it for and you can re-use it later.

Many software compainies take advantage of code reusability by maintaining their own in-house repository of modularized code. These repositories serve as libraries of solutions to common programming problems. Indeed, this is exactly the purpose that the Standard Template Library (STL) attempts to serve.

In summary, writing modularized code may be inconvenient at times, but it’ll save you from a lot of headaches later on. More importantly, it saves your time — and your time is money.