This is the final post in a four-part series that details the creation of a dynamically driven questionnaire (or survey) using Dynamics CRM and the InRule BRMS. You can find previous entries in this series here:
Part I: Overview
Part II: Dynamics architecture
Part III: Defining client-side ViewModels using knockoutjs
In this final entry in my series on dynamic surveys, we will examine the business logic and rules involved in the process of administering a guided survey. The example that I'm using models the rate calculation process needed to provide a quote for business insurance. Looking for the source? I’ve provided information at the end of the entry on how to obtain it
In addition to the InsuranceQuote entity which serves as the root for this survey's Domain, there are a few other data structures that are important to making the survey function. They are:
- Survey Definition
- Question Definition
Figure 1: The survey schema
The idea is that we are establishing a prototypical relationship between what is the platonic ideal of a Survey/Question and an actual concrete instance of that particular entity. For example, when a user opts to take a survey, information from the Survey Definition is *copied* into an instance of a Survey entity rather than simply referenced.
Segregating Command and Query
One of the biggest advantages to using the prototype (or template object) pattern is that it promotes a clean separation between the read/write aspects of the application.
Commands are issued using the Dynamics CRM SDK, either from the rule application executing rules (e.g., adding the next question to the survey's question collection based off of a definition) or from the client UI (saving a user's answer by updating a question's answer attribute). This allows the UI logic to remain focused on its core duties - retrieving a list of questions, rendering them, and recording responses. Survey administrators use standard Dynamics CRM forms to add new question definitions and associate them with Survey Definitions, while the logic governing questions is implemented by the Rule Application controlling the survey. The Cycle is maintained.
The basic software principle of separating concerns is equally as valid in a rule application as it is in any other piece of software. One of the measures that I took to help with that aspect was to separate infrastructure-related rules from survey-specific rules using ruleset folders. The survey entity rightly “owns” the specific rules regarding survey questions which reside under the ‘POC1Survey’ folder. Modifying the current survey or even adding an additional survey (e.g., ‘POC2’) requires much less work and carries a lower risk of problems when areas of change have more defined boundaries:
Figure 2: Separation of infrastructure from survey rules
Divide and Conquer
The rules that drive a dynamic survey are divided into several discrete functional areas:
- Controlling rulesets that coordinate and manage the execution of other rules. Their primary job is to go through and execute a list of rules one at a time, optionally making decisions before/after each that affect how execution should proceed
- Rules that decide which question to present to the user
- Logic that maps users' response to questions back into the business domain
- Business domain rules that make use of data gathered and mapped from the survey questions to make decisions and take action
The "brain" of the rule application is our RatingController. This ruleset is responsible for managing the list of rules to execute (acts as a dispatcher), and lives at the root InsuranceQuote entity context.
Figure 3: Entry point to rule execution is the Rating Controller
Rules Entry Point
The survey is first initialized from a Survey Definition loaded from Dynamics using the Rule Helper assembly library (provided as part of our Dynamics Integration Framework, the library allows arbitrary queries to be issued against Dynamics from within a Rule Application). Because our Survey entity is a child of our Insurance Quote entity, and not the other way around, we preserve proper encapsulation by passing the Insurance Quote entity to the business rules responsible for mapping answers back into the business domain.
Once the survey has been instantiated, it's time to figure out what question needs to be asked (if any) - but only if there aren't any questions that are still awaiting an answer. Assuming that there aren't any pending questions, the rules then evaluate the survey data against the list of possible questions, taking into account responses to previously asked questions. Some spiffy vocabulary templates round out the Business Language rules to allow a very natural way of conveying the survey logic, as the question below demonstrates:
Figure 4: Vocab templates make for an elegant way for authors to express their intent
Controlling the Order of Questions
The reason why we halt rule set is because in this scenario we want to ensure that questions are asked in a particular order, and that users are only ever presented with one new question at a time. This is something that can confuse people. When designing their surveys, I’ve seen many folks incorrectly assume that creating an explicit field to hold some type of ordinal value will control the order of questions being asked. In my opinion, that’s not a favorable approach because sticking an integer field on something isn't a natural ordering scheme – additional logic is needed to actually apply and enforce the ordinal. It's much better to design things in such a way that the questions are asked in the proper order because that's the order that they're structured in the rules:
Figure 5: Natural ordering of questions solves a lot of problems and prevents others
Want to change the order that questions are asked? Simply re-arrange the rules as you see fit! Other than the CompleteSurvey rule, which must be last in the list, it doesn't matter to the rules what order they are presented.
Taking Action from Answers
After determining what question should be asked (or flagging the survey as completed), it's time to map the survey responses back to the business entities. That's the job of the POC1Responses ruleset.
As a side note, the name of the survey is POC1, so I've named rules that pertain to this specific survey accordingly. That gives us a nice separation between infrastructure and survey-specific logic. Each action in this ruleset defines the end-state of answering a question or questions:
Figure 6: Rules are narrowly scoped to a specific set of actions
Validating Data and Achieving Idempotence
The final aspect of the rules is a bit more subtle, but has perhaps the greatest impact on the behavior of the survey.
Because data collected from survey responses is being mapped back into the business domain, it is necessary to ensure that the values being written are in line with the business domain’s data validation rules. To achieve that, an auto-sequential controlling ruleset on the insurance quote was added that, in turn, invokes a survey-specific controlling ruleset that examines the pool of answered questions to determine which business-domain specific validations need to be evaluated. Here’s what the Employee survey-specific validation control rule looks like:
Figure 7: Validation should be conditoned on answers provided to relevant questions
If this all seems like it’s more complicated than it needs to be, consider what would happen if rules were executed multiple times against the same set of data – any actions taken by the rules in response to answers might be repeated.
What we want is to structure the rules execution process such that any arbitrary number of application of rules for a given beginning state will always have a single consistent resulting end state – a concept otherwise known as idempotence. We achieve this objective by structuring our rules in such a way that we both a) segment the processing of data from the actions taken as a result of an answer, and b) author survey-specific rules in such a fashion that each rule has no dependency upon any of its siblings executing before or after it.
How to Get the Source Code
We want your implementation using InRule to be a stunning success. If you’re an existing InRule customer and you’re currently using Dynamics, this is a great opportunity to engage with myself or one of my colleagues on the ROAD (Rules Oriented Application Development) team where we can provide not only the full source material but also guidance and advice on integrating Dynamics with the survey and the InRule product. Not (yet) a member of the “no hard-coded rules” club? Drop me a line here in the comments, via the email address above or tweet us and I’ll get you set up with the source.
Creating the survey functionality and getting to the point where we’re at today wouldn’t have been possible without the support and assistance of my co-workers John Hauppa and Mark Lonsway here at InRule. Their guidance and direction at key points has been essential to this production, and deserves recognition. Also thanks to the rest of my colleagues at InRule for being an awesome and talented group of people with whom I’m grateful for the opportunity to learn from.