@pinzonjulian ‘s post, [Practical advice after Shopify’s Packerk Retrospective]( Practical advice after Shopify’s Packerk Retrospective ) got me thinking–especially after I saw Eileen Uchitelle’s RailsWorld 2024 talk, The Myth of the Modular Monolith, and this post from Brandon Weaver.
I couldn’t get away from the thought that we seem to lack a basic consensus on what modularity is, what problem modularity is trying to solve, and what are sound practices for implementing modules.
I ended up writing a series of articles on this (this one is probably the most relevant). Not because I’m an expert or authority (I’m not), but because I wanted to sort out my thoughts–and because any conversation needs a starting point. ![]()
In the article, I quoted this passage from 99 Bottles of OOP on object-oriented design because I think it is equally applicable to modularity:
Where you once optimized code for understandability, you now focus on its changeability. Your code is less concrete but more abstract—you’ve made it initially harder to understand in hopes that it will ultimately be easier to maintain. This is the basic promise of Object-Oriented Design (OOD): that if you’re willing to accept increases in the complexity of your code along some dimensions, you’ll be rewarded with decreases in complexity along others. OOD doesn’t claim to be free; it merely asserts that its benefits outweigh its costs.
(emphasis added)
If modularity efforts require all stakeholders to buy in to the validity of the exercise, then there needs to be clarity around the theory, the practice, and the goal of modularity. How else can they measure the benefits against cost?
I also strongly feel that the creation of conventions to guide implementation would be hugely helpful. I propose four to start (at least one of which is sure to be controversial). Again, I don’t claim to be “right,” I just want to start a conversation: if not these conventions, then what?
- Packs/modules are only for domain logic. No controllers, views, or other UI objects should be allowed (just use namespaces to organize UI objects, if needed).
 - Only coupling between packs/modules should be scrutinized and regulated for purposes of dependency graphs. Coupling with the UI layer is expected behavior (although this doesn’t mean abandoning interfaces).
 - Only data objects should be passed to and from packs/modules.
 - Packs/modules must own their own data (persistence).
 
I argue that autonomy should be the overarching goal of modularity, and that these conventions promote autonomy. I would love to hear your thoughts. ![]()