I solved a similar requirement with the following structure rewritten in your terms above:
With the following notes:
- Parts are autonomous by themselves, each with a part number.
- The car template is stand alone by itself.
- Parts can be added to the parameter group, and a number of parameter groups belong to the vehicle.
- A group of options cannot exist without a car.
- A group may depend on another group.
- I need to protect against circular links
I started playing with my model by writing a test case before I wrote the class code (Test Driven Development), which gave me the code (in C #) as:
var dieselEngine = new Sku("diesel 2_litre,",1000); var petrolEngine2 = new Sku("petrol_2_litre",800); var petrolEngine25 = new Sku("petrol_25_litre",900); var petrolTurbo = new Sku("petrol_turbo",2000); var dieselTurbo = new Sku("diesel_turbo",2000); var car = new Car("myCar"); car.AddGroup("Engines"); car.AddSkuToGroup("Engines", diselEngine); car.AddSkuToGroup("Engines", petrolEngine2); car.AddSkuToGroup("Engines", petrolEngine25); car.AddGroup("Turbos"); car.AddSkuToGroup("Turbos", petrolTurbo); car.AddSkuToGroup("Turbos", dieselTurbo); car.SetRequirement(diselEngine, dieselTurbo); car.SetRequirement(petrolTurbo, petrolEngine2); car.SetRequirement(petrolTurbo, petrolEngine25);
I am adding a dependency parameter for groups, not Sku, since a part may exist on several cars, but may have different dependencies for each specific car.
I need to put everything through the root car object, which will check and enforce all my business rules (for example, checking and protecting against circular links).
If all access through the car object is awkward, you can always return the car.AddGroup function car.AddGroup group so that the code makes sense to read:
var engines = car.AddGroup("Engines"); engines.AddSkuToGroup(diselEngine); engines.AddSkuToGroup(petrolEngine2); engines.AddSkuToGroup(petrolEngine25);
But do not forget that business rules can only be applied by car, as the car has the visibility of all components. Therefore, we always associate with the root:
class ConfigurableProduct { List<Group> groups = new List<Group>(); Group NewGroup(string name) { var group = new Group(this, name); this.groups.Add(group); return group; } bool ContainsSku(string skuId) { foreach (var group in this.Groups) { if (group.ContainsSku(skuId)) return true; } return false; } } class Group { Group(ConfigurableProduct parent, string name) { this.parent = parent; this.name = name; } string name; List<string> skuIds = new List<string>(); ConfigurableProduct parent; void AddSkuToGroup(string skuId) {
For a real database repository, I would have worried about saving for a long time, it could be a text file, an MSSQL database, a MySQL database, MongoDB, there are so many options.
Itβs always useful for me to focus on how I want to use the code in my application, and not how to use the database, as the repository can be abstracted through the repository interface, which returns the class (a simple old POCO class, but in this case we started to develop business logic to protect against invalid states).
For the front end, you can push it all through JSON to something like angular or a knockout that can visualize parameters that are available dynamically and show or hide different elements depending on the dependencies between the groups.
Work front example
I'm not sure what you are connecting to the external interface (or if you will only use a razor, in this case you will need to save the state on the server and update each selection), but I gave an example of using Knockoutjs here: http://jsfiddle.net / g18c / 5jt9bwsv / 1 / with working dependencies and a dynamic javascript object constructor.
- Passed through the provided JSON products by the group
- Creates computed fields that change depending on the target dependency.
- Binds to view via knockout
Selected SKUs can simply be transferred to the server, any business rules can also be implemented in the javascript interface.
Of course, any data that is sent by the client to the server should be checked by creating a product schedule on the server and checking the correctness of the SKU provided (that is, you do not want to allow the use of Diesel Turbo for selection for a gasoline engine).