omni.interfaces
OmniRules Interfaces
License: Agileworks Community License Agreement Version 1.0
Documentation
Introduction
Omni-Interfaces is part of the OmniRules Suite of apps and the most foundational of all the packages. It contains all the interface definitions so it's lightweight if you need to interface with OmniRules when starting a new software package.
Problem and solution domains are expressed in TypeScript interfaces or simple JSON, which is then used to generate OmniRules decision artifacts and engines.
Interfaces
Aggregate
An aggregate Domain Driven Design, is a cluster or a group of associated objects that we treat as a unit for the purpose of data changes via rules. Each aggregate starts with a root and has a boundary. The boundary defines what is inside the aggregate. The root is a single starting-point entity.
interface AggregateInterface {
name: string; // The name of your aggregate root
version?: VersionInterface; // Use this to audit your aggregates as they evolve
facts: FactInterface[]; // Facts are either known, or derived by a rule/rules
documentation?: string; // It's always important to document your aggregate
}
export interface VersionInterface {
major: number;
minor: number;
patch: number;
}
Fact
Facts are either known beforehand or are derived by a business rule. From the POV of our aggregates, facts are datapoints that are immutable once known, or calculated once it is sufficient other facts to determine it's result.
Calculated facts are usually opportunistic and declarative, not imperative. They lie dormant until the time is right. Aggregates can be executed over and over until all it's facts are known. Once known, the fact does not change.
Known facts are usually immutable and do not trigger a recalculation unless explicitly request by setting the RuleBehaviour of a rule to AlwaysCalculate
interface FactInterface {
name?: string; // The name of the fact. Eg: Eligibility
path?: string; // Eg: Application.Eligibility
rule?: RuleInterface; // See Rule
rules?: RuleInterface[];
pathMapping?: PathMappingInterface[]; // Map dependency facts from you Business Object Model (BOM)
dataType?: DataType;
sampleValue?: any; // Useful for documentation and sample BOM generation
enumerations?: string[]; // If dataType is string, you can specify valid enums
documentation?: string; // Again, always important to document everything
}
export interface PathMappingInterface {
replaceName: string; // The required fact from the Rule POV
withPath: string; // The fact path from the BOM POV
}
type DataType = "string" | "number" | "boolean" | "date" | "object" | "array" | "bigint";
Rule
A rule is what we use to implement our Business Rules. They can be defined atomically and should be very simple and expressive or declarative. Depending on how you write them, they can be reused by other aggregates.
Let's see an example rule called Eligible simply checks if an Applicant is over the age of 18. If the age isn't known, the rule won't trigger and remain dormant until the applicant's age is known.
Sample Rule.statedAs code for rule called Eligible
:
ApplicantAge > 18
As simple as that. For single lines that's all you really need. If you wanted to combine it with another fact, let's say no criminal record and you end up writing multiple lines, use the theResultIs function:
const
hasNoCriminalRecord = CriminalRecord.length === 0,
isOfAge = ApplicantAge > 18;
theResultIs(
hasNoCriminalRecord && isOfAge
);
{
"CriminalRecord": [],
"ApplicantAge": 19
}
See omni.models for more details on path mappings for more complex domains.
Avoid using too much or-logic, instead break your rules into smaller pieces of logic that will in turn get used by another piece of rule. This allows us to write them simple, have a clear trace for our audit because the calculation's inner state is kept immutable and is also very helpful during data analysis, AI training and troubleshooting.
interface RuleInterface {
name: string; // The name of your rule
statedAs?: string; // A simple Javascript statement that expresses the rule
dataType?: DataType;
behaviour?: RuleBehaviour; // Determines when a rule is executed in an engine
documentation?: string; // Always good to document stuff
}
type RuleBehaviour = "AlwaysCalculate" | "OnlyOnceWithAllFacts" | "OnceWithSomeFacts" | "Disabled";
type DataType = "string" | "number" | "boolean" | "date" | "object" | "array" | "bigint";
Copyright Agileworks 2019