# Inheritance and Versioning
BriteLines has two important functionalities: Inheritance and Versioning. A Line can be straightforward, with just a collection of Risk Types with single Version. Or a Line can be complex, with Risk Types inherited across multiple Products (Inheritance) and changes that exist in multiple Versions with different effective dates (Versioning).
Inheritance allows models to share common definition ancestors. This allows common data elements to be defined in an upstream template Line of Business (LOB) product, then utilized repeatedly through inheritance into specific LOBs products that extend the base product. For example, there might be Homeowners product that defines 80% of all HO business, but then inherit HO-Common into HO-2, HO-3, and HO-5, each of which introduces new item, rates, and rules.
Each Line can have multiple Products, in above example LOB is Homeowners with root Product
HO-Common and other Products
HO-5 inherited from
HO-Common Product. This is handled via
Line, Risk Type and all entities of Risk Type are bound to a Version. A Version is composed of a name and an effective date, the effective date tells when a certain Line of Business, Risk Type, or Entity is going live/effective from.
Once a Line of Business or Risk Type is live, users should not be able make changes to it. Instead, users will create a new Version with a new effective date and make changes there.
Consider following Line effective from
Auto Line of Business: Vehicle Risk Type: VIN - Field
Later the user decides to change the label of a Data Field from
VIN to something more verbose like
Vehicle Identification Number.
In this case, a new Version with a new effective_date should be created and we should duplicate the
VIN Field with updated label.
So going from one Version to another Version requires duplication of data. In BriteCore Classic we duplicate the whole Line of Business instead of just duplicating the Data Field.
The goal here is to avoid as much duplication as possible and make changes as fast as possible.
To support this we have split some of our entity's models into two: a version model and an instance model.
# Version Model
Version model mostly only contains pointers so that when going from one version to another version all we have to do is to duplicate bunch of pointers. A version model holds pointers for:
- RiskType (ForeignKey)
- RiskTypeVersion (ForeignKey)
- Version (ForeignKey)
- Instance Model (ForeignKey)
- Other Many-to-Many relations for entity
RiskItemVersion are version models
# Instance Model
Instance models contain data points like
label. These models will only be duplicated when a change happens to instance-level data.
RiskItem are instance models.
# DB Schema
- Consider we have an enum data Field with 5 options and the user would like to add a new option. This will require us to duplicate the
RiskFieldVersionmodel, add new option in
options(many-to-many), and that's it. It still uses the previous instance model (
RiskField) as there was no change in data points like
label, etc. and we have avoided duplicating them unnecessarily.
- Only duplicate Version and Instance model when we are explicitly making a change which affects them. Going from one Version to another can still use previous instances as long as there is no change happening.
- Avoid ForeignKey relationships at the Instance model level. Duplicating Instances means that all direct relations also need to be duplicated unnecessarily.
- From API perspective, end users do not need to know how we are handling versioning on the backend. A single API call contains all data to create/update a risk field and Version and Instance model will be created/updated respectively (if needed).