6

I've been brainstorming on a specific problem for a while and today I've thought of a solution. But am not too sure about it. Hence this question for feedback and suggestions.

I'll use the simple example of a product T-Shirt.

The T-Shirt has multiple options:

Color: White, Black

Size: Small, Medium, Large

Now in the case of a White T-shirt, there is no Large and Medium. So Large and Medium option should not be available when selecting White.

This means that if you first select Large or Medium. Then White should not be available.

Previous implementation was done as a tree structure. So you always have to select Color then Size. But it's not really a tree the way I see it.

My idea was to create a list of rules.

pseudo code:

rule1: if color is white, sizes not allowed are [large, medium]

//then generate the opposite rules based on rule1.
rule2: if size is medium, color not allowed are [white]
rule3: if size is large, color not allowed are [white]

store rules in database

When you are dealing with products that have many options this could get complicated, that's why I thought generating the other rules based on the first rule can reduce the complexity.

Thoughts anyone?

Update:

Someone remarked below and I realised I used the wrong example. It's not a product which has a SKU and stock level. It's a service. A better example would be a configurable computer. Many different CPU, RAM, GPU, etc combinations. Which all produce different price and depending on specific motherboard or some specific selection, not all CPUs and/or RAM etc are selectable.

Update2:

The products/services each have around 7 options. Each option can have between 2 - 7 values. A matrix structure as suggested, would become complex IMO.

Also we've moved away from having a price for each single variation (which was ridiculous to manage) to having formula's to generate prices dynamically.

There was always an issue with the DB load because of the tree structure. Each time an option is selected it has to fetch the values of the subsequent options. Each time you add a new value to an option you also duplicate a lot of the subsequent options. So it gets out of hand really quickly.

To go into more details my solution was to use a document based database (NoSQL) You would have a "Products" or "Services" collection.

Each product/service would look something like this:

{
  "product": "T-Shirt",
  "options": {
    "size": [],
    "color": [],
    "pattern": [],
    ... about 4 more
  },
  "rules": [....],
}

Initially you just load all the options in the interface. Then as you make selections you run the rules to disable the specified option values.

Using such a structure seems to me that it would have less overhead by having the rules embedded in each product/service instead of having a large relational table with all the options (which is already massive).

The client side benefits because it doesn't have to query the DB each time an option is changed.

  • 3
    My immediate thought here is that in a real t-shirt store, each permutation would be a separate stock item. So you'd know that the White, Small combination was not available because the stock level for that is 0. So I guess that would basically make the structure a dictionary. Depends on what you're trying to do, but it's possible you may also have to deal with the scenario of the small size being picked first and then checking what colours are available. – Mr Cochese Jan 13 '17 at 15:17
  • Right! I used a wrong example. In my case it's a service so there is no SKU and stock level. – moleculezz Jan 13 '17 at 15:31
  • Also... When small size is selected then the default options are displayed. So basically the rules are a filter on the default options. – moleculezz Jan 13 '17 at 15:37
  • What's wrong with a tree? If the rules are complicated, a tree is still the best to handle them. Have you ever seen the rules behind the tariff of say Deutsche Bahn (German railways). This is not even a tree, but an awful graph that has quite some contradictions. – qwerty_so Jan 13 '17 at 15:40
  • Are there more rules or exceptions? i.e. is it easier to indicate medium does not come in white or here are the 12 colors medium comes in out of 13. – JeffO Jan 13 '17 at 21:40
2

A tree (your existing implementation) is simpler to model but you impose limits in the order with which users need to select what kind of product they want. If that's not OK for you, a generic way to model all the combinations (existing or future ones) is to represent the combinations as a multidimensional array indexed by strings instead of numbers (more like a multidimensional dictionary actually).

In user COMEFROM's answer that's what is represented, a 3 dimensional array: Product x Color x Size. At the intersection of all the columns you store a boolean value. If ['t-shirt', 'white', 'large'] == false then you don't have a large white t-shirt. If it is true, then you have.

Of course this gets complicated fast. The more you add products and options, the more dimensions you add to the array. Above 4 dimensions and it's hard to visualize your data structure or think about it. The number of values that you store also increases.

But if you have just a few exceptions, then maybe you can model only those with a multidimensional array. Basically you assume that a combination is valid and then you look it up in the multidimensional array of exceptions to see if the value is present there. If it is then the assumption is false, which means you don't have that particular combination.

The advantage with a multidimensional array is that you can look at it from whichever direction you want. First color then size, or first size then color, it's all the same. You eventually reach the cell where all the options intersect and you see what value you have there. The disadvantage is that the size of the array can grow very large and that you need to rebuild your values any time you add a new dimension.

Your solution for having rules can also work. It's similar to the multidimensional array but modeling execution (if-then-else) instead of data lookup based on some values (data lookup is simpler than rules logic).

  • Yes, in my case I have in some cases 7 options and each option can have values between 2 - 7. So it will get complicated very fast. I don't have an exact number on how many exceptions there are, but I don't think it will be on the many side. More on the low or medium side. I will update the OP with more information after all the feedback – moleculezz Jan 16 '17 at 14:01
  • I still picture a lot of records to represent all the possible combinations with the exceptions. You would only ignore all combinations that use "small" size in the example. But you still have to include all possible combinations that include "large" and "medium" with the rest of the options. I still seems a lot to me. – moleculezz Jan 17 '17 at 12:15
2

You may want to look at the Entity-Attribute Value design for modeling things that have multiple types of attributes with arbitrary values.

I learned about this pattern of design from Magento, an ecommerce web app. You can read about how they use EAV here.

  • I've looked into this before. The only thing missing is a way to filter out values of certain attributes based on selections of other attributes. This is a nice solution for modelling the "options" part (in my example) in a relational DB. The "rules" part is where I am having difficulty modelling. – moleculezz Jan 16 '17 at 20:14
  • @moleculezz we're running into that problem at work. you can predefine a bunch of functions and have them take parameters: rules = { "someOption": [ ["requires", "someOtherField", "expectedValue"], ["mustBeIn", ["a", "b", "c"]]]} – Rudolf Olah Jan 16 '17 at 21:11
1

The standard term for your problem is usually referred to as product lines. A less simplified example are cars. When you buy a new car, there are many many options to configure it with lots of constraints on which combinations are possible and which not.

Product lines just means, that one product is available in lots of different configurations (lines).

To get closer to your questions, these configurations are typically individual features, which can be modelled together with their constraints. Take a look at FeatureIDE for an example of an available tool for this sort of feature modeling.

Keep in mind that in general, arbitrary constraints can lead to really complex evaluations being necessary, on which features are still selectable, and which are not. Feature modeling therefore uses much more sophisticated approaches than simple tree evaluations. Strong tools like FeatureIDE therefore translate your selected features and all the constraints into a large SAT formula and run state-of-the-art SAT solvers to answer questions like "which other features can I still select?".

It's up to you to decide if your use-case warrants this complexity and needs full blown feature modeling, or whether you have a very simple feature model and want to do things manually. As the other answers so far have not pointed out, that there are feature model tools out there, I just added this for completeness and as reference to future readers.

0

I'd probably have a set of set of options stored for each product. So, for the t-shirt there would be this set of set of options available:

{ 
    {"color:white", "size:small"},
    {"color:black", "size:small"},
    {"color:black", "size:medium"},
    {"color:black", "size:large"}
}

This is all data you need to have to recognize the types of options a product has ("color", "size"), the values available for each type and the combinations of options allowed in a valid order of the product.

Note that this model works only when there's a relatively limited choice of options and values. Allowing any 24-bit RGB-color as an option wouldn't be feasible. The sets would simply grow too large to store and handle.

(Note: The syntax above is not supposed to be JSON or anything really. Technology is irrelevant. Those {}s denote a set like in mathematics. The objects (options) in the sets could be strings or of some custom type. The point is to have a simple data set that represents every viable combination of options for a product.)


Edit: After reading the Update2 of the question I'd say this is not a feasible solution. It would work for a limited set of options based on stock levels of a product though.

  • The format for the option is not-quite-json :-) – Sklivvz Jan 13 '17 at 16:05
  • It's not supposed to be json at all :). No technology tags in the question so I used the mathematical notation for sets. – COME FROM Jan 13 '17 at 16:06
  • This solution can become unwieldy when you have 7 options each having between 2 - 7 values – moleculezz Jan 16 '17 at 13:57
  • @moleculezz True. The size of the data set for 7 options with 7 possible values each would be close to 1 000 000 already. However, if the availability of the product with a set of options means that there are actual products stored somewhere with those options, then it's quite likely that the set all available combinations of options is quite limited. – COME FROM Jan 16 '17 at 14:04
  • 1
    @moleculezz If the set of available options for a product is based on physical products already produced and in store, then the set will probably be relatively small. It's quite inlikely to have a million variations of some item actually produced and stored waiting for an order. I imagined the back end service would fetch the store status of the product, and if there were blue shirts of size S in store, then it would return {"color:blue", "size:s"} as one possible option set. – COME FROM Jan 16 '17 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.