Multi Tenancy - Development Structure
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
You might ask, what is the relation between multi tenancy and the development structure... And you would be wrong to assume that there isn't any. In particular, I am talking about designing the development structure and the tenants.
No, I don't think that most of the tenants would care about how you structure your development effort. What I do think is that if you are not careful you might end up with the following problem:
Pretty horrible, isn't it?
One of the things that you need to care for when you are building such a system is to enable development of tenants customizations without forcing the developers to have all the weight of all the tenants all the time.
I took part in such a project, in which each tenant's customization lived in the main solution, with the core application. By the time I left, the main solution contained over 60 projects, Visual Studio was slow, the use of the configuration manager to control what to build when was pervasive (and different from one developer to another), leading to a lot of interesting issues:
The team was at the second or third tenant at that point, if I recall correctly. They had seven hundreds to go through.
Obviously this approach wouldn't work. We need to start, from the beginning, as we want to continue. And considering such issues can lead to a great benefit both in the short and long term. For some reason, a lot of architects don't seem to take into account such considerations, which tends to hurt later on.
A better approach, from my perspective, is to start with clear distinction about what is in the core project and what is in the tenats' customizations. Even generalized tenants' customization (those shared across more than a single tenant), should be separated.
In effect, this mean that we would have the following structure:
- MyTenantApp.sln - this is the core application
- Tenants\Northwind\Northwind.sln - customization solution for the Northwind tenant
Depending on the maturity of the application, a tenant project may or may not reference the actual projects of the core vs. referencing the compiled binaries. If we are in the first tenant (or the first few), we will generally need to extend the core a lot, so it is useful to do so.
Once we have gotten to the point where we have (more or less) stabilized what the core does and what each tenant do, we move to referencing the compiled core binaries, to reduce the load on Visual Studio and to ensure that there is this extra step in the middle, that would cause us to think about changing the core (with the versioning issues it may entail).
In this scenario, the core is actually the SDK for the application, not just the application itself. It means that there are more complex duties required of it, since it is a published interface which we will give to other developers to use. It means that there are versioning concerns you need to take into account, and that you should design your core with extensibility in mind. That does not mean BDUF, however, that is why I suggested having the core libraries as part of the first few tenants projects, so you can add this extensibility as you need it.
And that is quite enough for now, there are a lot of other considerations that you need to consider, such as source control structure, and how you sync between all the tenants and the core, but they are of lesser importance compared to the initial development structure.
Comments
I work on a mult-tenant product with at the minute only 4 different tenants.
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.
The important part of the latter approach is being able to easily rebuild the tenants specific configuration for debugging purposes.
The minute you start developing single pieces of work for one customer then I think you are heading down a very dark tunnel.
Our approach at the minute is that if it is not good for the core product and only applicable to one tenant then we just say no.
You've listed alot of good ideas here... most consistent with a system I am designing. One thing to keep in mind with points of extension is the add-in framework released with .Net. It really helps with the versioning issue of add-ins.
BOb
Comment preview