Software Design Blog - Null Object Pattern Simple solutions to solve complex problems / http://www.rssboard.org/rss-specification BlogEngine.NET 3.1.1.0 en-US /opml.axd http://www.dotnetblogengine.net/syndication.axd Jay Strydom Software Design Blog 0.000000 0.000000 How to make your application 5x faster with background processing <img src="/pics/banners/5XPerformanceGainBlog.jpg" class="img-responsive" alt="5X Performance Gain"> <br> <p> Processing everything in real-time is easy but often makes an application tightly coupled, prone to failure and difficult to scale. </p> <p> Let’s assume a user just clicked on the purchase button to kick off the following workflow: </p> <ol> <li>Save the order</li> <li>Send a confirmation email (mask the credit card number)</li> <li>Update the user’s loyalty points in an external system</li> </ol> <p> <b>The problem</b> 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? </p> <p> <b>The solution</b> 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.</p> <p> 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. </p> <a href="/Downloads/SmtpQueuePerformanceExample.zip" role="button" class="btn btn-primary btn-sm">Download Source Code</a> <h3>Setup</h3> <p>The following XML document will be used as the purchase order. It is about 512KB to simulate a decent payload.</p> <pre class="brush: xml;"> <!--?xml version="1.0" encoding="utf-8" ?--> <order> <account> <name>Test User</name> <address>123 Abc Road, Sydney, Australia</address> <payment> <type>Visa</type> <cardnumber>4111111111111111</cardnumber> </payment> </account> <catalog> <book id="bk101"> <author>Gambardella, Matthew</author> <title>XML Developer's Guide</title> </book> ... </catalog></order></pre> 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. <pre class="brush: c-sharp;"> 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); } } </pre> The SMTP mailer will be configured to write the mail to disk to simplify the illustration. <pre class="brush: c-sharp;"> 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); } } } } </pre> The MaskedMailerDecorator will be used for masking the credit card details. <pre class="brush: c-sharp;"> 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 =&gt; MaskNumber(match.Value)); } _next.Send(message); } private static string MaskNumber(string value) { return value.Length &lt;= MaskDigits ? new string(MaskCharacter, value.Length) : string.Format("{0}{1}", new string(MaskCharacter, value.Length - MaskDigits), value.Substring(value.Length - MaskDigits, MaskDigits)); } } </pre> <h3>Baseline</h3> <p>Let's establish a performance baseline by running the application with the Null Mailer that doesn't do anything. Refer to the <a href="/post/reject-the-null-checked-object">reject the null checked object</a> post if you are new to the null object pattern.</p> <pre class="brush: c-sharp;"> 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 =&gt; orderProcessor.Process(request)); stopWatch.Stop(); Console.WriteLine("Seconds: {0}", stopWatch.Elapsed.TotalSeconds); Console.ReadLine(); } </pre> <pre>Seconds: 6.3404086 </pre> <h3>Real-Time Processing</h3> Let’s measure the performance when MaskedMailerDecorator and FileSmtpMailer are used. <pre class="brush: c-sharp;"> 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", "p@mail.com", "a@mail.com", "Order"); var maskedMailer = new MaskedMailerDecorator(ccRegEx, fileMailer); var orderProcessor = new PurchaseOrderProcessor(maskedMailer); var stopWatch = Stopwatch.StartNew(); Parallel.For(0, 1000, i =&gt; orderProcessor.Process(request)); stopWatch.Stop(); Console.WriteLine("Seconds: {0}", stopWatch.Elapsed.TotalSeconds); Console.ReadLine(); </pre> <pre>Seconds: 32.0430142 </pre> <div class="alert alert-danger" role="alert"> <b>Outch!</b> The application took 5x longer to process the same number of requests. </div> <h3>Background Processing</h3> <p>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.</p> <pre class="brush: c-sharp;"> public class QueuedMailerDecorator : IMailer { private readonly IMailer _next; private BlockingCollection&lt;string&gt; _messages; public QueuedMailerDecorator(IMailer next) { if (next == null) throw new ArgumentNullException("next"); _next = next; _messages = new BlockingCollection&lt;string&gt;(); Task.Factory.StartNew(() =&gt; { 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 &amp;&amp; !_messages.IsAddingCompleted) { _messages.CompleteAdding(); } GC.SuppressFinalize(this); } } </pre> <p>Here is a diagram that depicts the collection of decorated mailers to intercept the communication between the PurchaseOrderProcessor and the FileSmtpMailer.</p> <p> <img src="/pics/blogs/SmtpMailerDecorator.png" class="img-responsive" alt="SMTP Mailer Decorators"> </p> Let's run the code below to evaluate if the queue made a performance difference. <pre class="brush: c-sharp;"> // Use Unity for doing the wiring var fileMailer = new FileSmtpMailer(@"C:\temp", "p@mail.com", "a@mail.com", "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 =&gt; orderProcessor.Process(request)); stopWatch.Stop(); Console.WriteLine("Seconds: {0}", stopWatch.Elapsed.TotalSeconds); Console.ReadLine(); </pre> <pre>Seconds: 6.3908034 </pre> <div class="alert alert-success" role="alert"> <b>Success!</b> The performance of the file mailer was nearly identical to the results without a mailer. </div> <p><b>The drawback</b> 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.</p> <p>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.</p> <h3>Summary</h3> 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. /post/how-to-make-your-application-5x-faster-with-background-processing jay@webdevelopment.co.nz /post/how-to-make-your-application-5x-faster-with-background-processing#comment /post.aspx?id=3232dd7f-e387-4eb3-b989-9b96d75a4419 Tue, 15 Dec 2015 07:41:00 +1300 Design Patterns Decorator Pattern Null Object Pattern Software Design Queues Decorator Design Pattern Design Patterns C# .NET Jay Strydom /pingback.axd /post.aspx?id=3232dd7f-e387-4eb3-b989-9b96d75a4419 0 /trackback.axd?id=3232dd7f-e387-4eb3-b989-9b96d75a4419 /post/how-to-make-your-application-5x-faster-with-background-processing#comment /syndication.axd?post=3232dd7f-e387-4eb3-b989-9b96d75a4419 Null Check Performance Improvement and Failure Reduction <p> Calling optional dependencies such as logging, tracing and notifications should be fast and reliable. </p> <p>The Null Object pattern can be used for reducing code complexity by managing optional dependencies with default behaviour as discussed in the <a href="/post/reject-the-null-checked-object">Reject the Null Checked Object</a> post.</p> <p>This post aims to illustrate the problem with the Null Object pattern and how to resolve it using a simple lambda expression.</p> <p><b>The problem</b> is that the null check pattern can potentially lead to performance degradation and unnecessary failure.</p> <p><b>The solution</b> is to avoid executing unnecessary operations especially for default behaviour.</p> <a href="/Downloads/BlockingNullObjectChecker.zip" role="button" class="btn btn-primary btn-sm">Download Source Code</a> <h3>Setup</h3> <p>The intent of the sample application is to read and parse XML documents for a book store. The document reader is responsible for logging the book titles using the code below.</p> <pre class="brush: c-sharp;"> public interface ILogger { void Log(string message); } public class ConsoleLogger : ILogger { public void Log(string message) { Console.WriteLine(message); } } public class DocumentReader { private readonly ILogger _logger; public DocumentReader(ILogger logger) { if (logger == null) throw new ArgumentNullException("logger"); _logger = logger; } public void Read(XmlDocument document) { if (document == null) throw new ArgumentNullException("document"); var books = document.SelectNodes("catalog/book"); if (books == null) throw new XmlException("Catalog/book missing."); _logger.Log(string.Format("Titles: {0}.", string.Join(", ", GetBookTitles(document)))); // Implementation } private static IEnumerable&lt;string&gt; GetBookTitles(XmlNode document) { Console.WriteLine("Retrieving the book titles"); var titlesNodes = document.SelectNodes("catalog/book/title"); if (titlesNodes == null) yield break; foreach (XmlElement title in titlesNodes) { yield return title.InnerText; } } } </pre> <div class="alert alert-info" role="alert"> <b>Note:</b> The GetBookTitles method adheres to the null check pattern. When the titlesNode is null on line 40, an empty IEnumerable will be returned instead of a null. This means that clients don’t have to check for a null and it reduces the likelihood of potential null reference exceptions. </div> <h3>Problem</h3> <p>Here is an example that illustrates the execution of the application.</p> <pre class="brush: c-sharp;"> static void Main(string[] args) { var document = new XmlDocument(); document.LoadXml(@"&lt;catalog&gt; &lt;book&gt;&lt;title&gt;Developer's Guide&lt;/title&gt;&lt;/book&gt; &lt;book&gt;&lt;title&gt;Tester's Guide&lt;/title&gt;&lt;/book&gt; &lt;/catalog&gt;"); var logger = new ConsoleLogger(); var docReader = new DocumentReader(logger); docReader.Read(document); Console.ReadLine(); } </pre> <pre>Retrieving the book titles Book titles: Developer's Guide, Tester's Guide. </pre> The solution works well when an actual logger is used but what happens if we replace the logger with the NullLogger as shown below? <pre class="brush: c-sharp;"> public class NullLogger : ILogger { public void Log(string message) { // Purposefully provides no behaviour } } var logger = new NullLogger(); var docReader = new DocumentReader(logger); docReader.Read(document); Console.ReadLine(); </pre> <pre>Retrieving the book titles </pre> <div class="alert alert-danger" role="alert"> <b>Oops!</b> The application parsed the book titles unnecessarily. What if the application crashed when the GetBookTitles method was called? This means that the application can potentially crash due to logging, which is not a good design. </div> <h3>Solution</h3> <p>Here is an example that illustrates the improved version. The logger was modified to accept two methods. The first method takes a string for simple logging operations and the second method takes a lambda function that will produce a string.</p> <pre class="brush: c-sharp;"> public interface ILogger { void Log(string message); void Log(Func&lt;string&gt; messageFunc); } public class NullLogger : ILogger { public void Log(string message) { // Purposefully provides no behaviour } public void Log(Func&lt;string&gt; messageFunc) { // Purposefully provides no behaviour } } public class ConsoleLogger : ILogger { public void Log(string message) { Console.WriteLine(message); } public void Log(Func&lt;string&gt; messageFunc) { try { Console.WriteLine(messageFunc.Invoke()); } catch (Exception ex) { Console.WriteLine("Failed to log the result. Error: {0}", ex); } } } public class DocumentReader { public void Read(XmlDocument document) { _logger.Log(() =&gt; string.Format("Titles: {0}.", string.Join(", ", GetBookTitles(document)))); ... } } </pre> <div class="alert alert-info" role="alert"> <b>Note:</b> The console logger reliability was improved on line 29 to 36 since exceptions can be caught instead of interrupting the application when a log building operation fails. </div> <p>Running the example using the Console Logger will produce the same result as the original example.</p> <p>Let's run the Null Logger example again.</p> <pre class="brush: c-sharp;"> var logger = new NullLogger(); var docReader = new DocumentReader(logger); docReader.Read(document); Console.ReadLine(); </pre> <div class="alert alert-success" role="alert"> <b>Success!</b> The output is empty since the GetBookTitles method was never called. Therefore, the null logger did not perform unnecessary work. </div> <h3>Summary</h3> <p>The null object checking pattern simplifies solutions by removing the need to check for null. The drawback is the potential risk of impeding performance and causing failure. Passing around lamba expression functions can be a subtle solution to overcome the problem without overcomplicating the code.</p> /post/null-check-performance-improvement-and-failure-reduction jay@webdevelopment.co.nz /post/null-check-performance-improvement-and-failure-reduction#comment /post.aspx?id=5ebbb760-4cca-4d6f-8f00-06ac81d3b0cf Sat, 12 Dec 2015 07:35:00 +1300 Null Object Pattern Software Design C# .NET Null Object Performance Reliability Jay Strydom /pingback.axd /post.aspx?id=5ebbb760-4cca-4d6f-8f00-06ac81d3b0cf 0 /trackback.axd?id=5ebbb760-4cca-4d6f-8f00-06ac81d3b0cf /post/null-check-performance-improvement-and-failure-reduction#comment /syndication.axd?post=5ebbb760-4cca-4d6f-8f00-06ac81d3b0cf Reject the Null Checked Object <p> 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. </p> <p><b>The problem</b> 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 (<i>Object reference not set to an instance of an object</i>).</p> <p><b>The solution</b> is to return a null object that exhibits default behaviour. This is called the <i>Null Object</i> design pattern.</p><p> <a href="/Downloads/NullObjectPattern.zip" role="button" class="btn btn-primary btn-sm">Download Source Code</a> </p><h3>Example 1: Debug Mode</h3> <p>Here is an example where additional tasks are performed such as logging verbose messages when the application is in debug mode.</p> <p>The cyclomatic complexity of the application has increased due to the number checks as shown below.</p> <h4>Null Checking</h4> <pre class="brush: c-sharp;"> if (isDebugMode) { logger.Log("Saving - Step 1"); } // Save Step 1 if (isDebugMode) { logger.Log("Saving - Step 2"); } // Save Step 2 </pre> 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. <h4>Null Object Design Pattern</h4> <pre class="brush: c-sharp;"> 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 </pre> <h3>Example 2: Registration System</h3> <p>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.</p> <p>The following interfaces will be used in the illustration.</p> <pre class="brush: c-sharp;"> public interface INotification&lt;in T&gt; { void Notifiy(T message); } public interface IReservationRepository { void Save(Confirmation request); IEnumerable&lt;Reservation&gt; GetReservations(); } </pre> <h4>Null Checking</h4> <p>Here is the complicated example that performs null checks.</p> <pre class="brush: c-sharp;"> public class ReservationServiceV1 : IReservationService { private readonly IReservationRepository _repository; private readonly INotification&lt;Confirmation&gt; _notifier; public ReservationServiceV1(IReservationRepository repository, INotification&lt;Confirmation&gt; 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&lt;Reservation&gt; GetReservations(bool confirmed) { var reservations = _repository.GetReservations(); return reservations == null ? null : reservations.Where(reservation =&gt; reservation.Confirmed == confirmed); } } </pre> <h4>Null Object Design Pattern</h4> <p>Here is the simplified version that works with default behaviour.</p> <pre class="brush: c-sharp;"> public class NullNotification&lt;T&gt; : INotification&lt;T&gt; { public void Notifiy(T message) { // Purposefully provides no behaviour } } public class ReservationServiceV2 : IReservationService { private readonly IReservationRepository _repository; private readonly INotification&lt;Confirmation&gt; _notifier; public ReservationServiceV2(IReservationRepository repository, INotification&lt;Confirmation&gt; 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&lt;Reservation&gt; GetReservations(bool confirmed) { return _repository.GetReservations() .Where(reservation =&gt; reservation.Confirmed == confirmed); } } </pre> <h3>Summary</h3> <p>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.</p> /post/reject-the-null-checked-object jay@webdevelopment.co.nz /post/reject-the-null-checked-object#comment /post.aspx?id=19939cbf-062a-4693-8b19-e9904db5feb1 Wed, 09 Dec 2015 20:53:00 +1300 Design Patterns Null Object Pattern Software Design C# Null Object Design Patterns Jay Strydom /pingback.axd /post.aspx?id=19939cbf-062a-4693-8b19-e9904db5feb1 0 /trackback.axd?id=19939cbf-062a-4693-8b19-e9904db5feb1 /post/reject-the-null-checked-object#comment /syndication.axd?post=19939cbf-062a-4693-8b19-e9904db5feb1