We worked on a project for several years centered around automobile auctions. Not surprising, one of the large classes in the system was Listing, which grew into a monster. Developers undertook several technical refactoring exercises to find ways to break up the huge class because it was causing coordination problems. Finally, a scheme was hatched to break out one of the key parts, Vendor, into its own class. While the technical refactoring was a success, problems emerged between the interactions by developers and business analysts: developers kept talking about changes to Vendor, which wasn’t a separate entity in their world. Developers violated what Eric Evans in DDD calls ubiquitous language on the project — make sure that all the terms on the team mean the same thing. While it made a few things more convenient for developers to split the functionality, the semantic coupling that defined the business process was violated, making our job more difficult.
Eventually, we unrefactored the Listing class back into a single large entity, because the software project revolved around it. We solved the coordination problem by treating Listing differently. Changes to Listing caused the continuous integration server to automatically generate a message to interested teams to encourage aggressive integration. Thus, we solved the coordination problem with an engineering practice rather than an architectural structure.
Figure 4-2. The relationship between modules, components, and quanta
As shown in Figure 4-2, the outermost container is the quantum: the deployable unit that includes all the facilities required for the system to function properly, including data. Within the quantum, several components exist, each consisting of code (classes, packages, namespaces, functions, and so on). An external component (from an open source project) also exists as a library, a component packaged for reuse within a given platform. Of course, developers can mix and match all possible combinations of these common building blocks.