Showing posts with label Practices. Show all posts
Showing posts with label Practices. Show all posts

Friday, May 04, 2012

A Study of WinJS Promise

.NET 4.5 introduces a new async/await asynchronous programming pattern. Metro Javascript library WinJS also has a similar asynchronous programming paradigm called Promise. Promise is an Javascript object with a "then" function that takes three parameters: a complete callback function, an optional failure callback function, and an optional on progress callback function. We can do something like:
    function getWebContentPromise(url) {
        WinJS.xhr({ url: url }).then(
            function (result) { // Successfully
                console.log("Get web content successfully. Data length:" + result.responseText.length);
            },
            function (err) { // Failed
                console.log("Get web content failed. Error:" + err);
            },
            function (prog) { // On progress
                console.log("Get web content on progress...");
            });
    }
I tested above script in Visual Studio 11 Beta. WinJS.xhr({ url: url }) returns immediately, and those "then" callback functions are hit later when the response content is ready or error occurs due to network issue. Looks good so far. How can I create my own Promise and asynchronous function? Say I have a simple script as follow:
    function complicatedCalculation(x, y) {
        var result = x + y;
        // fake busy work...
        for (var i = 1; i < 10000000; i++) {
            var dummy = (i * i) / i;
        }
        return result;
    }

    function getResult(x, y) {
        var result = complicatedCalculation(x, y);
        return result;
    }
It's just a heavy function that would block the UI for a while. So how can we convert it to be Promise-able? From MSDN documentation, I found Promise.as and Promise.wrap functions, and both could wrap an object in a Promise object. Unfortunately the documentation is super simple without any sample code or detail explanation, basically just useless. Forgive that since WinJS is still in Beta. Anyway I tried:
    WinJS.Promise.wrap(complicatedCalculation(x, y)).then(...
It works but it's not asynchronous, i.e. WinJS.Promise.wrap(complicatedCalculation(x, y)) doesn't return immediately, instead "then" callback functions are invoked only after the complicatedCalculation function is completed. That's not what we want. So I manually convert above method to the Promise object, whose constructor accepts three parameter, a complete callback function, an optional error callback function, and an optional on-progress callback function:
    function complicatedCalculationPromise(x, y) {
        return new WinJS.Promise(function (completeCallback, errorCallback, progressCallback) {
            try {
                var result = x + y;
                // fake some busy work here...
                for (var i = 1; i < 10000000; i++) {
                    var dummy = parseInt((i * i) / i);
                    if (progressCallback && dummy % 1000000 == 0)
                        progressCallback(dummy);
                }
                completeCallback(result);
            } catch (e) {
                errorCallback(e);
            }
        });
    }

    function getResult(x, y) {
        complicatedCalculationPromise(x, y).then(function (result) {
            return result;
        });
    }
Above code compiles okay and works without any exception. But it's still a synchronous function. The fuction complicatedCalculationPromise blocks the operation until the calculation is completed. I guess it's due to the fact that Javascript is single-threaded. Why WinJS.xhr could be asynchonous? The reason is that inside the xhr function, an XMLHttpRequest is created, a callback for response change event is registered, the request is sent out and then xhr method will return immediately without waiting the response from network. XMLHttpRequest supports asynchronous callback natively. WinJS.xhr is simply a wrapper of XMLHttpRequest and exposes it as a Promise object.

To simulate an asynchronous processing in Javascript, we could modify the script as below:
    function complicatedCalculationAsync(x, y) {
        return new WinJS.Promise(function (completeCallback, errorCallback, progressCallback) {
            var count = 0;
            var result = x + y;
            try {
                setTimeout(function () {
                    count++;
                    if (count == 10000)
                        completeCallback(result);

                    var dummy = parseInt((count * count) / count);
                    if (progressCallback && dummy % 1000 == 0)
                        progressCallback(dummy);

                    setTimeout(arguments.callee, 0);
                }, 0);
            } catch (e) {
                errorCallback(e);
            }
        });
    }
Now the function becomes real asynchronous. But we have to partition the work manually and use setTimeout timer function to hand back control to Javascript execution thread periodically. All those hustles are due to the limitation of single-threaded Javascript model for UI processing. In HTML5 Web Workers allows you to load the Javascript dynamically and run it in background thread, and you can pass result back to the UI thread. I hope that when WinJS.Promise is final released, it could have an option to integrate with Web Workers so asynchronous execution can be run in a separate background thread. That would be a big lift in my opinion.

Wednesday, March 21, 2012

Task-based Asynchronous Programming in .NET 4.5

.NET 4.5 introduces the new "async" and "await" keywords to simplify the asynchronous programming. They are task-based asynchronous model, and are extensively used in the new Metro applications for better responsive UI experience. Following code example illustrate the simple usage of "async" and "await" (run in Visual Studio 11 Beta):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.IO;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder syncContent = new StringBuilder(), asyncContent = new StringBuilder();
            Stopwatch watch = new Stopwatch();
            string testUrl = "http://www.google.com";
            GetWebContent(testUrl); // Warming up network connection

            Console.WriteLine("Sync web request calls start...");
            watch.Start();
            for (int i = 0; i < 100; i++)
            {
                syncContent.Append(GetWebContent(testUrl));
            }
            watch.Stop();
            Console.WriteLine("Sync web calls completed within {0} ms", watch.ElapsedMilliseconds);
            Console.WriteLine("Sync web content lengh: {0}", syncContent.ToString().Length);

            List<Task<string>> tasks = new List<Task<string>>();
            Console.WriteLine("\nSync web request calls start...");
            watch.Restart();
            for (int i = 0; i < 100; i++)
            {
                tasks.Add(GetWebContentAsync(testUrl));
            }
            watch.Stop();

            Console.WriteLine("Async web calls returned within {0} ms", watch.ElapsedMilliseconds);
            watch.Restart();
            Task.WaitAll(tasks.ToArray());
            watch.Stop();
            tasks.ForEach(v => asyncContent.Append(v.Result));
            Console.WriteLine("ASync web calls completed within {0} ms", watch.ElapsedMilliseconds);
            Console.WriteLine("Async web content lengh: {0}", asyncContent.Length);

            Console.Read();
        }

        static async Task<string> GetWebContentAsync(string url)
        {
            var webClient = new WebClient();
            var content = await webClient.DownloadStringTaskAsync(url);
            return content;
        }

        static string GetWebContent(string url)
        {
            var webClient = new WebClient();
            var content = webClient.DownloadString(url);
            return content;
        }
    }
}
The synchronous method is included in the demo cod for comparison purpose. The console app result:



Basically you need to add "async" keyword to the function definition telling compiler they could be asynchronous call(s) inside that method; "async" methods can return Task (no actual return value), Task<T> (return value of T) or void (only used in event handler without any return).

Inside a method marked as "async", you are able to use "await" keyword for a call that promises return or return value. Once "await" keyword is used, compiler will do some magic stuff for you and make that asynchronous invocation happen. Many IO and network related methods in .NET 4.5 have been refactored to support this task-based asynchronous model. Those asynchronous methods, with naming convention of xxxxAsync where xxxx is the method name, are out-of-box and can be used directly with "await" keyword.

This async programming model is much easier to work with comparing to the old .NET asynchronous programming model. In old days, developers need to spend a lot of effort to handle those callback functions such as Beginxxxx/Endxxxx methods and IAsyncResult parameter. That's painful and sometimes it's impossible to do nested async calls and error handling. With the new task-based async model, all those hustles are gone.

You can easily wrap a method as async method using TPL introduced in .NET 4.0. Code snippet below shows one way to achieve this:
        static async Task<double> MyComplicatedHeavyCalculationAsync(double x, double y)
        {
            double value = await Task<double>.Run(() => MyComplicatedHeavyCalculation(x, y));
            return value;
        }

        static double MyComplicatedHeavyCalculation(double x, double y)
        {
            // Do your complicated work ...
            return x + y;
        }
All sound good. But how about the thread context such as updating the UI content? In WPF, Silverlight and Metro apps you are most likely safe to do so since compiler are smart enough to inject the delegate code that could marshall the update back to the UI thread. For ASP.NET things are a bit more tricky. You have thread pool and httpcontext for each request is dynamically generated. Good news is that the new ASP.NET 4.5 will support task-based asynchronous model in certain ways, refer next version ASP.NET white paper for detail.

Thursday, May 19, 2011

ASP.NET MVC Controller Out of Control

MVC pattern and Microsoft ASP.NET MVC implementation are quite popular and successful in recent years for many reasons such as modularity, readability, maintainability, and separation of concerns. However, out-of-box ASP.NET MVC may not fit well in some scenarios. You won't get the goodness of MVC without proper implementation. Recently when I reviewed one of our ASP.NET MVC applications I just found another example of how a pattern could become anti-pattern.

The ASP.NET MVC application is an internal authoring system letting people to manage a bunch of products and their attributes. The products then can be published and exported to a list of XML files that are used by front-end servers to display to public. This application's base domain model was quite simply: a Product has many properties and a Product belongs to one or more Category. The complexity goes to product properties and business logic behind them. That resulted in a huge Product controller in the implementation. The controller class is so big that the developer split it to a couple of partial classes to avoid thousands lines of code in one class file. That doesn't smell good at all.

The Product management UI has a few tabs which group different properties in a logical way. AJAX has been extensively used to populate and update those partial Product properties. Each UI component (partial view) has at least two corresponding controller actions, one for read and one for date. The controller was too complex and was doing too much: input and validation, data manipulation (CRUD), view mapping etc. It looks like going back to the old WebForm model and the controller is just like the code-behind we used to do in traditional ASP.NET.

This sounds like a common problem. Google "ASP.NET MVC big fat controller" there're thousands of results. Many people have been struggling on similar pain. Also many people provided suggestions or solutions to resolve the problem. I found one article with great insight on this topic that posted long time ago right after ASP.NET MVC 1.0 was released.

A handful esteemed people even built a new MVC framework on top of ASP.NET from scratch called FubuMVC when they found ASP.NET MVC had the problem along with other issues. If you want to stick with ASP.NET MVC, there're some good thoughts to slim the controller and make the applicaton more readable, extendable and maintainable:

1. ControllerLess action by one controller one action.
2. Grouping controllers.
3. Use AutoMapper to simplify the property mapping between different models.
4. Move logic and code to service layer as much as possible.
5. Use Command pattern to distribute responsibilities.

The last one Command pattern can be extended to Command Query Responsibility Segregation (CQRS) pattern, referring to this channel-9 video about applying CQRS to ASP.NET MVC 3.

Above ideas can be used together when we are doing ASP.NET MVC application developing or refactoring. It sure takes more effort at the beginning but it would pay off in the long run.

Tuesday, April 26, 2011

Dynamically Invoke Generic Method In .NET


Today I cleaned up a lengthy method in our project which I think it's worthy of a post. Our project has a repository that caches all business objects, we called them entities and the entity list is long. The cache is loaded/refreshed when repository is first accessed or some entities have been changed in the back-end store. The method for loading entities is something like:
void LoadEntitiesCache()
{
    List<EntityType1> entity1List = DataStore.GetAllEntitiesByType<EntityType1>();
    SaveEntitiesToCache(Entity1List);
    List<EntityType2> entity2List = DataStore.GetAllEntitiesByType<EntityType2>();
    SaveEntitiesToCache(Entity2List);
    List<EntityType3> entity3List = DataStore.GetAllEntitiesByType<EntityType3>();
    SaveEntitiesToCache(Entit32List);
    ....
    List<EntityTypeN> entityNList = DataStore.GetAllEntitiesByType<EntityTypeN>();
    SaveEntitiesToCache(EntityNList);
}
The way of my clean-up is something like:
void LoadEntitiesCache()
{
    Type [] allEntityTypes = new Type [] { EntityType1, EntityType2, ..., EntityTypeN };
    foreach(Type entityType in allEntityTypes)
    {
        List<entityType> entityList = DataStore.GetAllEntitiesByType<entityType>();
        SaveEntitiesToCache(entityList);
    }
}
The logic is there but above code won't work because you can't invoke a generic method like that, instead reflection must be used for such usage. Following code example shows how to use reflection to invoke a generic method (entity/cache update logic is not included):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections.ObjectModel;
using System.Collections.Concurrent;

public interface IEntity
{
    string Identifier { get; }
    string Type { get; }
}

public class Book : IEntity
{
    public string ISBN { get; set; }
    public string Category { get; set; }
    public string Identifier { get { return ISBN; } }
    public string Type { get { return Category; } }
}

public class CD : IEntity
{
    public string Name { get; set; }
    public string Category { get; set; }
    public string Identifier { get { return Name; } }
    public string Type { get { return Category; } }
}

public class KeyedEntityCollection<T> : KeyedCollection<string, T> where T : IEntity
{
    protected override string GetKeyForItem(T item)
    {
        return item.Identifier;
    }
}

public class Repository
{
    static ConcurrentDictionary<Type, object> _entitiesCache = new ConcurrentDictionary<Type, object>();

    void LoadEntitiesCache()
    {
        // Load all entities from back-end store and save them in _entitiesCache
        DataSource dataSource = new DataSource();

        Type[] entityTypes = new Type[] { typeof(Book), typeof(CD) };
        MethodInfo methodInfo = typeof(DataSource).GetMethod("GetEntitiesByType");
        foreach (var entityType in entityTypes)
        {
            object _cacheObject = null;
            if (_entitiesCache.TryGetValue(entityType, out _cacheObject) && _cacheObject != null)
                continue;

            try
            {
                // Invoke DataStore.GetEntitiesByType<T>() dynamically
                MethodInfo genericMethod = methodInfo.MakeGenericMethod(entityType);
                IEnumerable dataReturn = genericMethod.Invoke(dataSource, null) as IEnumerable;

                // Create EntityCollection dynamically
                Type[] types = new Type[] { entityType };
                Type entityCollectionType = typeof(KeyedEntityCollection<>);
                Type genericType = entityCollectionType.MakeGenericType(types);
                IList genericCollection = Activator.CreateInstance(genericType) as IList;

                if (dataReturn != null)
                {
                    foreach (var entity in dataReturn)
                    {
                        genericCollection.Add(entity);
                    }
                }
                _entitiesCache.AddOrUpdate(entityType, genericCollection, 
                    (type, existingValue) => { return genericCollection; });
            }
            catch (Exception ex)
            {
                // Log error
                throw;
            }
        }
    }

    public Repository()
    {
        LoadEntitiesCache();
    }

    public KeyedEntityCollection<T> GetEntities<T>() where T : IEntity
    {
        object cachedEntityCollection = null;
        _entitiesCache.TryGetValue(typeof(T), out cachedEntityCollection);
        return cachedEntityCollection as KeyedEntityCollection<T>;
    }

    public T GetEntityById<T>(string identifier) where T : IEntity
    {
        var entityCollection = GetEntities<T>();
        if (entityCollection != null && entityCollection.Contains(identifier))
        {
            return entityCollection[identifier];
        }
        return default(T);
    }
}

internal class DataSource
{
    // Get data from database, or xml files, or whatever data store
    public IEnumerable<T> GetEntitiesByType<T>() where T : IEntity
    {
        // Mock some test data here
        if (typeof(T) == typeof(Book))
        {
            List<Book> bookSource = new List<Book>();
            Enumerable.Range(1, 100).ToList().ForEach(
                i => bookSource.Add(new Book() { ISBN = i.ToString(), Category = "Computer" }));
            return bookSource as IEnumerable<T>;
        }
        else if (typeof(T) == typeof(CD))
        {
            List<CD> cdSource = new List<CD>();
            Enumerable.Range(1, 100).ToList().ForEach(
                i => cdSource.Add(new CD() { Name = i.ToString(), Category = "Music" }));
            return cdSource as IEnumerable<T>;
        }
        else return null;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Repository repo = new Repository(); 
        var books = repo.GetEntities<Book>();           // Get all books
        var secondBook = repo.GetEntityById<Book>("2"); // Get the second book
        var cds = repo.GetEntities<CD>();               // Get all CDs
        var thirdCD = repo.GetEntityById<CD>("3");      // Get the third CD
        Console.Read();
    }
}

Friday, January 28, 2011

Implementing Simple Custom Rules By Code

In my previous two posts Microsoft Workflow Rules Engine was used to execute the business rules. That maybe a bit overkill if there're only a small set of rules to run and the use cases of them are relatively simple. In that case we could implement the rules and control their execution directly. The simple console app below demos the concept of custom rules implementation:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        #region demo domain objects
        public class Product
        {
            public string Name { get; set; }
            public decimal Price { get; set; }
        }

        public class ShoppingCart
        {
            public List<Product> SelectedProducts { get; set; }
            public List<string> CouponCodes { get; set; }
            public decimal TotalAmount { get { return SelectedProducts.Sum(prod => prod.Price); } }
            internal decimal Discount { get; set; }

            public ShoppingCart()
            {
                SelectedProducts = new List<Product>();
                CouponCodes = new List<string>();
                Discount = 0;
            }
        }
        #endregion demo domain objects

        #region promotion objects 
        class CouponPromotion  
        {
            public string Name { get; set; }
            public string PromotionCode { get; set; }
            public decimal Discount { get; set; }
            public DateTime ExpiredOn { get; set; }
        }

        class TotalAmountPromotion // discount if total amount is greater than a number
        {
            public string Name { get; set; }
            public decimal TotalAmount { get; set; }
            public decimal Discount { get; set; }
            public DateTime ExpiredOn { get; set; }
        }
        #endregion promotion object

        #region custom rules interface and implementation
        interface ICustomRule
        {
            void Execute(ShoppingCart cart);
        }

        class CouponPromotionRule : ICustomRule
        {
            private CouponPromotion mCouponPromotion;
            public CouponPromotionRule(CouponPromotion promotion)
            {
                this.mCouponPromotion = promotion;
            }

            public void Execute(ShoppingCart cart)
            {
                if (mCouponPromotion.ExpiredOn >= DateTime.Today && cart.CouponCodes.Contains(mCouponPromotion.PromotionCode))
                {
                    Console.WriteLine(mCouponPromotion.Name + " applied");
                    cart.Discount += mCouponPromotion.Discount;
                }
            }
        }

        class TotalAmountGreaterRule : ICustomRule
        {
            private TotalAmountPromotion mTotalAmountPromotion;
            public TotalAmountGreaterRule(TotalAmountPromotion promotion)
            {
                this.mTotalAmountPromotion = promotion;
            }

            public void Execute(ShoppingCart cart)
            {
                if (mTotalAmountPromotion.ExpiredOn >= DateTime.Today && cart.TotalAmount >= mTotalAmountPromotion.TotalAmount)
                {
                    Console.WriteLine(mTotalAmountPromotion.Name + " applied");
                    cart.Discount += mTotalAmountPromotion.Discount;
                }
            }
        }
        #endregion custom rules interface and implementation

        static void RuleTest(ShoppingCart cart)
        {
            // Mock CouponPromotionRule and TotalAmountRules
            CouponPromotionRule rule1 = new CouponPromotionRule(new CouponPromotion()
            {
                Name = "Coupon Promotion Rule 1",
                PromotionCode = "123456789",
                Discount = 10,
                ExpiredOn = new DateTime(2100, 1, 1)
            });

            CouponPromotionRule rule2 = new CouponPromotionRule(new CouponPromotion()
            {
                Name = "Coupon Promotion Rule 2",
                PromotionCode = "111111111",
                Discount = 20,
                ExpiredOn = new DateTime(2000, 1, 1)
            });
            TotalAmountGreaterRule rule3 = new TotalAmountGreaterRule(new TotalAmountPromotion()
            {
                Name = "Total Amount Rule 1",
                TotalAmount = 1000,
                Discount = 100,
                ExpiredOn = new DateTime(2100, 1, 1)
            });

            ICustomRule[] rules = new ICustomRule[] { rule1, rule2, rule3 };
            foreach (var rule in rules)
            {
                rule.Execute(cart);
            }
        }

        static void Main(string[] args)
        {
            ShoppingCart shoppingCart = new ShoppingCart();
            Enumerable.Range(1, 5).ToList().ForEach(i => shoppingCart.SelectedProducts.Add(
                   new Product() { Name = "Product" + i.ToString(), Price = 100 * i }));
            shoppingCart.CouponCodes.Add("123456789");
            shoppingCart.CouponCodes.Add("111111111");
            Console.Write("\nShopping Cart before rules execution -- ");
            Console.WriteLine("Total : ${0}\tDiscount : ${1}", shoppingCart.TotalAmount, shoppingCart.Discount);

            RuleTest(shoppingCart);

            Console.Write("Shopping Cart after rules execution -- ");
            Console.WriteLine("Total : ${0}\tDiscount : ${1}", shoppingCart.TotalAmount, shoppingCart.Discount);

            Console.Read();
        }      
    }
}

The result of the test app:

Wednesday, January 05, 2011

Good to be Lazy<T>?

Just read Dino Esposito's article Don’t Worry, Be Lazy about the new new Lazy<T> class in .NET Framework 4.0. For short it's a wrapper class to simplify your work for the "lazy loading" approach.

Sometimes we don't want to populate all related data for a complex object at one shot. Ideally, for the performance consideration, we should only retrieve data that are needed. A class is usually abstracted from business model, for instance a Customer object would have properties of ID, Name, Address, Purchased Orders, etc. Populating all these fields could be costly and may require a few expensive calls to backend system. It's possible that only a small portion of an object data is used when requesting a Customer object. Why those purchased orders data are filled when only Customer's name is in interest? Lazy<T> is designed to help for such scenarios: delay loading data until they are actually requested.

Following code example demos such usage. A User class has an Address property, and the Address data are only loaded once when Address property is accessed:

class Program
{
class Address
{
public string Location { get; set; }
public string GeoCode { get; set; }
public Address(string loc, string geo)
{
this.Location = loc;
this.GeoCode = geo;
}
}

class User // User has Address property which is lazily loaded
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public User(string id, string fName, string lName)
{
this.ID = id;
this.FirstName = fName;
this.LastName = lName;
_repoAddress = new Lazy<Address>(GetUserAddress);
}

private Lazy<Address> _repoAddress = null; // Lazy container loaded from repository
private Address _setAddress = null; // Container to setter
public Address Address
{
get
{
if (_setAddress == null) // Only get repository data if not being set
return _repoAddress.Value;
else
return _setAddress;
}
set
{
_setAddress = value;
}
}
private Address GetUserAddress() // Method to load the address data from repository
{
Console.WriteLine("...... Loading address for user {0} ......", this.ID);
return UserService.GetUserAddress(this.ID);
}
}

static List<Lazy<User>> _repoUserList = new List<Lazy<User>>(); // Fake User repository
static List<Lazy<Address>> _repoAddressList = new List<Lazy<Address>>(); // Fake Address repository
static void MockData() // Mock some sample data
{
for (int i = 1; i <= 10; i++)
{
string fakeID = i.ToString();
_repoUserList.Add(new Lazy<User>(() =>
{
Console.WriteLine("... Mocking User {0} ...", fakeID);
return new User(fakeID, "FName" + fakeID, "LName" + fakeID);
}));
_repoAddressList.Add(new Lazy<Address>(() =>
{
Console.WriteLine("... Mocking Address {0}...", fakeID);
return new Address("Location" + fakeID, "GeoCode" + fakeID);
}));
}
}

class UserService // Fake Service
{
public static Address GetUserAddress(string ID)
{
var addr = _repoAddressList.FirstOrDefault(a => a.Value.GeoCode == "GeoCode" + ID);
return (addr == null) ? null : new Address(addr.Value.Location, addr.Value.GeoCode);
}
public static User GetUserByID(string ID)
{
var user = _repoUserList.FirstOrDefault(u => u.Value.ID == ID);
return (user == null) ? null : new User(user.Value.ID, user.Value.FirstName, user.Value.LastName);
}
}

static void Main()
{
MockData();
User user = UserService.GetUserByID("5");
Console.WriteLine("The user's name: {0} {1}", user.FirstName, user.LastName);
Console.WriteLine("The user's address: {0} {1}", user.Address.Location, user.Address.GeoCode);
user.Address = new Address(user.Address.Location + "(new)", user.Address.GeoCode + "(new)");
Console.WriteLine("The user's updated address: {0} {1}", user.Address.Location, user.Address.GeoCode);
Console.Read();
}
}
Result:
... Mocking User 1 ...
... Mocking User 2 ...
... Mocking User 3 ...
... Mocking User 4 ...
... Mocking User 5 ...
The user's name: FName5 LName5
...... Loading address for user 5 ......
... Mocking Address 1 ...
... Mocking Address 2 ...
... Mocking Address 3 ...
... Mocking Address 4 ...
... Mocking Address 5 ...
The user's address: Location5 GeoCode5
The user's updated address: Location5(new) GeoCode5(new)
Above demo code searches a DAO User object from the mock data list, whose Address property is not loaded until its value gets accessed. Notice the private lazy<Address> property is only used in the getter method, and would be overridden by setter value so the custom value can be saved and passed back to service layer for further process.

A LINQ expression can be used to initiate the Lazy<T> as shown in the mock data population. We can see only the first 5 mocked Users were created because the fifth User was returned and the rest 5 mocked Users were not being accessed at all.

The last note is that all Lazy collections in above demo code are not thread-safe. To make Lazy<T> thread-safe, you need to pass a LazyExecutionMode parameter to its constructor, for detail refer to MSDN.

Sunday, December 07, 2008

Design Patterns By Example: Strategy vs Template vs Builder vs Bridge

In this post I will go through a few related design patterns. Unlike many online design pattern tutorials, patterns concept and UML diagrams will not be our focus. Instead I will provide more understandable code examples for the discussion.

Strategy Pattern

Strategy defines an interface common to all supported algorithms or behavior. The implementation of the Strategy is dynamically invoked at run time. Generic list sorting in .NET is a good example of using strategy pattern:

using System;
using System.Collections.Generic;

class test {

    class Person
    {
        public string name { get; set; }
        public int Age { get; set; }
    }

    class PersonSortByAge : IComparer<Person>
    {
        public int Compare(Person p1, Person p2)
        {
            return p1.Age.CompareTo(p2.Age);
        }
    }

    static void Main(string[] args)
    {
        List<Person> people = new List<Person>();
        people.Add(new Person() { name = "Andy Wade", Age = 20 });
        people.Add(new Person() { name = "Cary Lee", Age = 10 });
        people.Add(new Person() { name = "Bob Ford", Age = 30 });

        Console.WriteLine("Original order:");
        people.ForEach(p => Console.WriteLine("Name:" + p.name + " Age:" + p.Age));

        people.Sort((p1, p2) => p1.name.CompareTo(p2.name));
        Console.WriteLine("Sort by name:");
        people.ForEach(p => Console.WriteLine("Name:" + p.name + " Age:" + p.Age));
        //Sort by name:
        //Name:Andy Wade Age:20
        //Name:Bob Ford Age:30
        //Name:Cary Lee Age:10

        people.Sort(new PersonSortByAge());
        Console.WriteLine("Sort by age:");
        people.ForEach(p => Console.WriteLine("Name:" + p.name + " Age:" + p.Age));
        //Sort by age:
        //Name:Cary Lee Age:10
        //Name:Andy Wade Age:20
        //Name:Bob Ford Age:30

        Console.ReadKey();
    }
}

In above example Lambda express and strongly typed IComparer are two different strategy or sorting algorithm, which are used to sort the people list by person's name and age respectively. Following code is another example:

using System;
using System.Collections.Generic;
using System.Linq;

class StrategyPattern
{
    enum Temperature { Cold, Mild, Hot }

    interface IActivity
    {
        string GetActivity(Temperature temperature);
    }

    class DayPlanner
    {
        private Temperature Weather;

        public DayPlanner(Temperature weather)
        {
            this.Weather = weather;
        }

        public void SetPlan(IActivity activity)
        {
            Console.WriteLine("Setting plan for " + activity.GetActivity(Weather));
        }
    }

    class IndoorActivity : IActivity
    {
        public string GetActivity(Temperature temperature)
        {
            return (temperature == Temperature.Cold) ? "Hockey" : "Fitness gym";
        }
    }

    class OutdoorActivity : IActivity
    {
        public string GetActivity(Temperature temperature)
        {
            switch (temperature)
            {
                case Temperature.Cold:
                    return "Ice skating";
                case Temperature.Mild:
                    return "Hiking";
                case Temperature.Hot:
                default:
                    return "Swimmig";
            }
        }
    }

    static void Main(string[] args)
    {
        DayPlanner planner = new DayPlanner(Temperature.Mild);
        
        OutdoorActivity outdoorActivity = new OutdoorActivity();
        planner.SetPlan(outdoorActivity); 
        // print out "Setting plan for Hiking"

        IndoorActivity indoorActivity = new IndoorActivity();
        planner.SetPlan(indoorActivity);  
        // print out "Setting plan for Fitness gym"

        Console.ReadKey();
    }
}

Here the DayPlanner holds a reference of an IActivity instance, an implementation of a strategy. With different strategy assigned, DayPlanner shows different activity. Strategy pattern results in dynamic behavior.

Template Method Pattern

Template method defines a sequence of method calls or some algorithms in base class, and the detail implementation of each method or algorithm is overriden by subclass. One obvious example is the ASP.NET Page life cycle: PreLoad, OnLoad, PreRender, etc. Those events are invoked by base Page class and developers are responsible to fill the detail implementation in code-behind for those events. Following code illustrate how the PersonDayPlanner schedules morning, afternoon and night activities by template method:

using System;
using System.Collections.Generic;

class TemplateMethodPattern
{
    abstract class PersonDayPlanner
    {
        // Template Method defines the skeleton steps
        public void Plan()
        {
            MorningPlan();
            AfternoonPlan();
            NightPlan();
        }

        // Abstract methods implemented by child classes
        public abstract void MorningPlan();
        public abstract void AfternoonPlan();
        public abstract void NightPlan();
    }

    class CollegeStudentSaturday : PersonDayPlanner
    {
        public override void MorningPlan()
        {
            Console.WriteLine("Have a simple breakfast and do cleanup.");
        }

        public override void AfternoonPlan()
        {
            Console.WriteLine("Study for 2 hours then go to gym for exercise.");
        }

        public override void NightPlan()
        {
            Console.WriteLine("Eat out with friends and watch movie after");
        }
    }

    class LittleKidSaturday : PersonDayPlanner
    {
        public override void MorningPlan()
        {
            Console.WriteLine("McDonald's happy meal for breakfast, then play at park.");
        }

        public override void AfternoonPlan()
        {
            Console.WriteLine("Friend's birthday party.");
        }

        public override void NightPlan()
        {
            Console.WriteLine("Play LEGO and watch TV.");
        }
    }

    static void Main(string[] args)
    {
        PersonDayPlanner saturday = new CollegeStudentSaturday();
        saturday.Plan();
        Console.WriteLine();
        //print out a student's plan on Saturday:
        // Have a simple breakfast and do cleanup.
        // Study for 2 hours then go to gym for exercise.
        // Eat out with friends and watch movie after

        saturday = new LittleKidSaturday();
        saturday.Plan();
        //print out a kid's plan on Saturday:
        // McDonald's happy meal for breakfast, then play at park.
        // Friend's birthday party.
        // Play LEGO and watch TV.

        Console.ReadKey();
    }
}

Builder Pattern

The Builder pattern separates the construction logic for an object. This pattern is often used when the construction process of an object is complex. By modifying above DayPlanner code demo we have following builder implementation:

using System;
using System.Collections.Generic;

class BuilderPattern
{
    interface IPersonDayPlan
    {
        void MorningPlan();
        void AfternoonPlan();
        void NightPlan();
    }

    class DayPlanBuilder
    {
        private IPersonDayPlan DayPlan { get; set; }

        public DayPlanBuilder() { } // default constructor

        public DayPlanBuilder(IPersonDayPlan dayPlan)
        {
            this.DayPlan = dayPlan;
        }

        public void SetPersonDayPlan(IPersonDayPlan dayPlan)
        {
            this.DayPlan = dayPlan;
        }

        public void BuildPlan()
        {
            if (this.DayPlan != null)
            {
                this.DayPlan.MorningPlan();
                this.DayPlan.AfternoonPlan();
                this.DayPlan.NightPlan();

                // You can control the steps or add new logic inside the builder
                if (this.DayPlan is CollegeStudentSaturday)
                {
                    Console.WriteLine("Play games no later than 12PM.");
                }
            }
        }
    }

    class CollegeStudentSaturday : IPersonDayPlan
    {
        public void MorningPlan()
        {
            Console.WriteLine("Have a simple breakfast and do cleanup.");
        }

        public void AfternoonPlan()
        {
            Console.WriteLine("Study for 2 hours then go to gym for exercise.");
        }

        public void NightPlan()
        {
            Console.WriteLine("Eat out with friends and watch movie after");
        }
    }

    class LittleKidSaturday : IPersonDayPlan
    {
        public void MorningPlan()
        {
            Console.WriteLine("McDonald's happy meal for breakfast, then play at park.");
        }

        public void AfternoonPlan()
        {
            Console.WriteLine("Friend's birthday party.");
        }

        public void NightPlan()
        {
            Console.WriteLine("Play LEGO and watch TV.");
        }
    }

    static void Main(string[] args)
    {
        DayPlanBuilder planBuilder = new DayPlanBuilder(new LittleKidSaturday());
        planBuilder.BuildPlan();
        //print out:
        // McDonald's happy meal for breakfast, then play at park.
        // Friend's birthday party.
        // Play LEGO and watch TV.

        // changing to student's plan
        planBuilder.SetPersonDayPlan(new CollegeStudentSaturday());
        planBuilder.BuildPlan();
        //print out:
        // Have a simple breakfast and do cleanup.
        // Study for 2 hours then go to gym for exercise.
        // Eat out with friends and watch movie after
        // Play games no later than 12PM.

        Console.ReadKey();
    }
}

The Builder pattern plays a little bit different "director" role compared with the Template method in the build process. In above example BuildPlan method can have different build steps for different IPersonDayPlan types; while the Template method has fixed run steps. Builder is creational pattern and it is mainly used to create complex object. Template method is behavior pattern and it defines skeleton of running procedure.

Bridge Pattern

Both Template method and Builder pattern use inheritance to implement different behaviors or algorithms. The situation would become messy when more and more objects join and play in the hierarchy. In above DayPlanner example, we could have AdultMonday, AdultTuesday...SeniorMonday, SeniorTuesday...etc. of many other combination for sub classes. Bridge pattern resolves the problem by decoupling an abstraction from its implementation so that the two can vary independently. Modify the code example again the Bridge version looks like:

using System;
using System.Collections.Generic;

class BridgePattern
{
    interface IDayPlanner
    {
        string DayOfWeek { get; }
        void Plan(int age, bool inSchool);
    }

    abstract class Person
    {
        public int Age { get; set; }
        protected IDayPlanner DayPlanner { get; set; }

        public void SetDayPlanner(IDayPlanner dayPlanner)
        {
            this.DayPlanner = dayPlanner;
        }

        public abstract void PlanDay();
    }

    class CollegeStudent : Person
    {
        public CollegeStudent(int age)
        {
            base.Age = age;
        }

        public override void PlanDay()
        {
            Console.WriteLine("College student's " + this.DayPlanner.DayOfWeek + " schedule:");
            this.DayPlanner.Plan(this.Age, true);
        }
    }

    class LittleKid : Person
    {
        public LittleKid(int age)
        {
            base.Age = age;
        }

        public override void PlanDay()
        {
            Console.WriteLine("Little kid's " + this.DayPlanner.DayOfWeek + " schedule:");
            this.DayPlanner.Plan(this.Age, false);
        }
    }

    class SaturdayPlanner : IDayPlanner
    {
        public void Plan(int age, bool inSchool)
        {
            if (age < 6)
            {
                Console.WriteLine("Play at park, friend's birthday party, and play LEGO.");
            }
            else if (age > 18 && inSchool)
            {
                Console.WriteLine("Study, gym exercise and social activities.");
            }
            // plan for other cases
        }

        public string DayOfWeek { get { return "Saturday"; } }
    }

    class MondayPlanner : IDayPlanner
    {
        public void Plan(int age, bool inSchool)
        {
            if (age < 6)
            {
                Console.WriteLine("Kindergarten.");
            }
            else if (age > 18 && inSchool)
            {
                Console.WriteLine("Classes, library and lab.");
            }
            // plan for other cases
        }

        public string DayOfWeek { get { return "Monday"; } }
    }

    static void Main(string[] args)
    {
        Person kid = new LittleKid(5);
        kid.SetDayPlanner(new SaturdayPlanner());
        kid.PlanDay();
        //Little kid's Saturday schedule:
        //Play at park, friend's birthday party, and play LEGO.

        Person student = new CollegeStudent(20);
        student.SetDayPlanner(new MondayPlanner());
        student.PlanDay();
        //College student's Monday schedule:
        //Classes, library and lab.

        Console.ReadKey();
    }
}

Now person and weekday are separated, and we don't have to do their combinational sub-classes anymore, known as "prefer composition over inheritance" for such scenario. The Provider model in .NET framework, such as Membership Provider and Session State Provider, is an example of using Bridge pattern.

Last but not least, design patterns are useful to resolve certain problems but they are not a silver bullet. Overusing them could introduce unnecessary complexity and cost. We should't force to use patterns as what I do in this posting. The pattern examples I presented above are just for demonstration purpose and it doesn't mean they are the best practices. In reality we should consider those patterns when having a code smell in our work.

Tuesday, October 21, 2008

Visitor Pattern By Example

Visitor pattern separates some algorightm or computation work to its own class. Being able to "visit" visitable objects, different algorithm implementations can do their work without modification of original objects. Let's say a person has different kind of valuables/assets, and the value calculations could have their own implementation:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        public interface IValuable  // Interface for visitable objects 
        {
            void Value(IValueCalculator calculator);
        }

        public interface IValueCalculator   // Interface for visitor implementation
        {
            decimal GetTotal();
            void Calculate(BankAccount bankAccount);
            void Calculate(Loan load);
        }

        public class NetWorthCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += bankAccount.Balance;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.Amount;
            }
        }

        public class MonthlyIncomeCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += (bankAccount.Balance * bankAccount.InterestRate) / 12;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.MonthlyPayment;
            }
        }

        public class BankAccount : IValuable
        {
            public string Name { get; set; }
            public decimal Balance { get; set; }
            public decimal InterestRate { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Loan : IValuable
        {
            public string Name { get; set; }
            public decimal Amount { get; set; }
            public decimal MonthlyPayment { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Person : IValuable // Composite pattern: Person itself is also IValuable
        {
            public string Name { get; set; }
            public List<IValuable> Valuables = new List<IValuable>();

            public void Value(IValueCalculator calculator)
            {
                foreach (IValuable item in Valuables)
                {
                    item.Value(calculator);
                }
            }
        }

        static void Main(string[] args)
        {
            Person person = new Person() { Name = "new graduate student" };
            person.Valuables.Add(new BankAccount()
            {
                Name = "Saving Account",
                Balance = 5000,
                InterestRate = 0.05m
            });
            person.Valuables.Add(new BankAccount()
            {
                Name = "Cheque Account",
                Balance = 2000,
                InterestRate = 0.01m
            });
            person.Valuables.Add(new Loan()
            {
                Name = "Student Loan",
                Amount = 5000,
                MonthlyPayment = 500
            });

            NetWorthCalculator netWorth = new NetWorthCalculator();
            person.Value(netWorth);
            Console.WriteLine("Assets' net worth is: " + netWorth.GetTotal());

            MonthlyIncomeCalculator monthlyIncome = new MonthlyIncomeCalculator();
            person.Value(monthlyIncome);
            Console.WriteLine("Monthly income from Assets: " + monthlyIncome.GetTotal().ToString("#.##"));

            Console.Read();
        }
    }
}

Run the console app will show following result:

    Assets' net worth is: 2000
    Monthly income from Assets: -477.5

The NetWorthCalculator and MonthlyIncomeCalculator are totally separated from the target IValuable objects. We can implement other type of calculation without any modification on existing code. When adding new IValuable type, the ICalculator interface and its implementations need to include the new type. Back to our example, assume the student found a job after graduation from school, paid off most of the student loan in six months and bought some Microsoft stocks. Two new IValuable types are introduced:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        public interface IValuable  // Interface for visitable objects
        {
            void Value(IValueCalculator calculator);
        }

        public interface IValueCalculator   // Interface for visitor implementation
        {
            decimal GetTotal();
            void Calculate(BankAccount bankAccount);
            void Calculate(Loan load);
            void Calculate(Job stock);
            void Calculate(Stock stock);
        }

        public class NetWorthCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += bankAccount.Balance;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.Amount;
            }

            public void Calculate(Job job)
            {
                // Do nothing
            }

            public void Calculate(Stock stock)
            {
                Total += stock.Price * stock.Share;
            }
        }

        public class MonthlyIncomeCalculator : IValueCalculator
        {
            private decimal Total = 0;

            public decimal GetTotal()
            {
                return Total;
            }

            public void Calculate(BankAccount bankAccount)
            {
                Total += (bankAccount.Balance * bankAccount.InterestRate) / 12;
            }

            public void Calculate(Loan loan)
            {
                Total -= loan.MonthlyPayment;
            }

            public void Calculate(Job job)
            {
                Total += job.Salary / 12;
            }

            public void Calculate(Stock stock)
            {
                // Do nothing
            }
        }

        public class BankAccount : IValuable
        {
            public string Name { get; set; }
            public decimal Balance { get; set; }
            public decimal InterestRate { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Loan : IValuable
        {
            public string Name { get; set; }
            public decimal Amount { get; set; }
            public decimal MonthlyPayment { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Job : IValuable
        {
            public string Name { get; set; }
            public decimal Salary { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Stock : IValuable
        {
            public string Name { get; set; }
            public decimal Price { get; set; }
            public int Share { get; set; }

            public void Value(IValueCalculator calculator)
            {
                calculator.Calculate(this);
            }
        }

        public class Person : IValuable // Composite pattern: Person itself is also IValuable
        {
            public string Name { get; set; }
            public List<IValuable> Valuables = new List<IValuable>();

            public void Value(IValueCalculator calculator)
            {
                foreach (IValuable item in Valuables)
                {
                    item.Value(calculator);
                }
            }
        }

        static void Main(string[] args)
        {
            Person person = new Person() { Name = "6-month after graduation" };
            person.Valuables.Add(new BankAccount()
            {
                Name = "Saving Account",
                Balance = 20000,
                InterestRate = 0.05m
            });
            person.Valuables.Add(new BankAccount()
            {
                Name = "Cheque Account",
                Balance = 5000,
                InterestRate = 0.01m
            });
            person.Valuables.Add(new Loan()
            {
                Name = "Student Loan",
                Amount = 1000,
                MonthlyPayment = 500
            });
            person.Valuables.Add(new Job()
            {
                Name = "Software Developer",
                Salary = 60000
            });
            person.Valuables.Add(new Stock()
            {
                Name = "Microsoft",
                Price = 20,
                Share = 100
            });

            NetWorthCalculator netWorth = new NetWorthCalculator();
            person.Value(netWorth);
            Console.WriteLine("Assets' net worth is: " + netWorth.GetTotal());

            MonthlyIncomeCalculator monthlyIncome = new MonthlyIncomeCalculator();
            person.Value(monthlyIncome);
            Console.WriteLine("Monthly income from Assets: " + monthlyIncome.GetTotal().ToString("#.##"));

            Console.Read();
        }
    }
}

Run the app again and now the net worth and monthly income are both positive:

    Assets' net worth is: 26000
    Monthly income from Assets: 4587.5

The Visitor Pattern is quite useful for some scenarios. But again we use the design patterns to resolve certain problems, and let the code more extensible and maintainable. They may not be suitable for some situations and over using them may make the code unnecessarily complicated.

Thursday, October 11, 2007

.NET Repository Pattern

Domain Driven Design (DDD) attracts quite a lot of attentions in recent years. Repository pattern is one important pattern in DDD. It mediates between the domain and data mapping layers, or a simple delegation of responsibility away from the domain objects.

Consider reading GeoCode from database, we may have following code:
public class GeoCode
{
public double Latitude;
public double Longitude;
public GeoCode(double lat, double lon)
{
Latitude = lat;
Longitude = lon;
}

public GeoCode GetByPostalCode(string postalCode)
{
GeoCode gc = null;
string connectionString = "....";
string sqlQuery = "SELECT Latitude, Longitude FROM GeoCode WHERE PostalCode = @PostalCode";
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand DBCommand = new SqlCommand(sqlQuery, connection);
DBCommand.Parameters.AddWithValue("@PostalCode", postalCode);
using (SqlDataReader reader = DBCommand.ExecuteReader())
{
if (reader.HasRows)
{
gc = new GeoCode(Convert.ToDouble(reader["Latitude"]), Convert.ToDouble(reader["Longitude"]));
}
}
}
}
catch (Exception ex)
{
Logger.LogException(ex);
}
return gc;
}
}
Such code works but it's not flexible and it has direct dependency to the backend store. With repository pattern we need to declare an interface and have a separate implementation:
public class GeoCode
{
public double Latitude;
public double Longitude;
public GeoCode(double lat, double lon)
{
Latitude = lat;
Longitude = lon;
}
}

public interface IGeoCodeRepository
{
GeoCode GetByPostalCode(string postalCode);
}

public class SQLServerGeoCodeRepository : IGeoCodeRepository
{
private string ConnectionString;
public SQLServerGeoCodeRepository()
{
ConnectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
}
public SQLServerGeoCodeRepository(string connectionString)
{
ConnectionString = connectionString;
}

public GeoCode GetByPostalCode(string postalCode)
{
GeoCode gc = null;
string sqlQuery = "SELECT Latitude, Longitude FROM GeoCode WHERE PostalCode = @PostalCode";
try
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
SqlCommand DBCommand = new SqlCommand(sqlQuery, connection);
DBCommand.Parameters.AddWithValue("@PostalCode", postalCode);
using (SqlDataReader reader = DBCommand.ExecuteReader())
{
if (reader.HasRows)
{
gc = new GeoCode(Convert.ToDouble(reader["Latitude"]), Convert.ToDouble(reader["Longitude"]));
}
}
}
}
catch (Exception ex)
{
Logger.LogException(ex);
}
return gc;
}
}
A wrapper class in service layer exposes all related functions:
public class GeoCodeService
{
private IGeoCodeRepository _repository;
public GeoCodeService(IGeoCodeRepository repository)
{
_repository = repository;
}

public GeoCode GetByPostalCode(string postalCode)
{
return _repository.GetByPostalCode(postalCode);
}
}

class Program
{
static void Main(string[] args)
{
IGeoCodeRepository repository = new SQLServerGeoCodeRepository();
GeoCodeService service = new GeoCodeService(repository);
GeoCode gc = service.GetByPostalCode("A1A1A1");
}
}
With repository pattern we can easily extend current implementation. For example, if we need to use web service to get the geo code, we can simply add a new implementation without changing any existing code:
public class WebServiceGeoCodeRepository : IGeoCodeRepository
{
private string WebServiceUrl;
public WebServiceGeoCodeRepository()
{
WebServiceUrl = ConfigurationManager.AppSettings["WebServiceUrl"];
}
public WebServiceGeoCodeRepository(string webServiceUrl)
{
WebServiceUrl = webServiceUrl;
}

public GeoCode GetByPostalCode(string postalCode)
{
GeoCode gc = null;
//Get GeoCode by web service
return gc;
}
}

public class Program
{
static void Main(string[] args)
{
IGeoCodeRepository repository = new WebServiceGeoCodeRepository();
GeoCodeService service = new GeoCodeService(repository);
GeoCode gc = service.GetByPostalCode("A1A1A1");
}
}
The other advantage of using repository pattern is the testability. For example we can create a fake data repository:
public class FakeGeoCodeRepository : IGeoCodeRepository
{
public GeoCode GetByPostalCode(string postalCode)
{
GeoCode gc = null;
double fakeCode = 111.111;
if (postalCode.StartsWith("A", StringComparison.InvariantCultureIgnoreCase))
fakeCode = 123.123;
gc = new GeoCode(fakeCode, fakeCode);
return gc;
}
}
The unit test becomes simple:
 [TestMethod()]
public void GetByPostalCodeTest()
{
IGeoCodeRepository repository = new FakeGeoCodeRepository();
GeoCodeService target = new GeoCodeService(repository);
string postalCode = "M1M1M1";
double expected = 111.111;
GeoCode actual;
actual = target.GetByPostalCode(postalCode);
Assert.AreEqual(expected, actual.Latitude);
Assert.AreEqual(expected, actual.Longitude);

postalCode = "A1A1A1";
expected = 123.123;
actual = target.GetByPostalCode(postalCode);
Assert.AreEqual(expected, actual.Latitude);
Assert.AreEqual(expected, actual.Longitude);
}
Related topics:
http://martinfowler.com/eaaCatalog/repository.html
http://martinfowler.com/articles/injection.html

Saturday, July 07, 2007

Singleton Pattern - A Logger Example

The idea of a singleton is to have a class that has only one instance and a global point of access to the instance. Following code is a simple singleton C# implementation:
public class Singleton
{
private static Singleton instance = new Singleton();

private Singleton() { }

public static Singleton GetInstance()
{
return instance;
}
}
The above implementation creates a new static instance during the class initialization. The singleton instance is retrieved by a static GetInstance method. An alternative is expose the singleton object by read-only property without a setter. The code needs a little bit change if a lazy creation is required:
public class Singleton
{
private static volatile Singleton instance;
private static object syncObj = new Object();

private Singleton() {}

public static Singleton GetInstance()
{
if (instance == null)
{
lock (syncObj)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
SyncLock in above code is for thread-safe consideration. In addition, the singleton class could be sealed if you don't like people to inherit from it and break the singleton principle.

Singleton pattern is very useful in some use cases. Here's a real life example. I needed a file logger for a simple web service application used in a small company. Enterprise library, logging application block, and even log4Net are just too heavy for such small application. In addition, the client is rejective to third-party tools.

I decided to write a file logger by myself. A stream writer was used, but I don't want multiple instances of stream writers being created and used at the same time. The IO is expensive and multiple accesses to a single file is not safe. Singleton came to play and only one instance of logger and one stream writer is created:
using System;
using System.IO;
using System.Configuration;
using System.Diagnostics;

class Program
{
static void Main(string[] args)
{
Logger.WriteLog("Jus a test.");
Logger.WriteLog(LogSeverity.Info, "Another test.");
Console.Read();
}
}

// A helper static class to get access the logger
public static class Logger
{
private static readonly FileLogger _logger = FileLogger.GetInstance();

public static void WriteLog(String log)
{
_logger.Write(log);
}
public static void WriteLog(LogSeverity logLevel, String log)
{
_logger.Write(logLevel, log);
}
}

// Enumeration for log severity
public enum LogSeverity { Error, Warning, Info, Debug };

// FileLogger class with Singleton pattern
internal sealed class FileLogger : IDisposable
{
private static FileLogger _instance = null; // Singleton object
private static object _syncLock = new object(); // Sync lock

internal StreamWriter _writer; // Stream writer writting to the log file
internal string _path = "C:\\Logs"; // Default folder
internal string _absolutePath; // C:\Logs\MachineName.log
internal string _fileName; // MachineName.log
internal int _logFileSize = 2; // New log file when its size bigger than 2 MB
internal LogSeverity _defaultSeverity = LogSeverity.Error; // Default severity

// Private constructor
private FileLogger()
{
GetConfigSettings();

_fileName = string.IsNullOrEmpty(Environment.MachineName) ?
"LogFile.log" : Environment.MachineName + ".log";
_absolutePath = _path + "\\" + _fileName;

if (!Directory.Exists(_path))
{
Directory.CreateDirectory(_path);
}

_writer = new StreamWriter(_absolutePath, true);
}

// Public static method to get Singleton object
public static FileLogger GetInstance()
{
if (_instance == null)
{
lock (_syncLock)
{
if (_instance == null)
{
_instance = new FileLogger();
}
}
}
return _instance;
}

// Check if the log file exceeds the maximum size
private void CheckFileSize()
{
if (_writer.BaseStream.Length >= (_logFileSize * 1024 * 1024))
{
this.Dispose();
string backupFile = string.Format("{0}\\{1}-{2}.log",
_path, Environment.MachineName, DateTime.Now.ToString("yyyyMMdd-HHmmsss"));
try
{
while (File.Exists(backupFile))
{
backupFile = backupFile.Replace(".log", "_1.log");
}
File.Move(_absolutePath, backupFile);
this.Dispose();
_writer = new StreamWriter(_absolutePath, true);
}
catch (Exception ex)
{
WriteToEventLog(ex.Message);
}
}
}

// Get default setting from configuraiton file
private void GetConfigSettings()
{
string appSetting = ConfigurationManager.AppSettings["FileLogger_Path"];
if (!string.IsNullOrEmpty(appSetting))
{
_path = appSetting;
}
int maxFileSize;
appSetting = ConfigurationManager.AppSettings["FileLogger_MaxFileSizeInMB"];
if (!string.IsNullOrEmpty(appSetting) && int.TryParse(appSetting, out maxFileSize))
{
_logFileSize = maxFileSize;
}
appSetting = ConfigurationManager.AppSettings["FileLogger_DefaultSeverity"];
if (!string.IsNullOrEmpty(appSetting))
{
try
{
_defaultSeverity = (LogSeverity)Enum.Parse(typeof(LogSeverity), appSetting);
}
catch (Exception ex)
{
WriteToEventLog(ex.Message);
}
}
}

// Clean up the stream writer
public void Dispose()
{
lock (_syncLock)
{
if (_writer != null)
{
_writer.Dispose();
}
}
}

// Write with default log severity
public void Write(string msg)
{
Write(_defaultSeverity, msg);
}

// Write message to log file
public void Write(LogSeverity logSeverity, string msg)
{
lock (_syncLock)
{
try
{
if (_writer.BaseStream == null)
{
_writer = new StreamWriter(_absolutePath, true);
}
CheckFileSize();
_writer.WriteLine("[{0}] at {1} -- {2}",
logSeverity.ToString(), DateTime.Now.ToString(), msg);
_writer.Flush();
}
catch (Exception ex)
{
WriteToEventLog(ex.Message);
}
}
}

private void WriteToEventLog(string message)
{
string source = "Logger";
string log = "Application";

try
{
if (!EventLog.SourceExists(source))
EventLog.CreateEventSource(source, log);

EventLog.WriteEntry(source, message, EventLogEntryType.Error);
}
catch { }
}
}