This post might be considered academic, but it offers a good overview of what I believe to be the guiding principles in terms of software modularity.
Let’s start with a little bit of background. Sometimes the way businesses are modeled are constrained by the available technology, which may block innovation, change and even growth in the business. Instead of establishing barriers, technologists should keep pushing for the evolution of technology, and keep fighting people who are against this evolution.
You may be fortunate enough to live in a better world, where software is built according to real business goals, bringing real value to the company. Great! However, this is not quite enough yet. Business models keep changing quickly, which means that the software in place ought to be flexible enough to support these changes, and also expansible enough to support that always desirable growth.
The real problem here is the following: How can we simultaneously achieve flexibility, expansibility, and maintainability in software architecture? This is a very tough question, but the answer is rather simple: “Achieve this by using high modularity levels”. Unfortunately, this cannot be achieved by some sort of magic, but only by dint of a focused architectural effort, as described below.
I like thinking of a module as just a block of code – this block of code can vary from being a method to being a class, a component, and a (web) service. Now, the modularity level evaluates the usage of modules in a given software architecture, mainly when it comes to encapsulation, coupling, and cohesion. Several authors have written about modularity, but my personal choice is Bertrand Meyer. His study on Object-Oriented Software Construction presents five criteria as a guide to evaluating modularity.
- Modular Decomposability – A software construction method satisfies Modular Decomposability if it helps in the task of decomposing a software problem into a small number of less complex sub-problems, connected by a simple structure, and independent enough to allow further work to proceed separately on each item.
- Modular Composability – A software construction method satisfies Modular Composability if it favors the production of software elements which may then be freely combined with each other to produce new systems, possibly in an environment quite different from the one in which they were initially developed.
- Modular Understandability – A software construction method satisfies Modular Understandability if it helps produce software which a human reader can understand each module without having to know the others, or, at worst, by having to examine only a few of the others.
- Modular Continuity – A software construction method satisfies Modular Continuity if, in the software architectures that it yields, a small change in the problem specification will trigger a change of just one module, or a small number of modules.
- Modular Protection – A software construction method satisfies Modular Protection if it yields architectures in which the effect of an abnormal condition occurring at run time in a module will remain confined to that module, or at worst will only propagate to a few neighboring modules.
Mr. Meyer also presents the following six principles.
- Linguistic Modular Unit – Modules must correspond to syntactic units in the language used.
- Few Interfaces – Every module should communicate with as few other modules as possible.
- Small Interfaces – If two modules communicate at all, then they should exchange as little information as possible.
- Explicit Interfaces – When two modules communicate, this fact must be obvious.
- Information Hiding – All information about a module should be private to that module unless it is specifically declared public.
- Open & Closed – A module should be open for small changes (with no impact on its interface), and closed in terms of readiness.
Both lists are quite self-explanatory, aren’t they?
From my point of view, software modularity is an overused expression, and people are usually not familiar with any criteria or principles for evaluating the level of modularity, such as the ones listed above. This post aims to provide a means whereby the often misunderstood concept of modularity is made explicit, while providing a foundation for designing truly loosely-coupled modules. I hope you find it useful.
Related posts:





November 27th, 2008 at 4:40 pm
Nice article and I absolutely agree.
We have to take these principals and not only apply them in our code, but also scale it up into the services/platforms we offer, business logic used etc.
Especially these days when we are slowly branching away from software as a service, but more towards platforms as a service.
We must create code/modules/services to be as loosely-coupled and agnostic as possible which ultimately shows others that we are developers/architects with a readiness towards change.
November 28th, 2008 at 12:56 pm
Hello Dewald, thanks for your comment. I agree with your thoughts.
We’ve been working on a highly changeable environment, building internet applications that should keep changing in order stay cutting edge and useful to people.
Loosely-coupled services have been the best shot for a while, and both interfaces and abstract software pieces play a very important part here, as you know.
Cheers!
November 28th, 2008 at 5:40 pm
Excellent.
Reminded me of http://www.cs.auckland.ac.nz/~ewan/essays/agenda.html which argues that most people in software view the adjective “modular” purely as a synonym for “good” (as opposed to any formal understanding of what modularity might actually mean).
Totally agree re thinking of a module as a block of code, which could be a low- (method, class) or high-level (component, web service). But I would interject that there is (should be) a level inbetween, what we might broadly think of as packages (or class clusters a la Booch). I wrote a post on this just yesterday and would be interested whether you agree with this.
November 30th, 2008 at 2:34 pm
Hello Ian. Thank you for contributing.
Definitely agreed, I also think of a package as a proper module. One of my major references in Software Engineering is Ivar Jacobson, who stated that software development processes should iteratively and incrementally refine software artifacts (or models if you like). According to this statement, the Use Case model, Analysis Model, and Design Model are gradually and parallelly evolved by the architect. Software modularity must be thought of from the beginning, as a cross-model concern.
Specifically about the Analysis Model, high level classes may be grouped together in packages, when modularity becomes totally evident for the first time. Therefore, the architect should focus mainly on dependencies among packages, and package boundaries. The modularity criteria and principles take place here as well.
However, during the Design Model drafting, when technology-specific concerns pop up, a compiled language may empower the architect to place one logical package scattered in more than one (physical) component, with no architectural drawback. If this is the scenario in place, then dependencies among components are the ones that matter the most at the end.
December 4th, 2008 at 1:35 am
Hi Ottavio.
Sorry I was a little slow following up but there is an overlap between your comments here and a follow-up to the findbugs post I wanted to write. It’s there now and I think you’ll find it interesting.
The nub is that there are architectural components and there are physical components (like packages). These may have a one-to-one correspondence but this is not essential. It follows that tangled packages are a smell but tangled architecture is … well more than that. In the extreme case, it equates to no architecture at all (just a bunch of classes).
Chunks of the piece are a bit tool-centric to get the views of the architectural components (Structure101 transformations), but the issues are, as ever, generic.
Cheers, Ian