Life belongs to the living, and he who lives must be prepared for changes.
Johann Wolfgang von Goethe
Latest Update: Pictures fixed to show using the text for the Submission Date. Thanks for picking up on that Carsten!
This week I had the joy of running a SAP NetWeaver Decision Service Management workshop – titled Cutting the IT Backlog via Do-It-Yourself Business Rules and Decision Services – at the Mastering SAP Technologies 2014 conference in Melbourne. Not only is it great to get together with like-minded folk who really understand the potential of business rules, I find preparing for annual conferences is a great opportunity to reflect on lessons learned over the past year. So this blog captures a few of those lessons learned on how to build adaptations directly into your business rules.
Now these lessons have come from some projects I have been working on where we are dealing with implementing government legislation using decision services and business rules. After nearly a year of dealing with legislation I have come to following conclusions:
- Legislation includes the most complex and complicated decisions and business rules any organization is likely to face
- Legislation is prime example of business rules that adapt over time, as new legislation and legislative amendments are introduced throughout the year at irregular intervals in response to changing markets, high profile news events, political initiatives, and lobbying by strategic interest groups
- Legislation is a prime example of decisions that may need to be applied retrospectively, e.g. when a citizen raises a legal appeal, it is often necessary to re-execute the decision under the original legislation with adjusted inputs based on the outcome of the appeal, and such appeals often take weeks, months or sometimes even years before the outcome is decided
- Most business and IT people are not very good at including adaptation strategies in their rules design – the focus is always on what happens now
So here a few simple strategies that we have used time and time again to cope with even quite complex adaptations. All of these can easily be built into decision services and business rules from the beginning of your design.
Minor adaptations: Add an Effective Date column to your Decision Table
When your focus is on what happens now, it’s easy to think of many thresholds, limits, rates and factors as unchanging. For example I can’t count the number of times I have seen workflows written with static deadlines, e.g. Escalation Date = Request Submission Date + 2 days.
More often than not, someone later wants to increase the deadline temporarily to cope with national public holidays, or the summer office close-down period.
It’s a not uncommon problem to forget that things can change or that exceptions can occur which vary the usual rate. In legislation one of the common assumptions of thresholds that never change are those built around a person’s age. E.g. A child is someone under 18 years of age; an old-age pensioner is someone over 65.
We tend to forget that these limits are actually quite arbitrary, and are a matter of current policy and legislation which can change.
Last November the Australian Productivity Commission proposed raising eligibility for the old-age pension from 65 years to 70 years, and since then there have been a number of media soundbites from Australian federal government politicians suggesting that this proposal is being taken very seriously.
Now the age at which a person is eligible for an Australian old-age pension has been 65 years old for over 100 years, so it’s completely understandable that both business and IT would think of the pension age as unchanging, but we simply can’t guarantee that will be the case in the future. To make things worse, media reports have suggested that increase in pension age will be gradual. The previous federal government has already introduced gradual changes to increase the retirement age by 6 months every 2 years from 2017, and it’s likely the pension age might be increased in a similar way.
If we used a constant or entered a direct value of 65 for the pension age in our business rules we would have a lot of rework to adapt our decision services and business rules if and when such changes are introduced. But if we instead store the value in a decision table and simply add an effective date column, we can easily cope with these sorts of changes, without having to worry about when or if they will be introduced.
By using a decision table with a date column, all anyone will have to do to adapt the pension age if such changes are legislated, is to add new row to the decision table; and if the changes don’t happen we simply only have one row with effective date <= 31.12.9999 and the rules will still work fine. There’s also very little impact on our design to add this from the beginning. We just add a simple expression to evaluate to read the pension age from the table and store in a Ruleset variable for use in any subsequent rules.
Such a decision table might look like this:
Of course this approach works equally well for those limit, thresholds, rates and factors that we do expect to change – like tax rates, inflation factors, superannuation caps, etc.
Major adaptations: Ruleset Preconditions
The thing about major adaptations is that they are nearly always introduced on a specific date. With government legislation, legislation and legislative amendments are always introduced on a publically announced date. For us the Australian Commonwealth law and legislation website http://www.comlaw.gov.au/ is the fount of all knowledge for such dates. In the private sector, major changes are also often introduced as at specific date – the introduction date of a new initiative or project, the start of a new fiscal year or new calendar year.
There’s another common consideration for major adaptations, i.e. while the underlying business rules of the decision service may need to be radically different from the previous version, often there is a lot of opportunity to reuse existing business rules.
Now you could just change your whole Ruleset and use the BRFplus versioning to decide which version of your decision service to run. That’s fine so long as the old rules were perfect in every way. Not so great if as a result of a legal appeal, complaint, or objection, an adjustment is needed to the old rules – because of course you can’t fix the old version and redeploy it again under the same deployment date once those rules have been superseded by a new version.
So we found a smarter, more flexible, and more visible way to ensure the correct rules are considered, and it’s made executing rules retrospectively much easier as well: Rulesets with preconditions. It works like this:
Each major adaptation, in our case each major legislation act or amendment, has its own ruleset containing the rules applicable to that adaptation and the sequence they are to be executed. So long as all the rulesets are contained within the same Rules Application it’s easy to reuse rules, and their underlying expressions and actions, in both rulesets.
Usually somewhere in the inputs of your decision service (aka BRFplus function) you will have passed a date that can be used to decide which version of the business rules should be used, e.g. the submission date of an application or request.
Before running each ruleset, that date can be compared to the dates for which the particular adaptation applies. This makes running the decision service for future and retrospective dates very easy – just pass the appropriate date as one of the decision service inputs, and – Hey Presto! – the correct rules are applied.
We can even mix rulesets with and without preconditions. So if there is a truly common ruleset that runs pre or post the others, all that needs to be done is to set the ruleset execution priority and each ruleset will be applied in the correct sequence.
Tip: Restrictions of preconditions is that whatever needs to be checked must be part of the decision service context, i.e. part of the inputs and outputs of the BRFplus function itself, and the precondition itself must be expressed as a Value Range expression.
Back to the Future: Constants for Milestone Dates
Now this is one strategy that was hard won. While our design had catered for most things that could change, there are always those true constants that never do. Like the introduction date of past legislation or a past initiative. It’s never going to change. So at first we were entering some of these as direct values in conditions, cells of decision tables, values in formulas, preconditions in rulesets, etc.
We only realised we were creating a problem for ourselves when we, admittedly without thinking it through, started using the same approach for an upcoming milestone date. It was a legislation date, it was already announced, and so it wasn’t going to change, right? Wrong! Politics being what it is, certain political lobbies were barracking for more time to introduce the changes, the politicians agreed and all of a sudden our set-in-stone legislation date was crumbling. Worse, the new date was in flux – we were told it would either be original legislation date + 1 month, or original legislation date + 2 months. Not happy!
Back to the design drawing board and we realised we needed to go through and change all those direct values to use a single constant expression. All well and good, but then something interesting happened…
We were discussing the testing phase in depth with the various business groups and the data migration team, and we started to realise that by moving from direct values to a constant we had accidentally discovered an easy way to handle future and retrospective testing; and improve the meaning and visibility of our rules at the same time.
Putting a milestone date in a constant meant we could give a meaningful name to the constant, e.g. Live Longer Act. Because we reused that constant across a wide range of expressions – e.g. in conditions, decision tables, formulas – all of a sudden all of these expressions became that much more business meaningful. For instance, instead of a row in a decision table indicating a rate applied from 01.10.2014, now it read as the rate applies to the Live Longer Act. Not only more meaningful but greatly improved the accuracy of assigning the correct date to the correct expression.
When we came to testing, we had a lot of data being migrated that we could use as test data, but of course it was all for past dates. So how could we test our future rules without creating or copying a lot of data to future dates? Easy! All we had to do was adjust the date in the constant, and everywhere that constant was referenced was automatically adjusted as well. So all those conditions, decision tables, preconditions, formulas, etc. were now pointing to 01.03.2013 or whatever date we chose, and we could then run before and after testing on past data just using the constant to control whether we were running future or retrospective rules. Magic!
P.S. Don’t forget to set your constant back to the real date before you deploy your decision services to production!
Anyone else have a strategy to share?
These 3 simple strategies have made all the difference for us, but I am sure there are many other approaches that could be used. We are so privileged to be part of the SAP Community Network, and I know the Business Rules Management community is very active in helping others. So I would be delighted to hear how others have tackled building rules for adaptation in your comments, or even whether you have used similar approaches successfully on your site.