Best PracticesHere is a collection of best practices for designing and implementing product models.
About Absolute and Relative Paths
You use absolute or relative paths to specify entities such as properties and rules. Paths have the following form:
<model group root node>.<path to the option item that has the property or rule>.<property name or rule name>An example of an absolute path for the memoryProvided property can take the following form:
In this example, MXDS-7500 is the model group's root node, memory.sim256 is the path to the option item that has the memoryProvided property, and memoryProvided is the property name.
If you want to use a property or rule in more than one model, you can use special symbols to specify relative paths. For example, the "*" in the following path indicates that the path begins at the root of the model group hierarchy:
Beginning the path with a period (.) indicates ''from the attachment point of the rule''. For example, the "." in the following path indicates that "an option item called sim256 in an option class called memory in the current model".
Guidelines: To Choose a Model Type
Modelers can choose among the following types of models:
Normal UI: option classes appear within a single frameTabbed UI: option classes are grouped into a series of tabsStepwise UI: option classes are grouped into a series of steps to guide the consumer through the configuration processThe Stepwise Configurator UI consists of a single page with tabs representing the options consumers can choose to configure a product. The Stepwise UI is most efficient for models that are flat: they do not require the use of dynamic instantiation, sub-model punch in and punch out, or the attachment of other models, option class groups and option item groups. You can choose to design a Stepwise UI for complicated models, but doing so may not match well with the goal of simple, seamless usability.
Guidelines: To Configure a Product Model
Consider the following when you configure a product model:
Cost factors: creation, maintenance, and performance.You must balance the cost of creating the model, compared with the cost of maintaining it and compared with its expected performance. The cost of creating the model represents the one-time effort expended to develop it; the cost of maintaining the model represents the effort expended over time to maintain and enhance it, while the performance represents the execution speed of the model on a particular hardware platform. You can optimize for any one of these factors, but keep in mind that trying to optimize for more than one of the factors means that you have competing goals. For example, while a complex model may run fast, it will be hard to maintain.Implementers' roles: model builder only, model builder and maintainer, model maintainer only.The implementer's role influences their bias. For example, if you give a consultant a month to implement a model, which will later be given to another group for maintenance, may focus on designing the model quickly rather than designing a model that will be easy to maintain. If the implementer implements as well as maintains the model, the model may take longer to design and may not run as fast, but it will be easy to maintain. Whatever your role is, your goal should be to set up a model that will not create problems in the future.Models
Make Models as Small and Simple as Possible
Model size matters. Large models take longer to render in the browser, are more difficult to maintain, and during configuration, the Configurator "walks" the model structure a number of times to get prices, fire rules, and so on. Keep the model size as small as possible using subassemblies and other techniques to improve performance and reduce maintenance costs.
For example, if you have a number of cable suppliers, each of which supplies a number of different lengths of cables, you can use different approaches to create a model to allow the user to select the quantity, length, and cable supplier. Following are some of the options you can consider while creating the model:
Create option items in your model to represent each of the available options as shown in the following figure:
This approach will work, although it may be tedious to implement and maintain it and creates a model with many options that will not be of interest to the end user.Implement the different cable length option items as an option item group, and include the cable length option item group under each of the manufacturers.This makes the model easy to maintain because the modeler has to look in only one place to update the cable option item information. However, this approach presents the end user with a long list of cables to choose from and does not improve performance since there is a large model to ''walk''.Create a submodel that allows the user to select a cable manufacturer and length, and use dynamic instantiation to let the user add as many different cable types and lengths as necessary, as shown in the following figure:
The following figure shows a sample cable selection user interface that uses dynamic instantiation to allow end users to configure their cable selections:
This approach keeps the model small, leading to better performance. The model is easy to maintain since the modeler does not have to look at a large number of duplicate option items. Configuration is easier for the end user since the end user does not have to look at a long list of cable types and manufacturers to find the right one.Use popup-qty Controls for Entering Quantity
To allow users to select an item and then enter the number of items they want, set the Option Class Display to ''popup-qty''. When the end user selects an item, a quantity box will display, allowing the end user to enter the number of items they want.
Another alternative is to use the User Entered Values (UEV) control to display an edit field next to the item where the users can enter a quantity. The behavior of the popup-qty control differs significantly from the behavior of UEV controls: the popup-qty control has quantity processing built in, while UEV controls require additional action.
When an end user enters a quantity in a popup-qty box, the application automatically selects the quantity of the selected item. Any properties attached to the item are included in the configurator state (property pool), and the values of any numeric properties are multiplied by the quantity entered.
When a value is entered in a UEV control, nothing else happens. UEV controls are designed to capture additional information from the user. To enable the UEV to behave as a quantity, the modeler must write an expansion rule that takes the value entered in the UEV control and picks that quantity of the selected item. Using the value entered in the UEV control to set the _quantity property using an assignment rule does not work as expected since this does not automatically create instances of the item's properties in the property pool.
To display a popup-qty box beside the item selected, use the popup-qty Option Class Display style and one of the tabular displays with quantity controls. This ensures that the correct number of items is selected and the correct properties are copied to the property pool.
For example, perform the following tasks to set up a popup-qty control:
The Model navigation page displays.
- Click the option group you want to modify.
- Click the Display tab.
- Select Multi-select Tabular Display from the UI Control drop-down list, as shown in the following figure:
- Scroll to the bottom of the page and enter the Column Headings, Column Properties, and Column Alignment settings as shown in the following figure:
- Click Compile and Test to compile and test the model. The Product Configurator page displays.
Guidelines: Define and Attach Properties
Modelers attach properties to models, option classes and option items, and then write rules that work on these properties in order to display messages, show, hide, or select items, and even set the values of other properties. Properties play an important part in modeling a configurable product, therefore you must take care while defining properties and using them. This section outlines some useful tips and procedures to follow when defining and attaching properties.
Use Meaningful Property Names
Sometimes, when developing a model, especially under severe time constraints, the modeler is tempted to take shortcuts in order to speed the development process. One of the most common shortcuts is to create properties with short, and often vague or cryptic, names. This may speed the development of the model in the short term, but dramatically increases the amount of effort required to maintain the model. The modeler should always design their models so that it is immediately obvious what a given property represents. The more meaningful the name you give to a property, the easier it will be to debug and maintain the model now and in the future.
Consider the following example of a model with cryptic property names:
At first glance, it may not be obvious what the properties assigned to this model are trying to accomplish. If you create meaningful names, it becomes easier to grasp the essence of all the properties and how they relate to one another.
Consider the following example of a model with meaningful property names:
Do Not Use the Same Property to Mean Two Different Things
Often, in haste to implement a particular feature, a modeler may reuse an existing property instead of creating a new property designed specifically for the problem at hand. This has two possible implications:
The model may be harder to understand if the existing property name bears no relation to the problem at hand.Re-use of the property name may cause errors in the model if the re-use conflicts with the property's original use.In the example cited in the previous section, let us suppose that our modeler created a property ''memory'' to store memory required. When the modeler determines that there is a need for a property to store memory, the modeler notices that there is already a property called ''memory'' and decides to use it instead of creating a new property. The following figure shows an illustration of the scenario:
At first glance, it looks like all option items require some amount of memory, instead of two items requiring memory and two providing it. Not only that, but the total_memory_required property no longer has the correct value since it now performs a sum of both memory required and memory provided. If it is modeled in this fashion, the modeler has to do extra work to separate the specific instances of the properties the modeler needs, such as using full or relative paths to the items containing the appropriate property instances.
Define Properties at the Appropriate Level in the Model Hierarchy
You may define properties at any level in the model group hierarchy. Where a property is defined determines which models can see the property and make use of that property. Use the following guidelines to determine where a property should be defined:
If you want to use a property only in a particular model, define the property at the model level.If you want to use a property in more than one model within a particular model group, define the property at that model group level.If you want to use a property in models that span model groups, define the property in the first model group that contains all the model groups whose models will use the property.As a last resort, define the property at the root model group node.
Using Multiple Properties with the Same Value
Multiple properties with the same value can sometimes make a model easier to build and maintain. This concept may be confusing at first and is best demonstrated by an example. Suppose that you are building a model that allows the user to choose from a selection of disk arrays. Each type of disk array has some number of disks associated with it. The user can choose multiple disk arrays of any type. One of the pieces of information that you need to calculate is the total number of disks that the user has selected.
Consider the following example of a model where multiple property names are used to clarify a purpose:
Suppose that you realize that you also need to know the number of 100GB disk arrays and the number of 250GB disk arrays. Instead of calculating these values by specifying item paths to the properties, or writing rules that have to be attached at a particular point in the model, or re-working all the disk and total_disk properties, you can define new properties that have the same values as the old disk property as shown in the following figure:
If you want the total disks, you can get sum(disks), and if you want the individual values, you can get them without specifying paths to individual properties or modifying the work that you had already done.
Use Worksheets to Simplify Property Assignment
When you develop a model, it is often necessary to assign the same set of properties to multiple option classes or option items. Worksheets are useful in such a situation because they allow you to rapidly set the values for a particular property on any number of option classes or items. This is especially true when using a formula to set the value of a property in multiple places. The modeler can copy and paste the formula to all the items.
In the following example, there are some display properties set for each item within a tabular display. A worksheet is used to allow the modeler to easily cut and paste the formulas for col1 and col2 to each item in the option class.
Another advantage of using worksheets is that you can provide a concise picture of a section of the model. A worksheet can provide an overview of a particular section of the model or a complete representation of the solution to a particular problem. The following figure shows a different view of the same option class. The worksheet shows all the min and max properties that are set for each option item.
Avoid Chaining Property Formulas
Properties attached to an item do not have any notion of sequence. This means that, when using formulas to set property values, you cannot rely on any particular order of evaluation of the formulas. If property A contains a formula and property B contains a formula that relies on property A, then there is no guarantee that the rule created from formula B will fire after the rule created from formula A. In order to get around this issue, the modeler has the following choices:
Turn the first formula into a rule that fires before the second formula is evaluated. All rules generated from formulas have a priority of 50. Creating a rule for the first formula and setting its priority to less than 50 ensures that the value of property A is set before the value of property B is calculated.Turn on repeat rule firing. In this case, the first phase of rule-firing calculates the value for property A. The second pass of the rule-firing loop calculates the value of property B based on the value of property A computed in the first pass.
Guidelines: Writing Rules
Rule Firing Conditions
You create rule conditions by applying boolean operations to relational expressions. A relational expression is the comparison of one function/property pair with another function/property pair using relational operations such as ''less than'', ''equal to'', ''greater than'', ''in'', ''not in'', and so on. The result is either ''true'' or ''false''. Boolean operators such as ''AND'' and ''OR'' wrap sets of these relational expressions. The relational expressions are called fragments, as they are fragments of a rule. The left-hand-side of the relational operator is often abbreviated ''LHS'', while ''RHS'' stands for right-hand-side.
Order Rule Fragments So That Rules Fire Only When Necessary
The evaluation of rule fragments determines when a rule fires. Therefore, the order in which fragments appear in a rule is important. The more quickly the model can determine whether a rule is true or false, the more efficient the model can be. And of course, the more quickly the model determines that a rule should not be fired, the sooner the model can continue with other processing. Placing rule fragments in order, from most likely to prevent the rule from firing to least likely to prevent the rule from firing, can improve performance.
Always test your rules to ensure that they fire only when appropriate. Knowing under what circumstances a rule's results will or will not be used is also important. For example, an expansion rule that always fires but will not pick something in the expansions section if the quantity formula results in zero, or if there are no matches for the formula in the > and <= fields in the expansions section, is inefficient.
Keep Rules Generic
Whenever possible, write rules that are as general as possible. For example, the following rule can be attached to any product to which the productType and handsetType properties are attached:
If propval(productType) != value(selectProductType)and propval(handsetType) != value(phonePreference)set _isVisible=0
This rule fires only for products where the productType property is attached AND does not match the selected product types AND if the selected phone preferences do not match the current product's preferences. This rule can replace other specific rules such as the following:
Use Formulas Where Appropriate
In many circumstances, formulas can be used instead of rules. During modeling, formulas are maintained as attached properties that have as their value an expression that is evaluated at runtime. If any of the functions referenced in the expression cannot be evaluated, the formula acts like a rule that has not fired. If you turn on the multipass rule firing, the formula is re-evaluated during each firing pass until rule firing ends or until the formula produces its result.
Use a formula rather than a rule when the only condition for requiring that you compute a result is that the function or the properties used in the formula have values.
Suppose that you want to compute the turning radius for truck components such as axel and wheelbase to ensure that a user's choice of truck components makes sense. You might attach a formula to the relevant truck components to compute the turningRadius as follows:
This formula will fire when each of the value(axelTurnFactor), value(wheelBaseTurnFactor), and sum(turningElements) expressions produces numeric results.
The equivalent rule is as follows:
The condition portion of the rule is long and seems to always evaluate to true. However, functions can return NULL if a property that they reference does not exist. Therefore, this rule checks that the result is non-NULL by evaluating whether a returned value is >= 0 or < 0.
Avoid Specifying Paths to Instances of Items or Properties
The LHS and RHS of a rule fragment consist of a function and a property name. The property name can contain both relative and absolute path information. However, specifying a property's path information in a rule fragment can result in the rule becoming inoperable if the path information or option classes change.
For example, the following rule references wheelSize and wellSize using fully specified path information. If the modeler needs to rename either the wheels or fender option classes, or wants to reuse the rule in some other model, the rule may not operate correctly.
If value(*.wheels.wheelSize) == literal("17in")and value(*.fender.wellSize) < literal(17)set _isVisible=0
Use path information only if you want to access one specific instance of a property, and then only if it is not possible to make a new property type to hold this value. If you must reference a property's path name, it is often better to use relative pathnames rather than absolute pathnames.
Should You Use Constraint Tables or Rules?
Constraint tables limit a customer's choice of one or more option items based on the customer's choice of another option item. For example, the choice of an exterior color for a car might limit the choice of interior colors.
Constraint tables work best for simple validation, for example, an option item does or does not work with another option item. Simple constraint tables are easier to maintain than rules. However, large and complex constraint tables are hard to maintain and can lead to performance issues. Constraint tables are turned into rules internally.
Rules are best for expressing complex validation issues, and are more versatile than constraint tables. While both constraint tables and rules can display error messages, you can also create rules to set properties or make choices.
Techniques to Simplify Model Creation and Maintainance
Using Option Class Groups, Option Item Groups, and Sub-assemblies: This technique works well when a group of options is repeated in many different models. For example, suppose that every computer you sell includes a list of hard drives that the user can choose from. Creating Option Class Groups, Option Item Groups, and Sub-assemblies allows the modeler to create and maintain common information in one place so that you can use it in many places.One disadvantage of this technique is that it can lead to overly large models if a sub-assembly is included in the same model many times.Sub-model punch-in and punch-out: This technique is useful when a configuration contains a selection that is also configurable. You can use sub-model punch-in and punch-out to nest complex configurations within one overall selling model.One disadvantage of this technique is that all copies of the configured product contain the same configuration.Dynamic instantiation: This technique allows multiple instances of a configured product within a single model. Each instance can have a different configuration.Tools to Guide Model Development
Modeling can be a time-consuming and tedious exercise, but in the end the correctness of the modeling and the scalability of the created solution are key to the success of the project. To aid in creating scalable and correct models, there is a collection of tools that can be used in various phases of development to guide the modeler. During development, the trace log and the model reporting tool can help the modeler determine which models to debug. Before pushing models into production, their scalability and stability can be tested using the load testing platform. Finally, during execution, the model cache status page can provide insights into the model's usage of the system, and the log analyzer can be used to make sense out of megabytes worth of log information.
Using the Trace Log
The trace log shows the execution of the rules engine. This is often, though not always, the most time-consuming part of each request that the configurator makes to the server. The trace log is designed to provide the information necessary to debug rules that misbehave and to track the execution time of rules. Therefore, always start debugging by reviewing the trace log.
To create trace logs using the Visual Modeler:
The model displays in the Model Preview tab.The model runs in a separate window.The trace log appears in a separate window.The trace log consists of two sections. The first section is the rule firing trace and the second section is the property pool.
The following illustration shows a section of a sample rule firing trace:
The rule firing trace has the following columns:
Sequence number: You can use this column to communicate with others about rule issues.Elapsed time: This column shows how long it took starting from the time the log entry was made until the start of rule firing.Body of the trace log: This shows the aspects of the rule firing, such as a condition being evaluated, an assignment occurring, the start of a rule or the conclusion of a rule, and so on.The log shows the number of milliseconds needed to fire a rule after each rule firing entry. The total number of milliseconds needed to run the model is logged at the end of the rule firing trace.
The property pool trace has the following columns:
Name: This is the full pathname to the item and the property on that item.Type: This is the property type for the named property, such as Numeric, List, or String.Value: This is the value of the property after the rule has fired.The following illustration shows a section of a sample property pool trace:
Use this log "single user" to get a feel of how extensive the rules are per click. Check how long it takes to fire the rules. If the answer is more than 100-200 ms, you may have scalability problems. In such a scenario, use the trace log to figure out if any particular rules are performing badly.
Using the Model Reporting Tool
The model reporting tool can provide an overview of a model's size relative to other models. Use it to help make decisions about which models to test. You can track the test results over time so that you can determine the amount of change to the model.
Using Load Testing Tools
Load testing tools help you determine how your model will perform after it is deployed. Keep the following in mind before using the load testing tools:
Understand what is being tested.Isolate your test cases so that you know what the impact means (local versus remote LAN testing, testing with and without clustering, testing with and without web fronting, and so on).Understand that as models change, so must any scripts that you use to perform testing and replay test scenarios.Cache Status
cmd=configstatus shows the current contents of the cache.Performance
Rules
Excessive paths to items:A rule that adds memory by:
totalMem = value(*.adapter.1.memory) + value(*.adapter.2.memory) + value(*.adapter.3.memory) + value(*.adapter.4.memory)
will perform much more slowly than:
If the memory property exists in other places for other uses so that sum(memory) would produce the wrong value, introduce additional properties on the adapter items 1-4 called adapterMemory, and use:
This is much less maintenance effort than maintaining:
totalMem = value(*.adapter.1.memory) + value(*.adapter.2.memory) + value(*.adapter.3.memory) + value(*.adapter.4.memory)
Write rules to fire only when they are needed:A rule that assigns totalMem = sum(mem) only needs to fire if count(mem) > 0Properties
Define properties at the correct position in the model group hierarchy:If they are local only to this model, define them in the model.If they may be used by other models within this model group, define them in the current model group.If they are more global than the current model group, define them at the lowest point in the model group tree that is an ancestor of a model where you want to use the property.
© 2011 IBM Corporation. All Rights Reserved |