My company needs to build an application to be rolled out for a lot of clients. This software will have many modules and functionalities, but some of these will need specific adjustments for some companies. Those adjustments might be of minor nature (like a new input in a form), or may be major customizations, like changing the entire form with different steps and business rules before save/edit/delete. It can be expected that the customization may also leads to some changes on database level, like new columns.
The application already exists, but we did not include these changes yet. The application uses .NET, WebApi, AngularJs. As software architecture design pattern we use microservices and a Domain Driven Design (DDD) approach. The Visual Studio Solutions structure is like this:
- WebApp: routes, JS, CSS, html.
- Module-Interface: WebApi Controllers, and Services
- Module-Domain: bounded contexts, aggregation roots, domain.
- Module-Infrastructure: unit of works, repositories, persistence validators, entity mapping
An idea to control this complex scenario is using different branches (on git) for each client. But this may lead to the problem that we need to maintain different applications in the future.
We think it is much better to keep it all in a single branch. But we have a lot of doubts about how to realize it in a good manner (best practice?).
As an example, imagine a CRUD for "User" domain that can have different business rules on different clients. Problems that we see:
Do we need to create different save methods on User domain? Like "saveForClient1", "saveForClient2"...?
- We fear that inheritance on domains could have a negative impact on our DDD approach for this problem.
I changed of job before going more deep in the solution, but there are comments asking about what strategy we choose.
Use different branches it's the worst idea. The better strategy is control the differences in the code, making different packages, files and REST resource paths to organize this code and attend the specific functionalities. Use interfaces and dependency injection to maintain the same contract in the system but with different implementations for the clients. DDD can help you to isolate this cases where some information from database is client specific.
In the front-end, it's a good idea to choose a painless library to help you to build interfaces, gaining flexibility to make different interfaces reusing the same components (like React).