Wednesday, January 23, 2008

Design Patterns for 70% programmers in the world

You must be wondering where was I from past 2 weeks. :) The answer is embeded below.



Agenda:
• Do you OOPs?
• Design Patterns? Why
• Design Patterns? What
• Design Patterns? How
• Why I hate my job?

In this presentation, I covered “Most Popular Top 10 Design Patterns” :

• Creational (Factory, Abstract Factory and Singleton)
• Structural (Façade, Decorator, Composite and Adapter)
• Behavioral (Strategy, Template and Command)

Target Audience:
Struggling developers who are in the realization phase of their career as a developer and try to reinvent themselves with OOPS.

Share this to your developer friends.

Download The Presentation

Sunday, January 6, 2008

Using Predicate Delegate & Anonymous Methods to create LINQ like functionality

Today, I would be your guide on our way to empower custom collections (i.e. Employee, Order, Account, etc) to facilitate LINQ like functionality. Before we step into creating this kind of functionality, let's understand few basic concepts first:

  1. Predicate Delegate: We use a Predicate delegate in lieu of a special delegate(function pointer) which takes only one argument and returns a boolean value. This type of delegate is specially used by .NET Framework List classes. For understanding this better, read my previous post on Predicate Delegate.
  2. Anonymous Method: These can be termed as block of code being passed as an argument to a function call. A sort of inline function. For understanding this better, read my previous post on Anonymous Methods.

We will start with understanding what we are trying to accomplish. We want a Generic List which facilitates the following:

  1. Sort on any property of the object in a collection, that too without writing any Custom Comparer. Once you finish reading David Hayden's blog where he talks about creating and using a Custom Comparer, you can understand the amount of code we write to facilitate sorting on custom properties. For example, we may have a collection of Person and would like to sort on "Lastname", "Firstname" and "Age".

    This requirement translates into providing a generic "OrderBy" clause/method into our custom generic list.

    So my version of David's code would proprably look like below:
    //Create Person collection
    LinqList<Person> people = new LinqList<Person>();
    people.Add(new Person("John","Doe", 76));
    people.Add(new Person("Abby","Normal", 25));
    people.Add(new Person("Jane","Doe", 84));

    //Sort by Lastname
    DisplayPeople(people.OrderBy<string>("Lastname"));

    //Sort by Age
    DisplayPeople(people.OrderBy<int>("Age"));

    //Sort by Firstname
    DisplayPeople(people.OrderBy<string>("Firstname"));
  2. Search/Find on any property of the object in a collection. Believe me or not, this too requires us to write custom comparers; like ones which we saw on David Hayden's blog. For example, we may have a collection of Person and would like to search for Lastname="Doe" or Age=25.

    This requirement translates into providing a generic "Where" clause/method into our custom generic list.

    My code would proprably look like below:

    //Create Person collection
    LinqList<Person> people = new LinqList<Person>();
    people.Add(new Person("John","Doe", 76));
    people.Add(new Person("Abby","Normal", 25));
    people.Add(new Person("Jane","Doe", 84));

    //Search where Lastname = 'Doe'
    DisplayPeople(people.Where<string>("Lastname", "Doe"));

    //Search where Age = 25
    DisplayPeople(people.Where<int>("Age", 25));

I will call this generic list as "LinqList" because I am trying to imitate LINQ functionality with best of my ability which will possess an ability of performing search using "Where" and sort using "OrderBy".

So, How do we design Linq kind-of functionality?

Since, I am going to design this; it becomes my responsibility to help you map these with C# provided functionality. "Where" maps to GenericList.FindAll() and "OrderBy" to GenericList.Sort(). You must be thinking if this already exists than why are we trying to re-invent the wheel?

I swear I am not cheating on you.. C# always looks for custom concrete comparer to perform the both - Find()/FindAll() and Sort(). To facilitate with a Generic Internal Comparer, I will be utilizing what we have learned from our past stories:

  1. Predicate Delegates
  2. Anonymous Methods
  3. Generic Methods and Generic Collections

Basic design consists of two components;

1) Finder - to facilitate GenericFind() and GenericSort()

Finder

2) LinqList - to consume Finder and turn a normal generic list into LINQ like list.

LinqList

Understanding the design of Finder

Let me show you the code of Finder.GenericFind()

/// <summary>
///
Perform find() operation
/// </summary>
/// <param name="collectionToBeSearched">
Give the list to be searched</param>
/// <param name="criteria">
Criteria to be compared</param>
/// <param name="fieldName">
Name of the property to be compared</param>
/// <param name="finderOption">
Types of Search Options to be used with Finder</param>
public List<listType> GenericFind(List<listType> collectionToBeSearched, fieldType criteria, string propertyName, SearchOptions finderOption)
{
List<listType> findResults = collectionToBeSearched.FindAll(
delegate(listType input)
{
bool result = false;

fieldType currentValue = (fieldType)input.GetType().GetProperty(propertyName).GetValue(input, null);
result = Compare<fieldType>(currentValue, criteria, finderOption);

return result;
});

return findResults;
}
/// <summary>
///
Compare object of type IComparable using CompareTo()
/// T defines the type of objects to be compared
/// </summary>
private bool Compare<T>(T value, T criteria, SearchOptions finderOption) where T : IComparable<T>
{
bool result = false;

switch (finderOption)
{
case SearchOptions.GreaterThan:
result = (value.CompareTo(criteria) > 0);
break;
case SearchOptions.GreaterThanOrEqualTo:
result = (value.CompareTo(criteria) >= 0);
break;
case SearchOptions.LessThan:
result = (value.CompareTo(criteria) < 0);
break;
case SearchOptions.LessThanEqualTo:
result = (value.CompareTo(criteria) <= 0);
break;
case SearchOptions.EqualTo:
result = (value.CompareTo(criteria) == 0);
break;
case SearchOptions.NotEqualTo:
result = (value.CompareTo(criteria) != 0);
break;
}

return result;
}

In GenericFind() method, I check the criteria using Predicate Delegate via Anonymous Method and then Concrete Reflection to dynamically read the value of the specified property and then evaluate the "read property value" to the criteria using Genrics based IComparable<T>.

There is another method too, Finder.GenericSort(); time to see the code :)

/// <summary>
///
Perform sort() operation
/// </summary>
/// <param name="collectionToBeSearched">
Give the list to be searched</param>
/// <param name="criteria">
Criteria to be compared</param>
/// <param name="fieldName">
Name of the property to be compared</param>
/// <param name="sortOption">
Types of Sort Options to be used with Finder</param>
public List<listType> GenericSort(List<listType> collectionToBeSearched, string propertyName, SortOptions sortOption)
{
collectionToBeSearched.Sort(
delegate(listType c1, listType c2)
{
int result;

fieldType valueToCompareWith = (fieldType)c1.GetType().GetProperty(propertyName).GetValue(c1, null);
fieldType valueToBeCompared = (fieldType)c2.GetType().GetProperty(propertyName).GetValue(c2, null);

if (sortOption == SortOptions.Ascending)
result = Comparer<fieldType>.Default.Compare(valueToCompareWith, valueToBeCompared);
else
result = Comparer<fieldType>.Default.Compare(valueToBeCompared, valueToCompareWith);

return result;
});

return collectionToBeSearched;
}

In GenericSort() I used Anonymous Method to consume List<T>:Sort Method (IComparer<T>) and then Concrete Reflection to dynamically read the value of the specified property and then compare "specified property's value" using Generics based IComparer<T>.

To supplement GenericFind() and GenericSort(), I used enums - SearchOptions and SortOptions. I will show you its self explanatory code:

/// <summary>
///
Types of Search Options to be used with Finder
/// </summary>
public enum SearchOptions
{
GreaterThan,
GreaterThanOrEqualTo,
LessThan,
LessThanEqualTo,
EqualTo,
NotEqualTo
}

/// <summary>
///
Types of Sort Options to be used with Finder
/// </summary>
public enum SortOptions
{
Ascending,
Descending
}

Understanding the design of LinqList

LinqList has a pretty simple code base. I just inherit it from Generic List<T> and add two generic based methods - Where and OrderBy; which internally consumes Finder.GenericFind() and Finder.GenericSort(), respectively.

/// <summary>
///
Use this class enrich your collection
/// with LINQ type functionality
/// </summary>
/// <typeparam name="T"></typeparam>
public class LinqList<T> : List<T>
{
/// <summary>
///
Search within your collection
/// </summary>
public LinqList<T> Where<R>(string propertyName, R criteria, SearchOptions findOption) where R : IComparable<R>
{
return new FinderUsingLinq<T, R>().GenericFind(this, criteria, propertyName, findOption);
}

/// <summary>
///
Search within your collection
/// using default EqualTo SearchOption
/// </summary>
public LinqList<T> Where<R>(string propertyName, R criteria) where R : IComparable<R>
{
return Where<R>(propertyName, criteria, SearchOptions.EqualTo);
}

/// <summary>
///
Sort your collection
/// </summary>
public LinqList<T> OrderBy<R>(string propertyName, SortOptions sortOption) where R : IComparable<R>
{
//Perform the generic sort
new FinderUsingLinq<T, R>().GenericSort(this, propertyName, sortOption);

return this;
}

/// <summary>
///
Sort your collection
/// using default Ascending SortOption
/// </summary>
/// <typeparam name="R"></typeparam>
/// <param name="propertyName"></param>
/// <returns></returns>
public LinqList<T> OrderBy<R>(string propertyName) where R : IComparable<R>
{
return OrderBy<R>(propertyName, SortOptions.Ascending);
}
}

Let's use newly created LinqList to Search and Sort

I will use David's person class.

public class Person
{
#region Private Members

private string _firstname;
private string _lastname;
private int _age;

#endregion

#region
Properties

public string Firstname
{
get { return _firstname; }
set { _firstname = value; }
}

public string Lastname
{
get { return _lastname; }
set { _lastname = value; }
}

public int Age
{
get { return _age; }
set { _age = value; }
}

#endregion

#region
Contructors

public Person(string firstname, string lastname, int age)
{
_firstname = firstname;
_lastname = lastname;
_age = age;
}

#endregion
}

Interested in code for Search and Sort functionality?

    //Create Person collection
    LinqList<Person> people = new LinqList<Person>();
    people.Add(new Person("John","Doe", 76));
    people.Add(new Person("Abby","Normal", 25));
    people.Add(new Person("Jane","Doe", 84));

    //Sort by Lastname
    DisplayPeople(people.OrderBy<string>("Lastname"));
    //Sort by Age
    DisplayPeople(people.OrderBy<int>("Age"));
    //Sort by Firstname
    DisplayPeople(people.OrderBy<string>("Firstname"));
    //Search where Lastname = 'Doe'
    DisplayPeople(people.Where<string>("Lastname", "Doe"));
    //Search where Age = 25
    DisplayPeople(people.Where<int>("Age", 25));

    //Search where Lastname = 'Doe' and sort the resultset by Age
    DisplayPeople(people.Where<string>("Lastname", "Doe").OrderBy<int>("Age"));

Wondering about the DisplayPeople(); see it here

//Iterate through the collection and print person details
private static void DisplayPeople(LinqList<Person> people)
{
Console.WriteLine("******** start ***********");

//Print people list
people.ForEach(delegate(Person person)
{
Console.WriteLine("{0} {1}, Age = {2}", person.Lastname, person.Firstname, person.Age);
}
);

Console.WriteLine("******** end *************");
Console.WriteLine();
}

Conclusion

In this post, I explained how we can use some really cool features of C# 2.0 Framework and accompalish real simple and widely used functionality like "Search" and "Sort". If you read the syntax of Where and OrderBy, you can easily feel the power of flow based programming. Example:

//Search where Lastname = 'Doe' and sort the resultset by Age
DisplayPeople(people.Where<string>("Lastname", "Doe").OrderBy<int>("Age"));

TIP: I am not sure how many of my readers noticed DisplayPeople(). This method uses one of another C# feature - List<T>.ForEach(), which uses Action(T) delegate. For knowing more about the Action(T) delegate, read my other post - Lights .. Camera .. Action (Action Delegate).

Saturday, January 5, 2008

Create a Military Parade of your own (Flow based Programming)

By the time, I am not writing it, you can read about this here; http://en.wikipedia.org/wiki/Flow-based_programming

Lights .. Camera .. Action (Action Delegate)

You can read about Action Delegate from http://msdn2.microsoft.com/en-us/library/018hxwa8.aspx

and you can see how its used by List(T).ForEach method http://msdn2.microsoft.com/en-us/library/bwabdf9z.aspx

Smash your head to the wall in your house (Concrete Reflection)

Trust me I am being impatient now... for the time being please use http://msdn.microsoft.com/msdnmag/issues/03/03/DesignPatterns/ to help you out

Story of Stunt Duplicates (C# Generics)

I would be writing soon about C# generics, for the time being I will use http://www.codeguru.com/csharp/.net/net_asp/tutorials/article.php/c11887/

An excellent tutorial from WROX publishers.