Why pattern is good for software development?
The full sample code for this post can be download here from my github Account.
In the real word, we usually said : “don’t reinvent the wheel”, that say before trying to do something, just look around if someone have not done it before or if there is not a better solution already put in practice by another people to solve the same problem.
Patterns are essential to software design and development. They enable the expression of intent through a shared vocabulary when problem solving at the design stage as well as within the source code. Patterns promote the use of good object-oriented software design, as they are built around solid object-oriented design principles.Patterns are an effective way to describe solutions to complex problems. With solid knowledge of design patterns, you can communicate quickly and easily with other members of a team without
having to be concerned with the low-level implementation details.
Patterns are language agnostic; therefore, they are transferable over other object-oriented languages. The knowledge you gain through learning patterns will serve you in any first-class object-oriented language you decide to program in.
Design patterns are all about the reuse of solutions. All problems are not equal, of course, but if you can break down a problem and find the similarities with problems that have been solved before, you can then apply those solutions. After decades of object-oriented programming, most of the problems you’ll encounter will have been solved countless times before, and there will be a pattern available to assist in your solution implementation. Even if you believe your problem to be unique, by breaking it down to its root
elements, you should be able to generalize it enough to find an appropriate solution.
The Domain Model pattern is useful when dealing with complex business logic. A popular design methodology that utilizes the Domain Model pattern is known as DDD. In a nutshell, DDD is a collection of patterns and principles that aid in your efforts to build applications that reflect an understanding of and meet the requirements of your business. Outside of that, it’s a whole new way of thinking about your development methodology. DDD is about modeling the real domain by first fully understanding it and placing all the terminology, rules, and logic into an abstract representation within your code, typically in the form of a domain model.
DDD is not a framework, but it does have a set of building blocks or concepts that you can incorporate into your solution:
The Ubiquitous language
To describe the domain, developers, architects,domain experts (someone with the knowledge and skills in a particular domain who will work closely with
you as you develop the domain model to ensure that you fully understand the business model before trying to represent it in code), and anyone else involved in a project have to speak the same language, this in DDD methodology is called Ubiquitous language.
Entity in DDD contain data and behavior in the domain model, for exemple in an e-commerce application, an entity can be a customer, or a product, in a banck system as we will se in our example in this post, it can be a a banck account ecc. Any logic pertaining to an entity should be contained within it.Entities are the things that require an identity, which will remain with it throughout its lifetime. For a database point of view, we can think of an entity as a database table but with some behavior.
Value objects have no identity; they are of value because of their attributes only. Value objects generally don’t live on their own; they are typically, but not always, attributes of an entity. For example, in some case the customer address in an e-commerce systhem can be view as value objects.
Aggregates and aggregate roots
Big systems or complex domains can have hundreds of entity and value objects, which have complex relationships. The domain model needs a method of managing these associations; more importantly,logical groups of entities and value objects need to define an interface that lets other entities work with them. Without such a structure, the interaction between groups of objects can be confusing and lead to problems later. From the DDD definition, an aggregate is simply “a cluster of associated objects that are treated as a unit for the purpose of data changes.” The aggregate root is an entity, which is the only member of the aggregate that any object outside the aggregate is allowed to hold a reference to. The idea of an aggregate exists in DDD to ensure data integrity within the domain model. An aggregate root is a special entity that acts as the logical way into the aggregate. For example, take a look of an order entity in an e-commerce context, you can regard it as the aggregate root, because you only want to be able to edit an order line or apply a voucher by going through the root of the aggregate : that is, the order entity. This enables
complex object graphs to remain consistent and business rules to be adhered to.
In DDD,Methods that don’t really fit on a single entity or require access to the repository are contained within domain services, The domain service layer can also contain domain logic of its own and is as much part of the domain model as entities and value objects.
The Application service is a thin layer that sits above the domain model and coordinates the application activity. It does not contain business logic and does not hold the state of any entities; however, it can store the state of a business workflow transaction. This will be clear in our demo exemple in this post.
The Repository pattern, acts as an in-memory collection or repository for business entities, completely abstracting away the underlying data infrastructure. This pattern allows you to keep your domain model free of any infrastructure concerns,making it POCO and PI.
Layering is an important concept in DDD because it helps to enforce the separation of concerns.In the image bellow, we have a graphical representation of the layers and concepts that make up DDD.
Now let build a sample application in which we are trying to apply DDD methodology, we will simulate a sub fontionality of a banck system : a banck subdomain transaction. The application is build with asp.net Core MVC 3 so you nead to have all tool install, you can read this post for more information about how to setup a development environment.
Go ahead and create a new asp.net core web application project in visual studio 2019, look at the following screenshot, my project name is called “BanckAccountSystem”
Go ahead and add 3 more .Net standard library :
“BanckAccountSystem.Model” : The Domain Model project will contain all of the business logic within the application. Domain objects will live in here and will have relationships to other objects to represent the banking domain the application is built around. The project will also define contracts in the form of interfaces for domain object persistence and retrieval; the Repository pattern will be employed for all persistence management needs. The Model project will not have a reference to any other project ensuring, it remains free of any infrastructure concerns and focuses squarely on the business domain.
“BanckAccountSystem.Repository”: The Repository project will contain implementations of the repository interfaces defined in the Model project. The Repository has a reference to the Model project in order to hydrate domain objects from the database as well as to persist. The Repository project is concerned only with the responsibility of domain object persistence and retrieval.
“BanckAccountSystem.AppService”: The AppService project will act as the gateway into the application , the API if you will. The presentation layer will communicate with the AppService via messages, which are simple data transfer objects. The AppService layer will also define view models, which
are flattened views of the domain model used solely for the displaying of data.
Right-click on the Repository project and add a project reference to the Model project. Right-click on the AppService project and add a project reference to the Model and Repository projects. Finally,
right-click on the BanckAccountSystem project and add a project reference to the AppService project.(see the image bellow)
“BanckAccountSystem” : the main web project (UI project) is responsible for the presentation and use experience needs of the application. This project talks only to the AppService and receives strongly typed view models that have been created specifically for the views of the user experience.
The whole picture can be see in the following image:
Now add two c# class called respectively “BankAccount” and Transaction to the “BanckAccountSystem.Model” project with the snippet bellow:
Note that our Transaction object in this example has no identifier property and then it’s what we will call a value object in DDD. All the code above it’s self explain. If a call to Withdraw is called with insufficient funds without a check, then an exception should be raised, so go ahead and add another class in Model project called “InsufficientFundsException” and insert the snippet bellow:
you can now change the Withdraw method on the BankAccount class like this:
For best practice, we can use a generic repository to hold the same fonctionalities in our application, but because this is a simple demo of how to apply DDD, just go ahead and add “IBankAccountRepository” interface in the a new folder called “Contract” inside Model project with the snippet code bellow:
Some actions don’t sit well as methods on a domain entity. For cases like these, you can use a domain service. The action of transferring funds between two accounts is a responsibility that belongs on a service class. Add a new class in Model project called “BankAccountService” with the following code:
We can you use raw ADO.net to make a direct connection from CRUD operation with db, but in this example, we will use Entityframework and the code first approach to automatically create DB schema from our model class, so right click on the Repository project and click on “edit project file” and modify it to look like bellow:
Also add the nuget package in the listing bellow to the Repository project:
Now in the Repository project add a new class called “BanckAccountContext” with the snippet in the lines bellow:
Now add a class called “BankAccountRepository” with the snippet bellow:
As you can see from the code above,we keep our repository very simple, we have not implemented an unit of work here and we are using entity framework savechanges method to simulate our an unit of work.
Now let’s use Entity framework tool to generate the DB in localdb, return to “BanckAccountSystem” web project, open appsetting.json file and modify it so it will look like this (I have add a json entry with our database connection string ):
Also modify your startup.cs class so that we can use asp.net core dependency injection (DI) to automatically resolve the “BanckAccountContext” and “IBankAccountRepository” classes.
In my example I’m using asp.net core 2.2, so there is more one thing to do before generate database tables, open “program.cs” and modify it so it will look like in the image bellow:
Without this change, an exception will be thrown when you try to create the database schema in the next section.
we are now ready to migrate, so open a powershell command prompt and navigate to the “BanckAccountSystem” folder project and run the command bellow
dotnet ef migrations add Initial
if you get some errore saying that there is a migration assembly project just read the error and modify your start configservices method so that the command can run as in this image.
This command will add a migration folder to the web project with all instructions to create our database the first time we launch the application
I’m going for now to create a seed data class just to populate our db with random data when we launch the application so go ahead and create a c# class inside “BanckAccountSystem” model folder project called “SeedData” with the snippet bellow:
now modify your startup.cs so taht in the middleway configure method you have the following code:
Press F5 to run the web project in debug mode, now if you use a sql server client tool like sql sever management studio to connect to your localdb database (you can also do it from visual studio with server explorer toolbox), you will notice that entityframework have create all database tables base on the model class we have created inside our Model project:
Now that you have dealt with the persistence and retrieval needs, you can add a service layer for clients to interact with the system in an easy manner.
Add a new folder to the AppServices project named ViewModel and add to it a new class named BankAccountView and one named TransactionView with the following definition:
The BankAccountView and TransactionView offer a flattened view of the domain model only for presentation purposes, To transform your domain entities into data transfer view models, you will need a mapper class, we will used AutoMapper library , so add automapper packege from nuget like in the image bellow:
Create a new class named ViewMapper and inherit from Automapper Profile base class:
now go back to the web project, and add this statment bellow in configureservice method
Now automapper will be able to map the model and viewmodel class buy just using Automapper “IMapper” interface method “Map”.
Add a second folder to the AppServices project named Messages; this folder will contain all the request-reply objects used to communicate with the service layer as we are using here Messaging patterns. Because all the replies shared a common set of properties, you can create a base class. Add a new class to the Messages folder named ResponseBase, with the following code
The Success property indicates whether the method called was run successfully, and the Message property contains details of the outcome of the method run.
You now need to implement all the request and reply objects; create a new class for each of the class listings displayed next:
With all the messaging objects in place, you can add the service class that coordinates the method calls to the domain entities: service and repository. Add a new class named ApplicationBankAccountService at the root of the AppService project:
The BankAccountApplicationService class coordinates the application activity and delegates all business tasks to the domain model. This layer does not contain business logic and helps to prevent any non-business-related code from polluting the domain model project. The layer also transforms
domain entities into data transfer objects that protect the inner workings of the domain and provide an easy API for the presentation layer to work with.
Now it’s time to finish the web client side project to comple our sample application, so open the startup.cs and inside ConfigureServices method, add the following line of code just after “services.AddTransient();” statement to registre “BanKAccountService” and “ApplicationBankAccountService” to asp.net core dependecy injection so that they can be dynamically resolved
Also modify your HomeController class in the controller folder from the web project so that is looking like the code bellow:
Modify the razor index page inside View/Home folder so that it’s contained the following code:
you should also add others .cshtlm razor page as in the image bellow, so that you will be able to simulate operation on bank account (I will left it as an exercise to implement this operation because we have already setup all buisness logic in the AppService project)
You can now run the applicationand you will see this image:
In this sample, you can create and edit a Bank Account, you can implement the rest of fonctionalities by calling the right buisness logic from AppService into the right action method and use razor do build the UI as you need. This was just to demonstrate a simple way to organize or application by following DDD methodology.