Archive

Posts Tagged ‘maintainable code’

Bringing Plausible Deniability to Development: the Strategy Pattern

July 30, 2009 3 comments

July 30th 2009 | David Cooksey

Bringing Plausible Deniability to Development: the Strategy Pattern

If the template pattern is a benevolent dictator the strategy pattern is a politician concerned with plausible deniability: Don’t tell me the details, just do it. The strategy is defined solely in terms of its inputs and outputs.

Let’s say you are writing a program that cuts checks for employees. The code that handles the physical printing of the checks is complete, all that remains is determining how much to print on the check for each person. The company contains both salaried and hourly employees in addition to salesmen whose pay is based on commissions. Also, the company sends out holiday checks to all employees at various times of the year based on how the company performed recently.

You want to be flexible, so your payment generator is designed as a windows service that polls a PaymentRequest table periodically. It then examines the type of payment to determine how the amount should be calculated. The next step is to write and organize implementations of the different ways to calculate payments.

The design should be flexible enough that it makes adding new payment types as simple as possible, while also providing as much flexibility as possible with respect to implementation details. You don’t want to mandate that a particular step in calculation occur, because you don’t know what future payment types might require.

This is where the strategy pattern comes into play. You can use a simple interface that defines your payment strategy to streamline your code and cut down on the number of decision points. All you really need is a block of code that looks at the payment record and decides what strategy to use. The other code should be the same regardless of the payment type. Here is some pseudo code for what this would look like:

public interface IPaymentStrategy
  {
    double CalculateAmount(IPaymentRequest paymentRequest);
  }

public class PaymentGenerator
  {
    public void LookForPaymentRequests()
    {
      IPaymentRequest[] paymentRequests= GetNewPaymentRequests();
      foreach (IPaymentRequest paymentRequest in paymentRequests)
      {
        Process(paymentRequest);
      }
    }

    private void Process(IPaymentRequest request)
    {
      IPaymentStrategy strategy;
      switch (request.PaymentType)
      {
        case 1:
          strategy = new HourlyPayment();
          break;
        case 2:
          strategy = new SalariedPayment();
          break;
        case 3:
          strategy = new CommissionPayment();
          break;
        case 4:
          strategy = new HolidayPayment();
          break;
        default:
          strategy = new FlatPayment();
          break;
      }
      double amount = strategy.CalculateAmount(request);
      WriteCheck(amount);
    }
}

IPaymentStrategy defines a simple interface that accepts an IPaymentRequest and returns the amount calculated. The PaymentGenerator pulls in new payment requests from a table. It picks the appropriate payment calculation method based on the payment type Id and uses it to generate the correct payment amount.

If a new payment type is added, it requires no code restructuring other than the creation of a new class that inherits from IPaymentStrategy, a new case block, and a new row in the PaymentType table.

This code structure places no restrictions at all on the implementation details of the individual payment types. If a lot of code is shared among the payment types, inheritance, a common dependency, or any other method can be used to reduce or eliminate code duplication entirely at the discretion of the programmer.

This makes it easier to ignore the gritty details of payment calculation which a more strict pattern such as the Template Pattern would force you to consider.

Flexible

Maintainable

Plausibly Deniable

The Strategy Pattern.

David Cooksey is a Senior .NET Consultant at Thycotic Software, an agile software services and product development company based in Washington DC. Secret Server is our flagship password management software product.

The Template Pattern A Benevolent Dictator

July 22, 2009 1 comment

Ben Yoder the Template Pattern

July 22nd 2009 | Ben Yoder

The Template Pattern: A Benevolent Dictator

The Template Pattern is unique because of the level of control maintained at the top level. An abstract class controls the steps and the possible default implementations of the algorithm, but it’s kind enough to let its subclasses modify the behavior in pre-defined methods.

Similar design patterns, and specifically the Strategy pattern, prescribe the encapsulation of individual algorithms and logic into single classes that can be called independently.

The Template Pattern is useful for avoiding code duplication and keeping code maintainable. When you copy and paste the same—or very similar—logic across code you should encapsulate that code to prevent drift. This is when a benevolent dictator class helps clean up your code.

Drift may occur due to a change in requirements. Imagine you are working on an application that has a requirement to create an audit record whenever a user edits information on a form. During version 1.0, you created an AuditLogger class that simply writes a record to the database.

public class AuditLogger
{
    public void InsertAuditRecord(){...}
}

However, for version 2.0 you have this requirement: whenever a regular user edits information on certain forms, an email should be sent to a system admin. Additionally system admins, due to their higher level of access, require separate security audit records to be created elsewhere. As quick fix, you could add methods called EmailNotification() and InsertAdminAuditRecord() to AuditLogger which can be called from the Save() method on the forms depending on the user type.

But after that’s been wrapped up, requirements change and a new power user type has been added to the system. This user type requires a single audit record, but this time there is no need to send an email notifying administrators. You could create a mess on all your forms by adding methods to AuditLogger and making decisions on the form, or you could encapsulate what differs between the auditing logic per user-type, recognizing that requirements may change again.

In this case, AuditLogger currently looks like:

public class AuditLogger
{
    public void InsertAuditRecord(){...}
    public void InsertAdminAuditRecord(){...}
    public void EmailNotification(){...}
}

In refactoring this to a Template Pattern, you’ll notice that InsertAuditRecord() and InsertAdminAuditRecord() are essentially the same logical step. By default, users should write a standard audit record, but administrators should write a special audit record. So in creating your Template class, you should define just a single virtual InsertAuditRecord() method that inserts a standard record and a virtual Notify() method that sends emails by default.

public abstract class AuditLogger
{
    public void Audit()
    {
        InsertAuditRecord();
        Notify();
    }

    public virtual void InsertAuditRecord()
    {
        Console.WriteLine("Auditing User...");
    }

    public virtual void Notify()
    {
        Console.WriteLine("Emailing Admin...");
    }
}

Next, create concrete implementations to define specific implementations of the methods, where needed. Your standard AuditLogger will simply be a concrete that extends AuditLogger with the default implementations, but your Admin and PowerUser loggers will override separate methods.

public class StandardAuditLogger : AuditLogger
{
}

public class AdminAuditLogger : AuditLogger
{
    public override void InsertAuditRecord()
    {
        Console.WriteLine("Auditing Admin User...");
    }

    public override void Notify()
    {
        return;
    }
}

public class PowerUserAuditLogger : AuditLogger
{
    public override void Notify()
    {
        return;
    }
}

The advantage of this is as requirements change, your specific logic is encapsulated, but you can continue to define default implementations. So if everyone except admins needs to send email notifications, you could pull the Notify() override out of the PowerUserAuditLogger and be done. And if another step was to be added to the audit process, a default method could be defined and called in the template without having to touch anything else.

The Template pattern becomes less useful the more the algorithms diverge. If you find yourself overriding every single method of the abstract Template class and adding in a lot of hook methods to control the flow from the subclasses, then the Template Pattern may not be your best choice. But if it looks like your code could use some iron fisted governing, let the Template call all the shots—and see how much simpler maintenance becomes.

Ben Yoder is a Senior .NET Consultant at Thycotic Software, an agile software consulting and product development company based in Washington DC. Secret Server is our flagship password management software product.