Express and easily manage complex dependencies between classes and components within a single layer, by grouping them into Modules.
The most popular and common 3 layer software architecture was created from the need to concise and clarify the dependency graphs between classes and components. Had we kept just a single layer for the whole application, those graphs would be unmanageable and tangled. It would be impossible to define any rules about the importance of one component over the others. It would also be impossible to define the 3 different responsibility classifiers which are explicitly expressed by the 3 layers. When we belong a class to the layer, we explicitly denote it to solve one of these general responsibilities.
Very similarly, in many of the modern software projects, layers have become very large themselves, as they contain lots of classes and those depend on each other. Sometimes this dependency graph is so complex that it naturally calls for splitting layers into more granular sub-layers. Many brave developers have gone a far way by being creative about this, and have introduced many new layers in their applications. But at some point this approach becomes somewhat arguable - can there really be so many layers? If so, then why do these all books talk about 3 layers only? and if not, then how do we manage the complex dependency graphs within a large layer?
If we simply want to group interrelated classes together, there is no necessity to introduce yet another layer. Instead, we can introduce a Module.
I call group of classes a Module, which represents some functionality of the application. I use term "component" to represent a class or any other element (e.g. structure or enumeration) which is grouped within a module. Thus, module consists of components. Module can be considered a more granular layer of the application.
Modules come with many similar characteristics to those of a layer (detailed relationships diagram is below):
All these relationships are expressed below.
Modules come with additional benefits, which we can't really enjoy with layers.
Quite unfortunately, applications supporting plugins are referred to as modular applications. That's because those applications support loading new plugins dynamically, as long as they all follow a unified interface structure expected and executed by the application. I'd rather call those plugins, since the uniformity of the interface is not so much specific to the modules, although it can be implemented for modules too.
This confusion is partly guilty in very small number of application frameworks supporting modules as they are explained in this article. Almost all papers talking about modular architecture explain plugins (not modules) and how to dynamically add and load new plugins into the existing application.
Some of the existing frameworks (e.g. require.js) have used module to denote something different than what I explained here.
So far, only angular.js's Module stands closest to the module explanation that I provided above. However, it's a complete application framework, and the choice is "all or nothing" (if you use angular, you need to use modules). Also, importance of the module is either not well explained or not well understood, since eventually developers end up having a single giant angular module, depending on all other existing modules in the application. On the other hand, I expect that the application does not necessarily need a module, and it can be defined only when the necessity exists (not "all or nothing" approach). For simple layers, modules will not be needed. For complex and evolving software layers, modules will be very nice to have.
I still can't name a framework supporting modular architecture for strongly typed languages such ac C# (my favorite). I hope it's somewhere there, and it's just I haven't found it yet.