Now we have worked for a while with Backlot framework, I like to share an example about how easy it is to work with this pattern and show you how you can create a more “customer friendly” conversation while defining and programming the application.
Read it as a first step by step example on how to create a simple application with the Backlot pattern.
The Scenario based Process
When starting projects we start defining roles and secenarios. This basically is quite similar of defining a datamodel for your application. Roles are the objects which are going to “play” the Scenarios you describe. You can define these for example by using techniques like Event storming but you can use others as well.
A shopping cart example
For an example we like to implement, a very basic shopping cart with one product. The description is “I grab a cart go to a shelve, grab a product from the shelve and drop it into my cart. I then walk to the checkout where I checkout the the product in my cart”.
This is a basic shopping experience as we are used to from day to day, described in human language. Based on this we can easily define “roles” and “scenarios”.
The roles are all “physical entities” involved. In this case:
- Cart
- Product
- Customer (described as I in the story above)
- Shelve
The scenarios are f.e.
- Grab cart
- Drop product in cart
- Checkout
Role
From here it starts to get more technical, but don’t be afraid we use our human story as the baseline. We have to define the roles and scenarios in more detail. Let’s take the product. We define this as:
public class IProduct : IRole, // optional: IPersist
{
string Uid {get;}
string Name {get;}
decimal Price {get;}
}
This means a product is something with a unique identifier, a name and a price. Nothing less.
Actor
Now you have defined the role(s). You as the director of this “movie” can start searching for the right actor(s). Let’s for example assume there is an ERP system in place where all products are in. Products look like this in this system.
{
"Uid": "B-01",
"Name": "BANANAS",
"Price": 2.99,
"Weight": 0.5
}
This seems to be a perfect candidate for our role.
Note 1: This example actor is using the same property names as the role defined. This is not needed by the Backlot framework, but we leave what we call “presenting” for another post.
Note 2: The actor is something which is what it is. It’s an entity, from an other system, we don’t have any influence on. But adopting the actor as a role in our system we can learn it. However this is something for a new post as well.
Note 3: As you can see the object we are now using has an extra property “weight”. While we do nothing in our scenarios with it, the property is still part of the actor. Maybe a watcher like the shipment provider (currently not part of our use case) like to know the weight. Backlot does not forget these properties because we do not rely on traditional mapping. We experience this as one of the strengths of the framework and it very well fit agile development techniques. I like to talk in more detail about this in another post as well.
Scenario
Now we have selected an actual actor, which can fulfil the role, we can write the scenario.
Here is where the real magics starts. You can look at a scenario as a “static function” or maybe even a “micro service”.
Because a scenario is a generic definition of everything thats executed (and can be watched) a lot of generics are true, but the 3 most importants are:
- It’s played by one main role.
- Other roles can play together within this scenario and after that they “know” each other / are related to each other.
- A scenario result in something.
Note: In our framework we have more generics like; a director directing the scenario, configurations, follow up scenarios, events, watchers and more.
A scenario for the “Drop Product In Cart” scenario can look like this.
[Scenario(typeof(DropProductInCart), access: new[] { Access.Open })]
public class DropProductInCart : Scenario
{
public DropProductInCart (IProduct role) : base(role)
{
}
protected override ICart Exec()
{
var cart = new {
Uid = "Cart-123",
Product = role
};
// do some calculation with the product price
return cart.Presents();
}
}
or even simpler like this:
[FuncScenario(typeof(IProduct), typeof(ICart), "dropproductincart"]
public static ICart DropProductInCart(IProduct role)
{
var cart = new {
Uid = "Cart-123",
Product = role
};
// do some calculation with the product price
return cart.Presents();
}
In this example DropProductInCart creates a cart add the product and then returns the Cart.
Disclaimer: This is not a reallife scenario because in our human story above we have defined “Grab Cart” as well which likely “creates” the cart in our instance, instead of having to do that within the DropProductInCart scenario.
When roles are marked as IPersist the scenario takes care of saving all roles used in the scenario. This means (main roles, supporting roles and results which are roles). Also do all these roles automatically get a relation with each other when used within the same scenario.
This scenario can be played in two ways.
1 from within c#
product.PlayAsync();
2 from an api endpoint
POST {{host}}/api/role/product/dropproductincart/
content-type: application/json; charset=UTF-8
{
"Uid": "B-01",
"Name": "BANANAS",
"Price": 2.99,
"Weight": 0.5
}
or when the main role (Product in this instance) is already persisted before:
POST {{host}}/api/role/product/dropproductincart/?uid=B-01
content-type: application/json; charset=UTF-8
An administration panel
Because a lot of generics are defined we can create a smart administration portal around this model. So we did. At Marvelous we have created a generic portal supporting your Backlot instance; scenarios, roles, and relations. Curious, let us know and get in touch with us via Marvelous.nl.
Verdict
Hopefully you have experienced a little bit how close the programming process is with the process of analysing and defining the application. The Backlot framework Marvelous has created within C# does help with a lot of generics making it more easy to implement scenarios and focus on the “real” implementation. We also experience new developers can adopt it very easy because we only have 4 concepts (Actor, Role, Scenarios, Watchers) you need to be familiar with and at it’s core the framework is adopting dos and don’ts from other best practices all developers are familiar with.
