Software Design Blog

Simple solutions to solve complex problems

A step-by-step guide to detect errors and retry operations


We are liable for the reliability of our apps, which work when tested but fail in production environments due to unexpected temporary conditions. Errors can occur due to an intermittent service, infrastructure fault, network issue or explicit throttling. If the operation is retried a short time later (maybe a few milliseconds later) the operation may succeed.

A lazy brain can quickly solve this problem without a lot of planning, flexibility or configuration in mind as shown in this MSDN sample that performs a retry when the SMTP mail client fails.

  
            try
            {
                client.Send(message);
            }
            catch (SmtpFailedRecipientsException ex)
            {
                for (int i = 0; i < ex.InnerExceptions.Length; i++)
                {
                    SmtpStatusCode status = ex.InnerExceptions[i].StatusCode;
                    if (status == SmtpStatusCode.MailboxBusy ||
                        status == SmtpStatusCode.MailboxUnavailable)
                    {
                        System.Threading.Thread.Sleep(5000);
                        client.Send(message);
                    }
                }
            }

The problem is how do you retry a failed operation correctly?

The solution is to create an error detection strategy to determine if the error can be retried and use a retry policy to define the number of retries and frequency between retries.

This post extends the previous example by adding retry logic to the SMTP Mail Client. The aim is to illustrate how to improve the reliability of an app by making it more robust.

Download Source Code

Retry Solution - Done Properly

Let’s get started by implementing clean retry code in 4 easy steps.

Step 1 – Add the transient fault handling NuGet package

The Microsoft transient fault handling NuGet package contains generic, reusable and testable components that we will use for solving the SMTP mail client retry problem.

Add the EnterpriseLibrary.TransientFaultHandling NuGet package to the Orders.Implementation project.

Step 2 – Create a transient error detection strategy

Transient (temporarily) faults are errors that can be retried. Here are a few examples of transient errors that may work if retried:

  • The host is not responding or is unavailable
  • The server is busy or the connection was dropped

Here are a few examples of permanent errors that won’t work even if retried:

  • Authentication failed (invalid username or password)
  • Bad request (invalid email address, attachment not found)

Let’s create a detection strategy that will detect SMTP Mail errors that can be retried.

  
    public class SmtpMailErrorDetectionStrategy : ITransientErrorDetectionStrategy
    {
        public bool IsTransient(Exception ex)
        {
            var smtpFailedException = ex as SmtpFailedRecipientsException;
            if (smtpFailedException == null) return false;

            return smtpFailedException.InnerExceptions
                    .Any(mailEx => mailEx.StatusCode == SmtpStatusCode.MailboxBusy ||
                                   mailEx.StatusCode == SmtpStatusCode.MailboxUnavailable);
        }
    }
Step 3 – Create the SMTP Retry Decorator

Based on to the single responsibility principle (SRP), the mail client should only be responsible for one thing, which is sending mail. Adding error detection and retry logic violates the SRP since it shouldn't be it's problem.

The decorator pattern is great for extending an existing class. Just imagine how large the class will become if we continually add cross-cutting functionality to it such as retries, logging and performance monitoring.

Here is the existing SMTP mail client used in the previous post:


We are going to decorate the SMTP mail client with a retry mail client decorator as shown below:

  
    public class SmtpMailClientRetryDecorator : IMailClient
    {
        private readonly IMailClient _next;
        private readonly RetryPolicy _retryPolicy;

        public SmtpMailClientRetryDecorator(IMailClient next, RetryPolicy retryPolicy)
        {
            if (next == null) throw new ArgumentNullException("next");
            if (retryPolicy == null) throw new ArgumentNullException("retryPolicy");
            _next = next;
            _retryPolicy = retryPolicy;
        }

        public void Send(string to, string subject, string body)
        {
            _retryPolicy.ExecuteAction(() => _next.Send(to, subject, body));
        }
    }
Step 4 – Compose the Solution

The transient fault handling library provides the following retry strategies:

Retry strategy

Example (intervals between retries in seconds)

Fixed interval

2,2,2,2,2,2

Incremental intervals

2,4,6,8,10,12

Random exponential back-off intervals

2, 3.755, 9.176, 14.306, 31.895

Let’s register the fixed interval retry strategy in the Unity IoC container as shown below. If you are new to Dependency Injection (DI), read this post.

  
            // This should be defined in app settings
            const int maxRetries = 5;
            var retryInterval = TimeSpan.FromSeconds(2);

            _container.RegisterType<FixedInterval>(
                        new InjectionConstructor(maxRetries, retryInterval));
            _container.RegisterType<RetryPolicy<SmtpMailErrorDetectionStrategy>>(
                        new InjectionConstructor(new ResolvedParameter<FixedInterval>()));
            
            _container.RegisterType<IMailClient, SmtpMailClient>(typeof(SmtpMailClient).FullName);
            _container.RegisterType<IMailClient, SmtpMailClientRetryDecorator>(
                        new InjectionConstructor(
                               new ResolvedParameter<IMailClient>(typeof(SmtpMailClient).FullName),

And for those who may think this is over-engineered and too complicated then this is how you can construct the retry policy in the SMTP mailer class – but of course you will run in to the problems discussed in earlier posts!

  
const int maxRetries = 5;
var retryInterval = TimeSpan.FromSeconds(2);
var policy = new RetryPolicy<SmtpMailErrorDetectionStrategy>(
                    new FixedInterval(maxRetries, retryInterval));
policy.ExecuteAction(() => client.Send(mesage));

Summary

This post showed how to implement a flexible, configurable solution using the Microsoft Transient Fault Handling Application Block to retry transient failures in order to improve app reliability.

If we refer to the original MSDN code sample, we can see a similar pattern by evaluating specific transient error codes (transient error detection strategy), pausing for 5 seconds (retry policy - retry Interval) and retrying the send operation once (retry policy - retry count).

Kill the switch with the strategy pattern

Chain of Responsibility

The previous post described the challenge of validating credit card numbers based on the credit card type such as visa or master card. Many if conditional checks were performed which was improved using the switch statement.

Why was the switch statement bad?

Let's say you have 5 cases and 10 lines each.

  • What if we had to add, remove or modify a case? The class has 7 reasons to change, which violates the open/close principle.
  • At least 5 tests are required to test each case. The class does 5 things, so it violates the single responsibility principle.
  • The class is at least 50 lines long without the possibility of reusing anything.

This post will provide an illustration of using the strategy design pattern with table control flow to replace the switch statement.

The problem is how we can define a family of algorithms (credit card validators), encapsulate each one, and make them interchangeable?

The solution is to use the strategy design pattern that allows the algorithm to vary independently from clients that use it.

Download Source Code

Setup

The following classes from the previous post will be reused.
  
    public class CreditCard
    {
        public string Type { get; set; }
        public string Name { get; set; }
        public string Number { get; set; }
        public string Expiry { get; set; }
    }

    public interface ICreditCardValidator
    {
        void Validate(CreditCard creditCard);
    }

Strategy Pattern

Let's get started with the strategy pattern in 5 easy steps.

1. Specify the signature for the algorithm in an interface

We need to validate a credit card number so we need a method that takes a number as shown below.

  
    public interface ICreditCardNumberValidator
    {
        void Validate(string number);
    }
2. Bury the algorithm implementation details in derived classes

Each credit card validator implementation can be different. In this example, all credit card validators will use a regular expression so we only need one class.

  
    public class RegExCreditCardNumberValidator : ICreditCardNumberValidator
    {
        private readonly Regex _regex;

        public RegExCreditCardNumberValidator(Regex regex)
        {
            if (regex == null) throw new ArgumentNullException("regex");
            _regex = regex;
        }

        public void Validate(string number)
        {
            if (!_regex.IsMatch(number)) throw new InvalidCreditCardException();
        }
    }

A new instance of the class will be created for each credit card type. For example:

  
  var visaRegEx = new Regex("^4[0-9]{6,}$", RegexOptions.Compiled);
  var visaValidator = new RegExCreditCardNumberValidator(visaRegEx);
3. Identify an algorithm that the client would prefer to access

The credit card validation algorithm is based on the credit card type. The credit card type is supplied in the credit card model/DTO. Therefore, we can perform an algorithm lookup based on the credit card type.

A dictionary is great way to perform a lookup, where the key represents the credit card type and the value represents the validator.

  
  var strategies = new Dictionary<string, ICreditCardNumberValidator>
                         (StringComparer.OrdinalIgnoreCase);

The strategy validator is shown below.

  
    public class CreditCardValidatorStrategy : ICreditCardValidator
    {
        private readonly IDictionary<string, ICreditCardNumberValidator> _strategies;

        public CreditCardValidatorStrategy(
                        IDictionary<string, ICreditCardNumberValidator> strategies)
        {
            if (strategies == null) throw new ArgumentNullException("strategies");
            _strategies = strategies;
        }

        public void Validate(CreditCard creditCard)
        {
            if (creditCard == null) throw new ArgumentNullException("creditCard");
            if (string.IsNullOrWhiteSpace(creditCard.Type)) 
               throw new ArgumentException(Resource.MissingCreditCardType);
            if (!_strategies.ContainsKey(creditCard.Type)) 
               throw new InvalidCardException(
                   string.Format(Resource.UnsupportedCreditCard, creditCard.Type));
            _strategies[creditCard.Type].Validate(creditCard.Number);
        }
    }
4. Building the table control lookup

We can build the dictionary lookup table based on a repository such as a database or a configuration file.

The credit card types and regular expressions are defined in the App.config as shown below.

 
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="creditcardnumberexpressions" 
             type="System.Configuration.DictionarySectionHandler" />
  </configSections>  
  <creditcardnumberexpressions>
      <add key="visa" value="^4[0-9]{6,}$" />
      <add key="mastercard" value="^5[1-5][0-9]{5,}$" />
  </creditcardnumberexpressions>
</configuration>

We can compose the dictionary of strategies from the App.config as shown below.

  
    public class ConfigDictionaryLoader : ISettingsLoader
    {
        private readonly string _sectionName;

        public ConfigDictionaryLoader(string sectionName)
        {
            if (sectionName == null) throw new ArgumentNullException("sectionName");
            _sectionName = sectionName;
        }

        public IDictionary<string, string> Load()
        {
            var settings = ConfigurationManager.GetSection(_sectionName) as Hashtable;
            if (settings == null) {
               throw new Exception(string.Format(Resource.MissingConfig, _sectionName));
            }
            return settings.Cast<DictionaryEntry>()
                           .ToDictionary(n => n.Key.ToString(), n => n.Value.ToString());
        } 
    }

    public class CreditCardValidatorFactory : ICreditCardValidatorFactory
    {
        private readonly ISettingsLoader _loader;

        public CreditCardValidatorFactory(ISettingsLoader loader)
        {
            if (loader == null) throw new ArgumentNullException("loader");
            _loader = loader;
        }

        public IDictionary<string, ICreditCardNumberValidator> CreateStrategies()
        {
            var cardPairs = _loader.Load();
            var strategies = new Dictionary<string, ICreditCardNumberValidator>
                                   (StringComparer.OrdinalIgnoreCase);
            foreach (var pair in cardPairs)
            {
                var regEx = new Regex(pair.Value, RegexOptions.Compiled);
                strategies[pair.Key] = new RegExCreditCardNumberValidator(regEx);
            }
            return strategies;
        }
    }
5. Running the solution
The entire solution is wired up as shown below.
 
            var configLoader = new ConfigDictionaryLoader("creditcardnumberexpressions");
            var creditCardFactory = new CreditCardValidatorFactory(configLoader);
            var strategies = creditCardFactory.CreateStrategies();
            var validator = new CreditCardValidatorStrategy(strategies);
           
            var creditCard = new CreditCard()
            {
                Type = "ViSa",
                Number = "4111111111111111"
            };

            validator.Validate(creditCard);

Summary

The strategy pattern provides a great alternative to the switch statement.

The advantages of the strategy design pattern are:

  • Reduces long lists of conditions such as If and Switch statements
  • Avoids duplicate code
  • Changes in one class does not require changes in other classes
  • The Open-close principle is achieved since the class is open for extension but closed for modification
  • The Single responsibility principle is achieved since the complexity is encapsulated per strategy
  • Unit testing is simplified since each strategy can be tested in isolation

Message Queue Delivery Strategies

Message Queue Delivery Strategies

The previous post focused on MSMQ fundamentals using a pull approach to retrieve messages from a queue.

This post is the start of a series that covers multiple strategies to push queued messages to clients. The intention of the push approach is to keep clients agnostic of being part of a message based architecture.

MSMQ technology is used but it is easy enough to change the implementation to use an alternative queuing solution such as Azure Service Bus.

Download Source Code

Setup

Setting up an MSQM was covered in the MSMQ fundamentals post.

The following code was used for placing 3 unique OrderModel messages in the queue.

  
    [Serializable]
    public class OrderModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    using (var queue = new MessageQueue(@".\Private$\Orders"))
    {
        queue.Formatter = new BinaryMessageFormatter();

        for (var orderId = 1; orderId <= 3; orderId++)
        {
            var order = new OrderModel()
            {
                Id = orderId,
                Name = string.Format("Order {0}", orderId)
            };
            queue.Send(order);
        }
    }

Command Pattern

The problem is how can a message infrastructure issue requests to objects without knowing anything about the operation being requested or the receiver of the request?

The solution is to use the command pattern to decouple senders from receivers. A command decouples the object that invokes the operation from the object that knows how to perform the operation.

The generic command interface is displayed below. The OrderProcessorCommand class implements the command interface to indicate that it can accept OrderModel messages, which it will use to simulate an order being processed.

  
    public interface ICommand<in T>
    {
        void Execute(T message);
    }

    public class OrderProcessorCommand : ICommand<OrderModel>
    {
        private readonly int _id;

        public OrderProcessorCommand(int id)
        {
            _id = id;
        }

        public void Execute(OrderModel message)
        {
            if (message == null) throw new ArgumentNullException("message");
            var start = DateTime.Now;

            // Simulate work being performed
            Thread.Sleep(TimeSpan.FromSeconds(2));

            Console.WriteLine("Processed {0} by worker {1} from {2} to {3}", 
                 message.Name, _id, start.ToString("h:mm:ss"), 
                 DateTime.Now.ToString("h:mm:ss"));
        }
    }
Note that a sleep was added on line 21 to simulate work being performed by the processor.

Queue Monitor

The queue monitor class acts as orchestrator, which is responsible for listening to the queue for incoming messages and calling a command to execute each message.

When the client calls the start method then the workflow outlined below will run consciously until the client calls the stop method:

  1. The BeginReceive method will kick off the queue listing operation.
  2. The OnReceiveComplete event will be raised when a message arrives.
  3. The command will be executed by passing in the message content.
  
    public interface IQueueMonitor : IDisposable
    {
        void Start();
        void Stop();
    }

    public class QueueMonitor<T> : IQueueMonitor
    {
        private readonly MessageQueue _queue;
        private readonly ICommand<T> _command;
        private bool _continue = true;

        public QueueMonitor(MessageQueue queue, ICommand<T> command)
        {
            if (queue == null) throw new ArgumentNullException("queue");
            if (command == null) throw new ArgumentNullException("command");
            _queue = queue;
            _command = command;

            _queue.ReceiveCompleted += OnReceiveCompleted;
        }

        private void OnReceiveCompleted(object sender, 
                             ReceiveCompletedEventArgs receiveCompletedEventArgs)
        {
            var message = _queue.EndReceive(receiveCompletedEventArgs.AsyncResult);
            _command.Execute((T)message.Body);
            if (_continue) _queue.BeginReceive();
        }

        public void Start()
        {
            _continue = true;
            _queue.BeginReceive();
        }

        public void Stop()
        {
            _continue = false;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool isDisposing)
        {
            if (!isDisposing || _queue == null) return;
            _queue.ReceiveCompleted -= OnReceiveCompleted;
            _queue.Dispose();
        }
    }

Single Receiver

Let's see the gears ticking over by processing the messages on the queue.

  
            using (var queue = new MessageQueue(@".\Private$\Orders"))
            {
                var command = new OrderProcessorCommand(1);
                var queueMonitor = new QueueMonitor<OrderModel>(queue, command);
                queueMonitor.Start();
            }
Processed Order 1 by worker 1 from 6:20:11 to 6:20:13
Processed Order 2 by worker 1 from 6:20:13 to 6:20:15
Processed Order 3 by worker 1 from 6:20:15 to 6:20:17 

The output above shows that the single receiver processed the messages in order, one at a time.

The drawback of the single receiver is the finite amount of throughput due to the constraint of processing one message at time.

Summary

This post demonstrated a generic approach to continually monitor a queue for new messages and pushing the message content to a command to execute.

The next post will describe how to broadcast a single message across multiple processors.

How to make your application 5x faster with background processing

5X Performance Gain

Processing everything in real-time is easy but often makes an application tightly coupled, prone to failure and difficult to scale.

Let’s assume a user just clicked on the purchase button to kick off the following workflow:

  1. Save the order
  2. Send a confirmation email (mask the credit card number)
  3. Update the user’s loyalty points in an external system

The problem is that non-critical workloads (step 2 and 3) can negatively impact an application's performance and recoverability. What happens when the mail server is down and the email confirmation fails? How do we monitor failure? Do we roll the transaction back or replay the workflow by taking a checkpoint after each successful step?

The solution is to ensure that application flow isn't impeded by waiting on non-critical workloads to complete. Queue based systems are effective at solving this problem.

This post will use a purchase order application that accepts XML requests. The application will sanitise the credit card details by masking most of the digits before sending the request to a mailbox.

Download Source Code

Setup

The following XML document will be used as the purchase order. It is about 512KB to simulate a decent payload.

  


  
    Test User
    
123 Abc Road, Sydney, Australia
Visa 4111111111111111
Gambardella, Matthew XML Developer's Guide ...
The PurchaseOrderProcessor class was intentionally kept small to focus on solving the main problem, which is to minimise the performance impact of the mailing system.
  
    public interface IMailer
    {
        void Send(string message);
    }

    public class PurchaseOrderProcessor
    {
        private readonly IMailer _mailer;

        public PurchaseOrderProcessor(IMailer mailer)
        {
            if (mailer == null) throw new ArgumentNullException("mailer");
            _mailer = mailer;
        }

        public void Process(string xmlRequest)
        {
            var doc = new XmlDocument();
            doc.LoadXml(xmlRequest);

            // Process the order

            _mailer.Send(xmlRequest);
        }
    }
The SMTP mailer will be configured to write the mail to disk to simplify the illustration.
  
    public class FileSmtpMailer : IMailer
    {
        private readonly string _path;
        private readonly string _from;
        private readonly string _recipients;
        private readonly string _subject;

        public FileSmtpMailer(string path, string from, string recipients, string subject)
        {
            if (path == null) throw new ArgumentNullException("path");
            _path = path;
            _from = @from;
            _recipients = recipients;
            _subject = subject;
        }

        public void Send(string message)
        {
            using (var client = new SmtpClient())
            {
                // This can be configured in the app.config
                client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
                client.PickupDirectoryLocation = _path;

                using (var mailMessage = 
                          new MailMessage(_from, _recipients, _subject, message))
                {
                    client.IsBodyHtml = true;
                    client.Send(mailMessage);    
                }             
            }
        }
    }
The MaskedMailerDecorator will be used for masking the credit card details.
  
    public class MaskedMailerDecorator : IMailer
    {
        private readonly Regex _validationRegex;
        private readonly IMailer _next;
        private const char MaskCharacter = '*';
        private const int MaskDigits = 4;

        public MaskedMailerDecorator(Regex regex, IMailer next)
        {
            if (regex == null) throw new ArgumentNullException("regex");
            if (next == null) throw new ArgumentNullException("next");
            _validationRegex = regex;
            _next = next;
        }

        public void Send(string message)
        {
            if (_validationRegex.IsMatch(message))
            {
                message = _validationRegex.Replace(message, 
                               match => MaskNumber(match.Value));
            }
            _next.Send(message);
        }

        private static string MaskNumber(string value)
        {
            return value.Length <= MaskDigits ?
               new string(MaskCharacter, value.Length) :
               string.Format("{0}{1}", 
                          new string(MaskCharacter, value.Length - MaskDigits),
                          value.Substring(value.Length - MaskDigits, MaskDigits));
        }
    }

Baseline

Let's establish a performance baseline by running the application with the Null Mailer that doesn't do anything. Refer to the reject the null checked object post if you are new to the null object pattern.

  
    public class NullMailer : IMailer
    {
        public void Send(string message)
        {
            // intentionally blank
        }
    }

    static void Main(string[] args)
    {
        var path = Path.Combine(Directory.GetCurrentDirectory(), "PurchaseOrder.xml");
        var request = File.ReadAllText(path); 

        var nullMailer = new NullMailer();
        var orderProcessor = new PurchaseOrderProcessor(nullMailer);

        var stopWatch = Stopwatch.StartNew();
        Parallel.For(0, 1000, i => orderProcessor.Process(request));
        stopWatch.Stop();

        Console.WriteLine("Seconds: {0}", stopWatch.Elapsed.TotalSeconds);
        Console.ReadLine();
    }
Seconds: 6.3404086

Real-Time Processing

Let’s measure the performance when MaskedMailerDecorator and FileSmtpMailer are used.
  
            Directory.CreateDirectory(@"C:\temp");
            var ccRegEx = new Regex(@"(?:\b4[0-9]{12}(?:[0-9]{3})?\b
                                       |\b5[1-5][0-9]{14}\b)", RegexOptions.Compiled);

            var path = Path.Combine(Directory.GetCurrentDirectory(), "PurchaseOrder.xml");
            var request = File.ReadAllText(path);
            
            // Use Unity for doing the wiring          
            var fileMailer = new FileSmtpMailer(@"C:\temp", "[email protected]", "[email protected]", "Order");
            var maskedMailer = new MaskedMailerDecorator(ccRegEx, fileMailer);
            var orderProcessor = new PurchaseOrderProcessor(maskedMailer);

            var stopWatch = Stopwatch.StartNew();
            Parallel.For(0, 1000, i => orderProcessor.Process(request));
            stopWatch.Stop();

            Console.WriteLine("Seconds: {0}", stopWatch.Elapsed.TotalSeconds);
            Console.ReadLine();
Seconds: 32.0430142

Background Processing

Let's extend the solution by adding a memory queue to buffer the results. The queue effectively acts as an outbox for sending mail without overwhelming the mail server with parallel requests.

    public class QueuedMailerDecorator : IMailer
    {
        private readonly IMailer _next;
        private BlockingCollection<string> _messages;

        public QueuedMailerDecorator(IMailer next)
        {
            if (next == null) throw new ArgumentNullException("next");
            _next = next;
            _messages = new BlockingCollection<string>();

            Task.Factory.StartNew(() =>
            {
                try
                {
                    // Block the thread until a message becomes available
                    foreach (var message in _messages.GetConsumingEnumerable())
                    {
                        _next.Send(message);
                    }
                }
                finally
                {
                    _messages.Dispose();
                }
            }, TaskCreationOptions.LongRunning);
        }

        public void Send(string message)
        {
            if (_messages == null || _messages.IsAddingCompleted)
            {
                return;
            }
            try
            {
                _messages.TryAdd(message);
            }
            catch (ObjectDisposedException)
            {
                Trace.WriteLine("Add failed since the queue was disposed.");
            }
        }

        public void Dispose()
        {
            if (_messages != null && !_messages.IsAddingCompleted)
            {
                _messages.CompleteAdding();
            }
            GC.SuppressFinalize(this);
        }
    }

Here is a diagram that depicts the collection of decorated mailers to intercept the communication between the PurchaseOrderProcessor and the FileSmtpMailer.

SMTP Mailer Decorators

Let's run the code below to evaluate if the queue made a performance difference.
             
            // Use Unity for doing the wiring          
            var fileMailer = new FileSmtpMailer(@"C:\temp", "[email protected]", "[email protected]", "Order");
            var maskedMailer = new MaskedMailerDecorator(creditCardRegEx, fileMailer);
            var queuedMailer = new QueuedMailerDecorator(maskedMailer);
            var orderProcessor = new PurchaseOrderProcessor(queuedMailer);

            var stopWatch = Stopwatch.StartNew();
            Parallel.For(0, 1000, i => orderProcessor.Process(request));
            stopWatch.Stop();

            Console.WriteLine("Seconds: {0}", stopWatch.Elapsed.TotalSeconds);
            Console.ReadLine();
Seconds: 6.3908034 

The drawback of the in-memory queue used in this post is that it requires memory to store messages temporarily before it is processed. It is possible to lose messages if the application crashes or stops unexpectedly before all of the requests have been processed.

These issues can be addressed with a locally persisted queue such as MSMQ or a cloud based queue such as Azure Service Bus. Queues provide many benefits that will be covered in the next post.

Summary

This post provided evidence to the performance degradation caused by processing non-critical workloads in real-time. Using queues can be an effective technique to keep an application responsive by buffering and processing tasks in the background.

Reject the Null Checked Object

Software solutions become overcomplicated with dozens of long and ugly checks for null. It is like a pothole and you will eventually fall in when you’re not looking carefully.

The problem is that methods returns null instead of real objects and every client must check for null to avoid the application from blowing up due to a NullReferenceExcetion (Object reference not set to an instance of an object).

The solution is to return a null object that exhibits default behaviour. This is called the Null Object design pattern.

Download Source Code

Example 1: Debug Mode

Here is an example where additional tasks are performed such as logging verbose messages when the application is in debug mode.

The cyclomatic complexity of the application has increased due to the number checks as shown below.

Null Checking

            if (isDebugMode)
            {
                logger.Log("Saving - Step 1");
            }

            // Save Step 1

            if (isDebugMode)
            {
                logger.Log("Saving - Step 2");
            }

            // Save Step 2
The code can be simplified as shown below since the logger is always called. A real logger can be registered whilst in debug mode otherwise a null logger that logs to nowhere will be used by default.

Null Object Design Pattern

            
public class NullLogger : ILogger
{
    public void Log(string message)
    {
        // Purposefully provides no behaviour
    }
}

logger.Log("Saving - Step 1");
// Save Step 1
logger.Log("Saving - Step 2");
// Save Step 2

Example 2: Registration System

The use case is to create a service to confirm reservations and to send optional confirmation notices. The service is also responsible for retrieving reservations that can be filtered based on the confirmation status.

The following interfaces will be used in the illustration.

    public interface INotification<in T>
    {
        void Notifiy(T message);
    }

    public interface IReservationRepository
    {
        void Save(Confirmation request);
        IEnumerable<Reservation> GetReservations();
    }

Null Checking

Here is the complicated example that performs null checks.

    public class ReservationServiceV1 : IReservationService
    {
        private readonly IReservationRepository _repository;
        private readonly INotification<Confirmation> _notifier;

        public ReservationServiceV1(IReservationRepository repository, 
                                    INotification<Confirmation> notifier)
        {
            if (repository == null) throw new ArgumentNullException("repository");
            _repository = repository;
            _notifier = notifier;
        }

        public void Confirm(Confirmation request)
        {
            _repository.Save(request);
            if (_notifier != null) _notifier.Notifiy(request);
        }

        public IEnumerable<Reservation> GetReservations(bool confirmed)
        {
            var reservations = _repository.GetReservations();
            return reservations == null ? null : 
                   reservations.Where(reservation => reservation.Confirmed == confirmed);
        }
    }

Null Object Design Pattern

Here is the simplified version that works with default behaviour.

 
public class NullNotification<T> : INotification<T>
{
    public void Notifiy(T message)
    {
        // Purposefully provides no behaviour
    }
}
   
public class ReservationServiceV2 : IReservationService
{
    private readonly IReservationRepository _repository;
    private readonly INotification<Confirmation> _notifier;

    public ReservationServiceV2(IReservationRepository repository, 
                                INotification<Confirmation> notifier)
    {
        if (repository == null) throw new ArgumentNullException("repository");
        if (notifier == null) throw new ArgumentNullException("notifier");
        _repository = repository;
        _notifier = notifier;
    }

    public void Confirm(Confirmation request)
    {
        _repository.Save(request);
        _notifier.Notifiy(request);
    }

    public IEnumerable<Reservation> GetReservations(bool confirmed)
    {
        return _repository.GetReservations()
                          .Where(reservation => reservation.Confirmed == confirmed);
    }
}

Summary

Avoid returning null and return default behaviour instead; such as an empty list. The Null Object design pattern will simplify code and reduce potential slip-ups causing unexpected failure.

Evolution of the Singleton Design Pattern in C#

This post is focused on the evolutionary process of implementing the singleton design pattern that restricts the instantiation to one object.

We will start with a simple implementation and move onto a thread safe example using locking. A comparison is made using Lazy Initialization and we will complete the post with a loosely coupled singleton solution using Dependency Injection.

Download Source Code

Singleton Components

We will use logging as our singleton use-case. The logging interface and implementation shown below will write to the console when the ConsoleLogger is instantiated.

       
    public interface ILogger
    {
        void Log(string message);
    }

    public class ConsoleLogger : ILogger
    {
        public ConsoleLogger()
        {
            Console.WriteLine("{0} constructed", GetType().Name);
        }

        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

Single Thread Singleton

Below is a simple implementation of a singleton.

    
    public class SingleThreadLogger
    {
         private static ILogger _instance;

         public static ILogger Instance
         {
             get
             {
                 if (_instance == null)
                 { 
                     _instance = new ConsoleLogger();
                 }
                 return _instance;
             }
         }
    }
Calling the singleton in a single thread from the console:
    
    static void Main(string[] args)
    {
         SingleThreadLogger.Instance.Log("Hello World");
         SingleThreadLogger.Instance.Log("Hello World");     
         Console.ReadLine();
    }
  ConsoleLogger constructed
  Hello World
  Hello World
Calling the singleton using multiple threads from the console:
    
    static void Main(string[] args)
    {
         Parallel.Invoke(() => SingleThreadLogger.Instance.Log("Hello World"),
                         () => SingleThreadLogger.Instance.Log("Hello World"));
         Console.ReadLine();
    }
  ConsoleLogger constructed
  Hello World
  ConsoleLogger constructed
  Hello World

Thread Safe Singleton

Below is an example of a poorly implemented locking approach around the constructor of the ConsoleLogger:
    
    public class ThreadLockConstructorLogger
    {
        private static ILogger _instance;

        private static readonly Object _lock = new object();

        public static ILogger Instance
        {
            get
            {
                if (_instance == null)
                {
                     lock (_lock)
                    {
                         // WARNING: Multiple instantiation
                        _instance = new ConsoleLogger();
                    }       
                }
                return _instance;
            }
        }
    }
Calling the singleton using multiple threads from the console:
    
    static void Main(string[] args)
    {
         Parallel.Invoke(() => ThreadLockConstructorLogger.Instance.Log("Hello World"),
                         () => ThreadLockConstructorLogger.Instance.Log("Hello World")); 
         Console.ReadLine();
    }
  ConsoleLogger constructed
  Hello World
  ConsoleLogger constructed
  Hello World

The ThreadLockConstructorLogger class has the classic double-checked locking bug. The first thread acquired the lock and is busy on line 15 while the second thread is waiting for the lock to be released on line 13. Once the second thread acquires the lock, another instance will be created on line 15.

We can solve the problem by implementing the double locking solution as shown below, where we perform another check to verify that the class has not been instantiated once the lock has been acquired.

    
    public class ThreadLockWriteLogger
    {
        private static ILogger _instance;

        private static readonly Object _lock = new object();

        public static ILogger Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new ConsoleLogger();
                        }             
                    }
                }
                return _instance;
            }
        }
    }
Calling the singleton using multiple threads from the console:
    
    static void Main(string[] args)
    {
         Parallel.Invoke(() => ThreadLockWriteLogger.Instance.Log("Hello World"),
                         () => ThreadLockWriteLogger.Instance.Log("Hello World")); 
         Console.ReadLine();
    }
  ConsoleLogger constructed
  Hello World
  Hello World

Lazy Instantiated Singleton

A simplified approach is to use lazy instantiation because by default, Lazy objects are thread-safe as shown below.

    
    public class LazyLogger
    {
        private static readonly Lazy<ILogger> _instance = 
            new Lazy<ILogger>(() => new ConsoleLogger());

        public static ILogger Instance
        {
            get { return _instance.Value; }
        }
    }
Calling the lazy singleton using multiple threads from the console:
    
    static void Main(string[] args)
    {
         Parallel.Invoke(() => LazyLogger.Instance.Log("Hello World"),
                         () => LazyLogger.Instance.Log("Hello World"));
         Console.ReadLine();
    }
  ConsoleLogger constructed
  Hello World
  Hello World

Dependency Injection Singleton

A singleton is considered an anti-pattern due to the following reasons:

  • Hidden dependencies makes it is hard to tell what a class is dependent on when the dependencies are not explicitly defined (ie: the constructor).
  • Tight coupling occurs when singletons are hardcoded into an application as a static method and unnecessary complicates mocking dependencies in automated tests.
  • Single Responsibility Principle is violated since the creation of an object is mixed with the lifecycle management of the application.

Dependency Injection (DI) can remedy the problems above. Let's have a look at the example below that consists of a WriteMessageAction class with a dependency on the ILogger interface.

    
    public interface IAction<in T>
    {
        void Do(T message);
    }

    public class WriteMessageAction : IAction<string>
    {
        private readonly ILogger _logger;

        public WriteMessageAction(ILogger logger)
        {
            if (logger == null) throw new ArgumentNullException("logger");
            _logger = logger;
        }

        public void Do(string message)
        {
            _logger.Log(message);
        }
    }
We can use Unity to manage the lifecycle of the ILogger instance as shown below.
    
static void Main(string[] args)
{
     var container = new UnityContainer();
     container.RegisterType<ILogger, ConsoleLogger>(
                  new ContainerControlledLifetimeManager());
     container.RegisterType<IAction<string>, WriteMessageAction>("One");
     container.RegisterType<IAction<string>, WriteMessageAction>("Two");

     var actions = container.ResolveAll<IAction<string>>();
     actions.ForEach(action => action.Do("Hello World"));

     Console.ReadLine();
}
  ConsoleLogger constructed
  Hello World
  Hello World
The key is on line 4 to 5, since we pass in "new ContainerControlledLifetimeManager()" to register the object as a singleton. By default, unity will create a new instance of an object when we omit the ContainerControlledLifetimeManager constructor parameter as shown below:
    
{
     var container = new UnityContainer();
     container.RegisterType<ILogger, ConsoleLogger>();
     container.RegisterType<IAction<string>, WriteMessageAction>("One");
     container.RegisterType<IAction<string>, WriteMessageAction>("Two");

     var actions = container.ResolveAll<IAction<string>>();
     actions.ForEach(action => action.Do("Hello World"));

     Console.ReadLine();
}
  ConsoleLogger constructed
  ConsoleLogger constructed
  Hello World
  Hello World