Welcome back to another post! Let’s talk about one of the most important software engineering principles - modularity.

What is it?

Modularity is basically breaking your system down into a set of distinct modules, each responsible for a certain aspect of your system’s overall functionality.

But IMO, it has a second part to it. I believe that modularity includes the ability to combine/assemble/disassemble different modules to change behavior of your system. I haven’t seen this be included in all definitions of modularity, but I see it as an essential part.

Why is it important?

The most obvious benefit of modularity is that your system is just easier to understand, simply because things are broken into digestible little easy-to-understand chunks.

The most important benefit of modularity though, is that it encourages and almost naturally leads to low coupling and high cohesion (aka single responsibility principle)!

And these two things, low coupling and high cohesion, are the holy grail of good software engineering. They make your system easy to understand, easy to develop, easy to maintain, and easy to test.

How/why does modularity encourage low coupling and high cohesion?

When you focus on breaking your system into a set of components where each component is responsible for a single aspect of your system’s functionality, you naturally end up with highly cohesive components, by definition. Now, it’s important to note that you don’t automatically get high cohesion simply by breaking down your system. You gotta put some effort into it. Break it down into components that make sense, components that are small, and that don’t have several responsibilities/aspects. So do your part!

When your components are cohesive, they will have less dependencies. This is because cohesive components have less responsibilities, and therefore need less things to depend on. So high cohesion naturally leads to low coupling.

So, in summary, modularity encourages low coupling and high cohesion.

How/why does low coupling and high cohesion lead to so many benefits?

There are two key things to understand here:

  1. When a change request comes in, it is usually related to one (or maybe a few) aspects of your system. When your system is modular/cohesive, these change requests map to roughly one component each! So if there is one small change request, you will only need to touch one small component! Clearly, this helps with maintenance!
  2. When you then proceed to making a change to the one component that needs to be changed, if your system is loosely coupled, this change will not cause a ripple effect, thus you won’t need to change any other components! This is a massive gain to maintainability!

As you can kinda see by now, the concepts of modularity, low coupling, and high cohesion are very closely related. And you can even throw in the single responsibility principle (SRP) in there too because it’s the same thing as high cohesion IMO.

All these things (modularity, cohesion, loose coupling) result in all the following benefits:

  • Maintainability - This one should be obvious by now. When you have a change request come in, only one component needs to be changed due to high-cohesion/SRP/modularity, and the change to that component won’t affect the other components due to low coupling. In fact, you don’t even need to consider other components. This makes maintenance a goddamn breeze!
  • Testability - When your components are modular, cohesive, and loosely coupled, it is often easy to instantiate them in isolation. And being able to instantiate things in isolation is key to testability! You can easily isolate your components in a test harness, dependency inject them with mocks, and go crazy with unit tests. Truly amazing!
  • Easy to understand - A modular, cohesive system is just easier to explain and understand. This one is just obvious haha :).
  • Easy to develop - This is a bit similar to maintainability, but initial development is sometimes seen as a different thing than maintenance, so I’ll mention it here. Developing small, cohesive, loosely coupled components is just easier. For example, if you are responsible for developing the Payment component, you don’t have to worry about the User, Order, etc components. You can get familiar with payments and start dev-ing right away. You can also unit test your component without the others being ready (thank you mocks 🙏).
  • Easy to refactor - You can consider refactoring as a special form of maintenance. ‘Nuff said. Haha :)

If you take things one step further and you implement your modular, loosely coupled, cohesive system as microservices, you can get additional benefits!

  • Independent tech stacks - Each of your components can be developed in their own language/tech-stack.
  • Independent scaling - Each of your components can be scaled independently.
  • Independent deployment - Each of your components can be deployed independently.

Conclusion

YEEHAW! That’s a lotta benefits! Let’s recap.

  • Modularity is basically breaking your system down into a set of distinct modules, one for each aspect of your system’s functionality.
  • Modularity encourages low coupling and high cohesion. You still gotta put in some effort, but it makes it more natural/easier to achieve these things.
  • Modularity, cohesion, and coupling are all closely related. Often one leads to or relies on the other(s).
  • Modularity, cohesion, and low coupling are, IMO, the holy grail of software engineering. They essentially allow you to develop/maintain/test/refactor/understand your system on a piece-by-piece basis. You don’t have to understand the whole thing if you just need to develop/maintain one piece.
  • If you go one step further and implement your modules as microservices, you get independent tech stacks, scaling, and deployment. Whoowee!

That’s it, have an awesome day!