Writing a scalable and maintainable application is not like walking in a park. You need to run that extra mile to make it happen. The foundation architecture and design pattern plays crucial role here. You can run into various issues if your initial foundation is not strong enough. “Fail planning is plan to Fail”. I think this phrase summarises it all. In this blog post I will do a walkthrough of architecting mission critical apps which are life line of the enterprise. So let us get started.
To prove my point I shall not be giving a fictious business case, but this would be some real example. Infact this is the project which I worked upon couple of years back. I was developing an Human Resources Management System. In the payroll module of this system there various earnings given to the employees like Basic Salary,Hra, Dearness Allowance etc. The basic salary was fixed and the HRA was calculated based on Employee Grades (Executive, Manager and Clerks). Below is the table which tells how hra should be calculated.
|Employee Grade||Hra Percentage (Basic Salary)|
In the system there should be a page where Hra should be applied based on the selection of Employee Grade from the dropdown list. See the below screen shot.
I have a disclaimer to be made here. The above screen shot is not from the actual application that I wrote. I developed this page just for this blog post keeping things very simple. I hope the business case is clear in your mind now so now let us get into some coding. I will first show you the anti pattern which most of developers will adopt to get this output and later on I will discuss about how this should be implemented with Separation of Concerns using Logical Layered Architecture.
THE ANTI PATTERN
The quick and dirty way to achieve this would be done in this simple 3 steps
- Drag the GridView control on the form.
- Bind it to some Datasource control like SQLDatasource or ObjectDataSource
- In the RowDataBound of gridview write your business logic to calculate the hra
This would solve the purpose but you will run into problems once the application starts growing. Everything here is tightly coupled. Your core business logic is written in the code behind file. So let us write the code that will differentiate men from boys.
SEPRATION OF CONCERNS WITH LAYERED ARCHITECTURE
The below diagram represents an N layered architecture for mission critical asp.net apps.
Using solution folder feature I have separated my solution to represent each layer. I have also added the unit tests project in the solution. All units tests are done using Mock objects which proves that the most of the code is written using abstraction rather than concretions. I have implemented few design patterns in the model layer which has my business logic encapsulated into it.In the upcoming sections I shall be talking about them.
- STRATEGY PATTERN : This pattern belongs to Behaviour patterns group. It encapsulates the algorithm within it for which the behaviour can be changed at run time. It means here that the strategy interface will encapsulate the behaviour which can be changed by the classes that will implement this interface. So let us look at the code below.
So now IHra interface is ready let us look at the classes which implements this interface.
The above code is of ExecutiveHraStrategy class which implements the IHra interface. As you can see the entire business logic of calculating the hra is encapsulated. In the same manner I have implemented the Manager and Clerk Hra in different classes implementing the same interface. This adheres to Single Responsibility principle.
- FACTORY PATTERN : The factory method pattern belongs to creational group. The factory pattern involves a static class with static method which returns the class instance based on the argument specified in the static method. Look at the code below
- DEPENDENCY INJECTION : This design pattern helps in decoupling , this can be achieved if you have code against abstractions rather than the concrete implementations. This injection ensures that all the dependency objects required for the class to function are already in place. There are three ways to do this
- via Constructor
- via Property
- via Method
See the code below how my service class gets all its dependency in the constructor. Notice here that it is based on abstraction (Interface) rather than concrete class. This enable us to do my unit testing based on mock objects. More on this in further section.
As mentioned above in my solution there is a project of Unit Tests. I am a big fan of Test Driven Development. I have used N-Unit framework to accomplish this. Using abstractions enable me to use mock objects. My service class depends on database to get the the data and do the calculations but whereas when I am writing my unit tests I really don’t require to connect to the live database and test my Hra calculation logic. I just need mock data to get this thing done. See the code below.
Let me show you now the test method code which uses this mock object to check the hra calculations.
It really makes lot of sense to spend few hours in planning architecture before starting the project. I hope you must have enjoy reading this post. I would love to hear from you. Download the sample code from here.