Home > .Net Technologies, Architecture, ASP.Net, C#/VB.Net, CodeProject, Dot Net Tips > Designing Business Logic Layer: Some Guidelines

Designing Business Logic Layer: Some Guidelines

Business Logic Layer is a very crucial layer for any data base applications. A timely thought when applied to this layer from the beginning of application layers design can save lots of time and complexity. Software architects divide the software into modules, then different layers, and core functioning layers for important application features. But when actual development work starts, complexity of different layers and modules start crawling into code gradually.
Reason being:
• We try to mix business rules of different modules wishfully
• Writing methods with abundant codes
• Not clearly separating responsibilities of presentation and data access layers
• Creating code duplicity, i.e.; writing same set of code or methods at various places

Results are:
• Difficult to debug
• Difficult to understand the flow
• Difficult to maintain and modify business rules correctly when such rules exist across layers and modules
• Difficult to write Unit Tests

We can avoid these things if we take care of these things when writing codes.
• Write methods that do single meaningful task with one call. Do not mix other code logic with the methods. For example, if we write SavePayment() method, then this method should only focus on save task, and not update or delete or check connection status or read Xml files, etc. This is what we call Single Responsibility Principle.
• Encourage use of factory methods for object creation instead of writing lots of If-else constructs based upon some input type values.
• When you need data or result sets (DTO) of other modules, then preferably call business logic layer methods of that module instead of writing that module code logic into yours. This is quite important aspect for any business logic layer.
• Classes in this layer should be loosely coupled. For this different injection patterns like dependency injection or inversion of control, etc can help. Sometimes even a simple Enum type can come to a great rescue.
• Write business methods that accept valid entity class object or DTO object in business rather than single valued parameters like integer or string or array or even optional params. This ensures business logic layer code function even unmodified when there are database table and entity or DTO class changes in behind.
• Avoid lots of business rules in stored procedures or even in presentation UI.
• Business logic layer methods should not be aware of presentation UI controls’ properties or values. These methods should accept values in integer or string instead.

Let me explain all these points by one example. I worked in an accounting module of a project where customers can make payments of their bills in various ways. They can make either full payment or in-partial or even in installments. For each payment mode, there were different rules and validations. So this module had clear separation of implementation with rules of each mode functioning without depending upon others. This way our lots of coding and debugging time got saved.
Let’s see the code snippets.

Enum showing different Payment Mode

public enum PaymentMode

{
Normal,
Part,
Installment
}

Custome Bill DTO

public class CustomerBillDTO

{
private Int64 intBillNo;
private Int16 intBillMonth;
private Int16 intBillYear;
private double dblBillAmount;
private string strCustomerID;
private Int64 intPayAmount;
//And many other fields…
}

Payment Processor factory class

interface IPaymentProcessorFactory
{
//
IPaymentProcessor GetPaymentProcessor(PaymentMode mode);
}

public class PaymentProcessorFactory : IPaymentProcessorFactory
{
//
private IPaymentProcessor objPaymentProcessor = null;

public IPaymentProcessor GetPaymentProcessor(PaymentMode mode)
{
//
switch (mode)
{
case PaymentMode.Normal:
objPaymentProcessor = new NormalPaymentProcessor();
break;

case PaymentMode.Part:
objPaymentProcessor = new PartPaymentProcessor();
break;
case PaymentMode.Installment:
objPaymentProcessor = new InstallmentPaymentProcessor();
break;
}
return objPaymentProcessor;
}
}

Different Payment Processor class

public interface IPaymentProcessor

{
//
bool SavePayment(CustomerBillDTO Bill);
}

public class NormalPaymentProcessor:IPaymentProcessor
{
//
public bool SavePayment(CustomerBillDTO Bill)
{
return true;
}
}

public class PartPaymentProcessor : IPaymentProcessor
{
//
public bool SavePayment(CustomerBillDTO Bill)
{
return true;
}
}

public class InstallmentPaymentProcessor : IPaymentProcessor
{
//
public bool SavePayment(CustomerBillDTO Bill)
{
return true;
}
}

Main class that processes each payment

class PaymentProcess

{
private IPaymentProcessorFactory objProcessor = null;
public PaymentProcess(IPaymentProcessorFactory Processor)
{
//
this.objProcessor = Processor;
}

public bool ProcessPayment(CustomerBillDTO Bill, PaymentMode mode)
{
//
IPaymentProcessor objPaymentProcessor = this.objProcessor.GetPaymentProcessor(mode);
return objPaymentProcessor.SavePayment(Bill);
}
}

At the calling end, we simply make a generous call as:

private void BtnSave_Click(object sender, EventArgs e)
{
//
PaymentProcessorFactory objFactory = new PaymentProcessorFactory();
PaymentProcess objProcess = new PaymentProcess(objFactory);
bool result = objProcess.ProcessPayment(objCustomerBillDTO(), PaymentMode.Normal);
}

As we see this is how we have clearly separated each logical functioning of a SavePayment() method.
Even in future, if Part or Installment payment mode is stopped, we do not have to modify the code logic to add any If-else construct to branch out or skip any code flows. In case a new payment mode is added, then writing a new XModePaymenetProcessor class, adding one more Enum value and finally one more object instantiation code in factory class will do enough.

Adding or removing any Bill or Customer related fields in CustomerBillDTO do not even pose threat to this business logic layer.

Finally, one should always keep in mind that you write class and class methods for others. So you should be very clear here: what the class should offer and how.

Thanks.

About these ads
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: