Everything can be made up for—except modularity

“Write clean code,” “write tests,” “think long-term,” “quality, quality, quality!” That’s all they ever say. Easy to say… You tell yourself that all these consultants are nice enough, but that they’ve never run a business and are just horrible perfectionists. Enough is enough—things are going fine, so you do nothing.
It’s human nature, but that’s precisely the idea I’d like to challenge with you: things aren’t black and white—it’s not just quality versus “quick and dirty.” Quality is a continuum, a slider that you alone can adjust, with the right information.
Put another way, yes, you can aim for a little quality; you can pursue quality in a pragmatic way. It’s all a matter of priorities.
Software Quality: A Matter of Priorities
Let’s take a quick look at the big picture: rather than writing a long essay to define what quality is (it’s a valid question, but that’s not the point here), let’s approach it from the perspective of practices:
-
Testing? If you’re at the POC (Proof of Concept) stage, it’s out of the question; if you’re starting to build something sustainable, it would be good to have some. But, well, if you really have to make a call, you can always add more later (even if it’ll cost you more because the code wasn’t designed to be tested).
-
Technology? Do your developers want to switch from Angular to React? This is perhaps the most visible issue—and, paradoxically, the least important one. If the architecture is already in place and you have tests, these changes go fairly smoothly. Again, it’s never easy or risk-free, but it’s a common operation.
-
And what about… architecture? Of course it’s important, but on a small scale you can rework it fairly easily. For example, you can refactor your code to bring out a hexagonal architecture, and make testing easier at the same time. It’s no small feat, but it’s far from insurmountable.
What is insurmountable, however, is having to break the architecture on a large scale—that is, modularity. Consequently, by contrast, none of the considerations mentioned earlier take priority.
Your top priority: modularity
So if there’s one thing you must not neglect—that you cannot neglect—it’s the modularity of your product. To fully understand this, consider that a lack of modularity results in dependencies—all of which are avoidable—that have become entrenched on a large scale. You redo the electrical work, and it ends up causing a plumbing problem. Everything depends on everything else; it’s no longer possible to change anything without breaking something else. The immediate symptoms are regressions in production and skyrocketing deadlines.
Fortunately, working on modularity from the very beginning will cost you €10,000 to €20,000, because the planning is done on paper and, in the early stages of a product’s life, there is—by definition—no existing code to refactor. On the other hand, if you discover this issue after years of development, it will cost you 10 to 100 times more—sometimes several million euros. This order of magnitude is very real and stems from the fact that you’ll have to unravel the “spaghetti code” mentioned earlier—which, in practice, often leads organizations to start from scratch. We know there’s a better way, but you’ll still have a rough time.
So if there’s one thing you should take away, it’s that good modularity allows you to tolerate poor software quality locally and improve things later without breaking everything. A module can accumulate many flaws: lack of architecture, obsolete technology, mediocre code, abysmal technical debt, not a single test in sight… But good modularity limits the consequences to the module itself—that’s what matters most. The module right next to it can very well be a little gem of development and remain completely unaffected by the first one, thanks to well-designed modularity.
A matter of discipline
To be precise, modularity isn’t something you establish once and for all. You start by creating an initial functional map, which will evolve as you delve deeper into each topic and as the application is built.
The project deliverable (the “output”) lays an important foundation—initial boundaries that won’t be called into question—but beyond that, it’s the reasoning behind it (the “outcome”) that really matters, because that’s what will allow you to stay on the right track and work independently. Two ideas are particularly important—and counterintuitive:
-
There is no universal model: if I ask you to “model a table,” the only valid answer is “what’s it for?” (a surgical table? a dining table? a poker table?).
-
And the corollary: breaking things down by entity doesn’t work. So there will never, ever be a “table” module. What a false good idea!
Conclusion
Working on modularity is a highly focused effort that will prepare your company for exponential growth in a few years. Are your modules not as elegant as you’d like? So be it. As long as they’re properly defined, that’s a lot. That’s 90% of the work and an immeasurable advantage in the long run. Good modularity is what allows your teams to move forward in parallel without stepping on each other’s toes.