I've been tasked with re-writing a fairly large web application for a company. This application provides certain financial/risk analysis to 3 clients that we currently have.
The huge issue around this app is each client is different and has slightly different data. They all log into the same website but after that their experience can differ slightly. Their database schemas aren't the same, occasionally their views have to differ to represent different data and their user management is a complexity nightmare. When a user logs into our site we need to pull data from the right database (each client has their own).
Say our clients are 3 hardware companies:
Hackman's Hardware might have slightly different analysis needs or request certains special columns in our reports. Similarly, Lowes Hardware might want to have slightly different security access to its pages then a different company based on its users.
Functionally, the web application is the same for them. It has the same tabs and the same goals at what information it is trying to present. But there are subtle differences between them that I'm having trouble encapsulating and it is making the code a mess.
Question: What is the best practice for handling a base application that needs modification for each new client that we get? What architecture/design pattern can we use to make adding new clients relatively painless despite their need for customization while still re-using as much as possible? How can we keep our codebase clean without the need for per-client hacks?
We are using ASP.NET MVC for this rewrite but I'm not sure how relevant that is to the question.
Create a master page that contains all of the information that is the same for every client. Then, add views and/or controllers that are unique to each client.
Have a look at the following link. It explains how to create an "Application Controller," an abstract class that can be inherited by your other controllers, so that you only have to write the code once that pushes your needed master page data into the view.
Passing Data to View Master Pages:
http://www.asp.net/learn/MVC/tutorial-13-cs.aspx
Also, have a look at the following link, which explains how to implement Partial Views and Subcontrollers in ASP.NET MVC:
Partial Requests in ASP.NET MVC
http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/
I'm going to have to disagree with some of the approaches that describe deriving from a common base controller, etc. because subclassing alone is not going to work out well. You'll be adding derived classes for each client and it will become a maintenance nightmare if you have more than just a handful of clients. Also, while a MasterPage is going to be used in some capacity, if your clients want input into the look and feel of their site, a lot of the things like colors, styles, etc. are going to need to be data driven.
The portal idea is pretty good, but if you have a lot of custom domain logic that will differ from client to client, it will also start becoming an issue quickly. If it is just a matter of hiding some pages for some clients, then a portal idea is not a bad suggestion. Keep in mind that if you are using pre-production environments that portal sites like DotNetNuke can be difficult to deploy from one environment to another unless you become intimately familiar with their schema. Plus, sites like DotNetNuke are not written in MVC so applying any test driven development practices will be much more challenging than beginning from scratch.
I would first start reading up on design patterns if you don't have a good background in them already, specifically the Strategy and Abstract Factory patterns. This will allow you to look at the design of the project with an eye towards favoring dependency over inheritance. Try to develop a few domain classes that will expose properties which are the templates for what you will expose to your clients. Those properties' types will use the classes that encapsulate what can vary from client to client. Once you build a couple of classes and test them, you can then produce the database schema necessary to support it. I suspect you will end up with a clients' table, tables that will contain the possible values for your entities and their related value types, and tables for each that associate the clients with these entities.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With