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.
  • If the customization is that huge that different HTML/Javascript files and .cs files need to be created, but also use already existing code, how can this be organized in a ‘nice’ way?

Updated (18/10/2016)

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).

6

Customization is as simple or complex as introducing any other requirement. Each time you add a custom business rule or a business rule modification to your application, analyse how to make this rule visible or invisible, active or inactive, available or not available by some kind of run-time switch. Think of the customization step just as an extra, separated requirement, and deal with each of this run-time switches exactly the same as you do with any other requirement: analyse your options how to implement it, make technical decisions, plan the effort, develop, test and deploy the feature. Ask yourself

  • which impact will decision have on the existing code base
  • which changes will be necessary in your database (maybe you need some custom fields only used for some of your customers, maybe you need a different table, maybe you have to make your model more generic etc.)

Just do not expect a “one size fits all” solution: different business requirements will lead to different forms of customization, so you will have to repeat these steps with each new custom feature. And avoid to group customizations “per client” like “saveForClient1”, “saveForClient2”. Instead, add customizations “per feature” – that gives you a much better granularity. For example, lets assume the business rules in the former case are the validation rules of the save method. You could either have one save method with a customized list of validations before saving happens, you could have a save method with additional parameters for controlling the validation, you could have two different save methods like “saveWithDefaultValidation” and “saveWithSpecialValidation”, you could have a flag in your User object or somewhere else in your data model for controlling which validation rules will apply – and there are many more possible solutions. As an additional option to this, you could also think of a plugin system, where extra functionality is made available by some additional modules sold only to the customers who pay for them (but still your core product remains 100% the same for each customer). Just pick the one which serves your purpose best.

It should be obvious that you will have to plan if your clients shall be able to change the specific customization options by themselves (for example, by some config file), or if you do this for them, or if you need to take some technical measures to prevent your clients for activating features they have not paid for. The plugin system above maybe such a measure. Nevertheless I recommend to avoid different core deployments for different clients, if possible.

EDIT: I like to add that I agree with the OP about not using per-client branches in the VCS for this purpose. The problem which occurs is that whenever a new feature in the trunk is added, the dev who adds the feature cannot see immediately if this will collide with any code of the other branches, and if there is something to be changed, too, or if a more general solution is needed which works for the trunk and client specific releases as well. If you are lucky, you might notice this later, when you try to propagate changes from the trunk to the client branches and get merge collisions. If you are not so lucky, you do not get any merge collisions, but one of your client releases now has a severe bug. Maybe your automatic tests will catch this, maybe your manual testing, or in the worst case the customer is the first who notices it, but it should be clear that your testing effort multiplies with each client. This is because when you allow arbitrary changes in each branch, you will have to make a full integration test with the whole product after a change in the trunk for each branch.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật