Code Organization Strategies — Layers, Features, Concerns?
The emerging software design approaches has not only influenced the way domain services interact with each other but it has also influenced the way code is being organized in different ways for achieving various business goals such as maintenance, productivity and agility.
In this article, we will take below mentioned Hotel Booking Application as an example for demonstrating the concepts assuming that all the code is hosted within same service.
Let’s also keep following business requirements to keep things bit interesting.
Business Rules
- Only hotel customers are allowed to book hotel facilities such as Spa, Transportation etc.
- The booking dates for facilities needs to be according to room booking.
- The charges for hotel facilities such as Spa, Transportation etc. will be automatically added to the room booking.
The use cases and approaches mentioned for hotel booking application are mainly for demonstrating the different approaches.
1. Organize Code By Layers
The approach uses the technical boundaries of the modules for organizing the code. Each module (layer) exposes interfaces and changes can be done to the implementation without affecting other modules (layers).
This approach has been in use for many years in software industry and works well for services with low complexity.
Pros :
- Easy to understand and follow : This code organization comes very handy as its easy to communicate the idea of layering.
- Code re-usability : The code, utility methods are part of same package which helps in promoting the reusability.
- Maintainability : The layers can be changed and replaced with other implementation as long as there is no changes in interfaces.
Cons:
- Productivity: This approach is not suitable when multiple team members are working in parallel on different features as developers can do changes to common code without realizing the impact on other features and team.
Notes:
The approach can introduce following challenges if code is not maintained properly.
- Developers confidence : This approach lacks the functional boundaries due to which developers find it difficult to assess the functional impact to other existing functionality when it comes to change management— where the changes are required, what will be side effect of those changes.
- Spaghetti code: The attention is paid more to the layers then the code within the layers which can potentially lead to spaghetti code unless team defines and maintains the explicit guidelines and contract for the modules implementation.
2. Organize By Business Capabilities
This approach is usually discussed in the context of Modular Monolithic Architecture but can be incorporated into services that have multiple inter related business capabilities with significantly high complexity.
Pros
- Isolation : The changes in one business capability doesn’t have any side effect to another capability.
- Productivity : Multiple teams can work in parallel for each business capability over stepping on each other.
- Decomposition and migration : The code can be easily migrated to another service if decomposition is required.
Cons
Code Re-usability : The common code gets duplicated across different capability modules.
Notes:
This approach can be an overkill if services are small in size and business logic is not complex.
3. Organize by Modules (technical and functional concern)
This approach uses all the important dimensions of the application such as technical concern and business concern for modularization. The important concerns are isolated and encapsulated into their own modules that are later used by the orchestrator /manager for providing the required API behavior.
Pros:
Testability : The business modules can easily tested by unit testing etc as they don’t have any external dependencies such as APIs or Data Access.
Plugability : Orchestrator can invoke the business capabilities based on the desired behavior of the APIs.
Example : If Business asks to provide one single API for doing Room Booking, Spa Booking and Transportation booking then a new orchestrator can defined that can easily use the existing modules to provide the desired capability.
Maintainability: The Separation of technical and functional concern promotes higher maintainability then other patterns as both technical and functional concerns are well isolated.
Cons:
External dependencies : In this approach, orchestrator is not aware of the business logic so if any core business capability module depends on the external dependencies for its business logic then orchestrator logic might get polluted as it may be forced to host part of the business logic to achieve desired behavior.
Look Outs:
This pattern is useful when services are required to expose different combination of business capabilities as per client needs.
This approach can also be useful when business logic is highly complex as each capability module will help in encapsulating that complexity behind well defined interfaces.
Please provide your feedback in case if I have missed any important details.
References
https://www.youtube.com/watch?v=Nsjsiz2A9mg&t=461s
https://codeopinion.com/organizing-code-by-feature-using-vertical-slices/