What is modular
On the transpiler part like typescript this problematic is handled without any third-party libraries or the need to use modular design patterns.
Also the ECMA 2015 was an important step forward as the modules became official part of the ECMA specification. Recently, the
seems to be supported by most browsers.
On the other parts of the specification, namely the
statements and linked constructs the implementation is still poor and we will have to wait some more time for the specification to become the implemented reality.
At the moment, we have to use transpilers to leverage the functionality and constructs the modules provides us. In the case of webpack it’s incorporated to the engine, so we can use the ECMA module syntax as well as we can setup some other module syntaxes.
In the case of Typescript, the modules are included in the language compiler. All we have to do, is setup the module resolution setup in the according tsconfig.json.
These are only few points advocating the usage of the module in the frontend development process. The usage of the modules itself provides us important tool to keep the codebase coherent and architecture readable, but it’s not automatically a salvation. There are some more rules that should be taken into account, when considering the design of the modules in your app.
What CRUST stands for
Crust stands for Consistent, Resilient, Unambigous, Simple and Tiny. These are basically few rules that, when imposed to our process of designing the modules, should ensure the development process to be easier and final product to be more maintainable.
This says us to keep the surface API of the modules and it’s shape of the exposed methods similar in the core principles. Further the shape of the output should not vary with different inputs. The consumer should not bother with handling the output that has different shape changing with the input provided. It’s OK to provide different output for failures and successes. But among these two types of result, the output should be as coherent as possible.
This term depicts the necessity to consume the input in a few different shapes. It’s always up to the discussion among programmers, what the polymorphic attributes should look like. The golden rule here is to provide handling of the most frequent use cases and wait with further enhancing till the further necessity appears. Just as it is important to provide a few different ways of accepting the input, it is also important to handle the wrong inputs with the properly designed errors.
Means to ensure that the consumer of the module API can always expect the same shape of the output. There should not be dependency of the shape of the output on the parametrs provided. In the opposite case, the consumer would be forced to handle many possible outcomes from the API, which would lead to cluttered code.
Means the surface of the modules’ API should be only that complex as the use case the API handles. The API should accept only few compulsory parameters, without which the module could not provide the proper solution. Everything other should be provided in options object. The modules API should be conservative. It means, the module should handle the most common scenarious without optional parameters with some default, most expected, setup. This setup should be possible to overload in the optional options object.
The surface of the exposed API should cover all use cases expect at the moment and still the architecture of the module should be ready for further expansion.
Modularity in Angular
Angular’s architecture leverages both ECMA and Its own modules.
Ng module and ECMA module
There are two basic mental constructs, when it comes to Component classes in Angular.
Container basically contains logic and handle the traffic from services handling the side effects and providing the data to the application. These Components basically don’t expose API as they are consumers of the services API and provides their results further to the Presentational components.
These components, on the other hand, expose some kind of API through @output decoratorated properties and accepts inputs throught the @input properties. They are self-contained ,modularized pieces of the application, where we can impose all the former rules for the modularized application. Most of the work is already done by the implementation of the decorators itself.
To keep the API consistent for services, we have types at our disposal, we should strive to define the interfaces for all the parameters that the components and services consume. This will allow us to keep the API consistent as we can reuse the types for parameters at different parts of the application for common use cases.