Skip to main content

Designed a mini business rule engine, here is how

Greetings!

When you are a passionate developer, you will always try to do better things, and experiments with new things. In this article, I will explain how we achieved a complex code cleanup by creating a mini business rule engine.

Why is it?

There is business logic depends on each other due to business behavior, mainly due to years of development. The business knowledge of the behavior is missing.

Problem statement

This legacy module has been developed a long ago and new codes are also a copy of those codes. I see numerous issues there.
  • Business knowledge is missing (Logic is hidden everywhere)
  • Unmanageable codes due to years of development
  • Complex logic
  • The main APIs (multiple) depend on this
  • Two domains are coupled
  • New joiners cannot understand the domain
  • Error-prone due to fragile codes

How to approach

As there are higher-priority tickets in the backlog, it is difficult to prioritize this kind of work as it might break everything. However, we need to improve this sooner than later. Hence, I took my time on the initial analysis. It was a lengthy process as it took nearly 3 months to complete everything.
  • Read the complete code
  • Gather 5 APIs codes paths into separate excel sheets
  • Evaluate findings with BA
  • Merge all the logic as a generic logic
  • Re-evaluate with BA
  • Improve missing scenarios
  • Design rules
  • Implement rules separately
  • Plug the rule engine into the main path one by one
  • QA and re-evaluate
As you could, until the last two stages, this is no impact on the existing code as well.

Technical design

First of all, you need to think a lot before introducing a business rule engine because when the business changes dynamic rule engines might not work. Hence this is not a "can do anything" like an engine. This is a solution to the given problem. Hence there are a few considerations.
  • Should not over-engineer
  • Decouple 2 domains
  • Remove the logic from the main API paths
  • Anyone should be able to quickly understand
Hence, I utilized a simple design pattern which is the Rules Design Pattern. One notable decision I took is, we should not do any persistence operations inside the rules, instead it evaluates the rules and return the decision. The calling path will then execute the decision by separating DomainB from DomainA.
Why the decision and execution are separated also due to business complexity.

What is the gain

We have achieved many things. To name a few;
  • Revealed business logic
  • Business logic is in a single place
  • Readable, maintainable, and extendable code
  • Eliminated multiple bugs
  • Decoupled business logic
  • The main logic is isolated

Conclusion

In this article, I described the process, and how we achieved the clean-up of a legacy code by creating a mini business rule engine. While the code and design might slightly change for different domains, you also can try these things to improve your code.

Happy learning ☺

Comments