Modules
The terms “module” and “component” are often used interchangeably, which causes confusion. As I mentioned earlier, any system is composed of components. Therefore, a module is a component. However, not every component is a module. To design a flexible system, it’s not enough to decompose the system into an arbitrary set of components. Instead, a modular design should enable you to alter the system by combining, reconfiguring, or replacing its components—its modules.
Let’s consider two examples of modules from our everyday lives (Figure 4.1):
LEGO bricks are a straightforward illustration of modularity in action. Each brick is a self-contained unit that can be connected with other bricks to form a variety of structures. The ease with which these bricks can be assembled and disassembled illustrates a perfectly modular system.
Another widespread example of modularity is the interchangeable camera lenses used by photography enthusiasts. The ability to switch lenses enables photographers to adapt their cameras to different shooting conditions and achieve various effects, all without requiring multiple cameras.
Figure 4.1 Modularity in real-life systems
(Images: left, focal point/Shutterstock; right, Kjpargeter/Shutterstock)
The success of a modular system depends on the design of its modules. To enable the desired flexibility of a system, its design has to focus on clear boundaries and well-defined interactions between modules. To reason about the design of a module, it’s helpful to examine three fundamental properties describing a module: function, logic, and context:2
Function is the module’s goal, the functionality it provides. It is exposed to consumers of the module through its public interface. The interface has to reflect the tasks that can be achieved by using the module, how the module can be integrated, and its interactions with other modules.
A module’s logic is all about how the module’s function is implemented; that is, the implementation details of the module. Unlike function, which is explicitly exposed to consumers, a module’s logic should be hidden from other modules.
Finally, a module’s context is the environment in which the module should be used. This includes both explicit requirements and implicit assumptions the design makes on the module’s usage scenarios and environment.
These fundamental properties provide valuable insights into a module’s role within the broader system, as summarized in Table 4.1.
Table 4.1 Comparison of the Three Fundamental Properties of a Module
Property |
Reflects |
Type of information |
---|---|---|
Function |
Module’s goal |
Public, explicit |
Logic |
How module works |
Hidden by the module |
Context |
Assumptions about the environment |
Public, less explicit than function |
To effectively design a module, its function should be clear and explicitly expressed in its public interface. The module’s implementation details, or logic, on the other hand, should be hidden from consumers by the module’s boundary. Ultimately, a clear and explicit definition of the context is essential for consumers to be able to integrate the module, as well as to be aware of how the module’s behavior might be affected by changes in its environment.
Let’s have a look at how these properties are reflected in the aforementioned modular systems: LEGO bricks and interchangeable camera lenses.
LEGO Bricks
The goal of the overall system—the LEGO constructor—is to form structures from individual building blocks. The modules of the system are LEGO bricks. As a module, each brick has the following properties:
Function: A brick’s goal is to connect with other bricks. It’s explicitly reflected by the “integration interface”: studs and holes through which it can be easily attached to other bricks.
Logic: The bricks are made from a material that supports the required weight to build sturdy structures and guarantees reliable attachment to other bricks.
Context: Since LEGOs are (generally) a toy for children, they have to be safe and appropriate for kids to play with. Furthermore, because of their purpose as a creative and fun playtime tool, using LEGO bricks to build actual houses would not be a good fit, as they are not designed or intended for such a task.
Camera Lenses
As I mentioned earlier in this chapter, interchangeable camera lenses enable photography enthusiasts to adapt to different shooting conditions without having to use multiple cameras. Both the camera body and the attachable lenses are modules. Let’s focus on the properties of camera lenses as modules:
Function: Enable capturing images with specific properties, such as focal length or aperture. The interface defines what kinds of cameras the lenses can be used with, as well as the supported range of optical capabilities.
Logic: The inner workings of lenses allowing them to be connected to a camera and capture the required optical capabilities.
Context: The supported ranges of camera models, as well as varying functionalities for different cameras (e.g., whether autofocus is supported or not).
Now that we have established an understanding of modularity in general, let’s explore how these concepts apply in the context of software design.