Tagged: BDD ndecision Fluent AOP PostSharp

Basic NDecision Use

NDecision is a Fluent decisioning engine written with Behavior Driven Development principles in mind. It makes business logic easy, allows the encapsulation of logic flow into chainable statements that can be set up and executed on object instances using Lambda syntax. If you're a BDD practitioner, NDecision will allow you to write your BDD rules using easy-to-follow conventions and familiar Gherkin nomenclature. Likewise, if you're a TDD practitioner, your NDecision specifications (the actual rules you write using Lambda expressions) can be used simultaneously in your unit tests. Rather than separate the unit testing code from the true application code, NDecision allows you to write the rules once, test them, and then use them in your real production code. 

NDecision is freely available via NuGet as a single assembly you can easily reference from any .NET application. If you're interested in the core NDecision functionality, grab NDecision via NuGet and start objectifying your logical flow today.

NDecision NuGet Install

NDecision Core Simple Example

Take a look at how easy it would be to solve a common logical problem using NDecision.

NDecision example usage scenario

NDecision via AOP

If you're into Aspect-Oriented Programming or you like things to be a little more dynamic and automatic, a second option exists that you might find interesting. The NDecision.Aspects package makes use of the amazing AOP product PostSharp, by SharpCrafters, to enable logic execution automatically at run-time. Rather than write your logical specifications inline, you implement the IHasSpec<T> interface. This interface's single method, GetSpec(), allows you the freedom of wiring up your logic in one place (or in many places, if you prefer to have your specifications split into individual classes based on your own need or preferences). 

Refactoring the Example for NDecision.Aspects

I'll build on the previous example and refactor the code to use the NDecision.Aspects package and to provide some insight into the difference. First of all, the logic from the original code has been moved into an implementation of the IHasSpec<BugsBunny> interface. 

Implementing the rules for an object in an IHasSpec implementation

Once your IHasSpec<T> implementation has been written, the majority of the work is complete. To use the specifications outlined in the IHasSpec<T> implementation, the ApplySpecsBeforeExecution (or ApplySpecsAfterExecution) attribute class can be used to decorate the methods whenever the specifications need to be applied. The screen shot below demonstrates how, using the ApplySpecsBeforeExecution attribute, the rules will automatically be applied prior to the method's logic being executed. 

Method with a parameter decorated for automatic specification application

If a second parameter for which there existed IHasSpec<T> implementations were placed on this method, specifications for that parameter would be picked up too. In this way, AOP takes over - for any parameter added to this method for which there exists an IHasSpec<T> implementation, the specifications will be dynamically found and executed on the parameter instance at run-time.

Your rules, in a sense, are automatically applied whenever you want them to be applied. 

NDecision with AOP, Option Two - Self-Awareness

Now, there may exist a circumstance where your object instances - in this case our favorite childhood cartoon character - should be allowed to do their own work based on the specifications and how they should be applied. In these cases it would be more optimal to have the capability of applying the ApplySpecsBeforeExecution or ApplySpecsAfterExecution attributes to the target class itself (or specifically, to methods of the target class). The code from above has been refactored with this idea in mind. Specifically, we've given Bugs his own method, also decorated with the ApplySpecsBeforeExecution attribute. 

Self-driven functionality

Likewise, the program code will need to be changed so that it allows Bugs his autonomy.

Allowing the target class to drive itself

Both methods result with the following obvious output - a console window showing the directions Bugs takes on his journey, in the order they were taken. 

Output of the demonstration code

Just like the NDecision core project, NDecision.Aspects is available for free via NuGet. Don't worry about the dependencies or having to install both packages; simply installing NDecision.Aspects will bring down everything you need, including the PostSharp assembly, as SharpCrafters so generously offer it up as a NuGet package too. 

NDecision.Aspects NuGet install

Happy coding! I hope you give NDecision a spin. If you do take the time to play with it, please let me know how it works out for you via the comments form. Or, you can find me on Twitter at @bradygaster.