Multi Tenancy - Where do you put variability?
Previously on the Multi Tenancy series:
- Multi Tenancy - Definition and scenario.
- Reviewing Litware HR - P&P Multi Tenancy Sample.
- Multi Tenancy - The Physical Data Model
- Multi Tenancy - Extensible Data Model
- Multi Tenancy - Extensible Behaviors
- Multi Tenancy - Development Structure
Paul Cowan has left an interesting comment on my post about Multi Tenancy - Development Structure.
I have migrated the app. from ASP and the ASP approach was to have a completelly seperate code stream for every customer and a seperate DB strucutre.
This was quickly getting out of hand.
I migrated all code streams into one app and every tenant now has their own DB instance of the same schema.
I am loathe to go down the path of actually developing maintainable bits of work that are only applicable for one tenant.
The variability has to be controlled by configuration, DSLs or maybe even clever use of build scripts that all build from the same code base.
I want to explain something, because it appears I wasn't clear. I am not advocating creating completely separate code streams (interesting description) for each tenant. I want a shared core with the variability existing within the scope of each tenant. Like this example:
Most of the application is in the core, but each tenant can decide to override specific functionality on as needed basis.
The key part here is that we want to be able to have a coherent view of how each tenant behave. Trying to do this by configuration or clever build scripts is actively detracting from gaining that clear view. I want to be able to open a project and look at all the things that this tenant is doing that are different from the default approach. I don't want to hunt down what "pays_overtime" means for this customer, and whatever they remembered that the "pays_overtime" configuration value must always go with the VALIDATE_MAX_OVERTIME_HOURS build value.
Regarding scripting and DSL, I am going to touch on this in a separate post, indeed, this is one extremely interesting way of dealing with the problem, but it is not conceptually different than the approach of creating a separate project. You just change the compiler, not the approach (not quite accurate on the detail, I'll admit, but enough for high level view).
You should remember that adding variability is easy, just put an if statement there. Making sure that you can understand what is going on there is a much more complex task.
Of course, if I have a set of modifications that always go together, I will probably decide to make this explicit in my model, so now the path to create a tenant would be similar to this:
But my main concern is the maintainability of the system. As such, I want to make sure that the view I have on a tenant's application is as clear as possible, and not mired in admittedly clever tricks that will cause a lot of pain down the road.
Comments
This current raft of posts hits a nerve with me as it is something I have been dealing with for the last year.
We also have new tenants coming on board soon.
As usual, there is a lot of great documentation on product lines in the java space.
My approach is to be either flexible in the structure of my db design or define the points of variabiltiy and have dsls to configure the individual tenants variability.
For instance every tenant can have their own field structure for contacts in our db without having to add extra columns to the table.
Each tenant can also have their own ETL script that maps contacts from their datastore to our datastore by having that variability trapped in one .boo file that is handled by Rhino.ETL.
I am still not were I would like to be with writing my own dsls and eagerly await the book.
A lot can still be achieved with configuration.
if defs although a crude approach are still an option.
As a side note. I started off with the idea of having a seperate SSIS .dtsx package for each tenant.
My good God, the trouble that brought me.
SSIS nearly gave me a nervous breakdown.
Rhino.ETL was the right option and thankfully I had the good sense to bin SSIS.
Nobody should make the same mistake.
I'm interested in learning the difference between a multi-tenanted application and a framework.
For example, Ruby on Rails is a bit like a multi-tenanted application for developers. Each application has the same core modules, the same folder structure, and broadly the same architecture.
Rails also has a set of key extension points. You add your own views, controllers and models. You download the plugins you want to add pre-built slices of functionality.
In Rails, they've found useful extension points to where the variability can go.
Is this completely different to how you might build a multi-tenanted application? Could you build a "framework" that provides the core functionality, with appropriate extension points? And then just use that framework to build a multi-tenanted application at a good pace?
Might have missed the point here, but just curious!
I don't think it is a matter of the architecture just being extensible.
I migrated the app. to ASP.NET MVC but that is really just a point of technicality.
I think the challenging bit and probably the fun bit is to make the app. as configurable for each tenant without having to cater for each tenant individually.
Tenant in this context is a client.
Each client has their own web site and their own database instance but when I release a new version, each client gets the same code version and each db is from the same schema. SQLCompare has been a god send on this front.
THe key to me is definintg the points of variability and then allowing these points to be configurable or flexible enough for each clients needs without verging significantly for that clients needs.
I never want to have a plug in or a code piece (apart from a dsl) that is just applicable for that client.
You have to keep in mind the maintainability of the whole.
Of course the business are always promising the clients they can have their own functionality.
Leads to some interesting meetings..........
Comment preview