fuzzelogic Solutions

August 19, 2009

sOlid :: Open Closed

Filed under: BDD, OO, Programming, c#, design — Tags: , , — admin @ 5:48 pm

Hey!

So, we got this one done as well. Thank you to everyone that turned up.

We went through ideas the principles hope to solve, and covered the OCP. We had a look at a couple of solutions on solving the good old “Filter a list of products”.

We also managed to sneak in the Specification pattern and managed to get through some good questions.

Again, everyone was happy enough to continue, so we’ve penciled in the week of the 21st September. I’ll have to confirm a date.

I’ll update the code base for download.

Once again, thanks to everyone.

Zak

August 18, 2009

Still sOlid

Filed under: BDD, OO, Programming, c#, design — Tags: , , — admin @ 6:22 am

Hi All!

Just a quick reminder, the “O” from S.O.L.I.D is up for discussion 19th August 2009. Same place, and similar time.

Hope to see you all there.

Zak

April 16, 2009

Open closed principle

Filed under: OO, design — Tags: , , , — admin @ 5:17 pm

O.C.P : Open closed principle….
       an object is open for extension but closed for modification.

So to understand what this means, lets consider the following scenario - (There’s a bunch of code).

We have a product entity, and we can get lists of these back from our repository.
The Requirement for Today: we’re asked to create a filtered list of products that match a certain color, so we create the following product filter class, who’s job it is to filter the list.
     

public class ProductFilter{
               public IEnumberable<IProduct> GetItemsMatchingTheColor( IEnumerable<IProduct> fullList, Color color) {
                   foreach ( var item in fullList )
                       if ( item.ItsColor == color);
                            yield return item;
               }
           }

That’s fine, and it gets us what we want… but as we know, change is always around the corner….

Requirement a little in the future: we’re asked to get list filtered by Product size.

      
           public class ProductFilter{
              public IEnumberable<IProduct> GetItemsMatchingTheColor( IEnumerable<IProduct> fullList, Color color) {
                   foreach ( var item in fullList )
                       if ( item.ItsColor == color);
                            yield return item;
               }
               // Added this new method…
               public IEnumberable<IProduct> GetItemsMatchingSomeSize( IEnumerable<IProduct> fullList, ProductSize size) {
                   foreach ( var item in fullList )
                       if ( item.Size == size);
                            yield return item;
               }
           }

so what did we do here??? well we cracked open the filter object added the new behavior and rebuilt it.

Requirement a little further in the future: we’re asked to get list filtered by Product size AND Color.

public class ProductFilter{
public IEnumberable<IProduct> GetItemsMatchingTheColor( IEnumerable<IProduct> fullList, Color color) {
                   foreach ( var item in fullList )
                       if ( item.ItsColor == color);
                            yield return item;
               }

public IEnumberable<IProduct> GetItemsMatchingSomeSize( IEnumerable<IProduct> fullList, ProductSize size) {
                   foreach ( var item in fullList )
                       if ( item.Size == size);
                            yield return item;
               }
               // Added this new method…
               public IEnumberable<IProduct> GetItemsMatchingSomeSize( IEnumerable<IProduct> fullList, ProductSize size, Color color) {
                   foreach ( var item in fullList )
                       if ( item.Size == size &amp;&amp; item.ItsColor==color);
                            yield return item;
               }
           }

so what did we do here??? well AGAIN we cracked open the filter object added the new behavior and rebuilt it. Although we managed to extend the behavior of the object we violated the OCP. What are the benefits of OCP? Well by following the principle we have 2 benefits:
               1. Objects are extensible which will satisfiy changing requirements
               2. Objects are maintainable and stable, because they didn’t change, there’s less chance of introducing bugs.

So how do we do this, how do extend something without cracking it open?(one way)….

If if we consider a few design principles… encapsulate what varies: in this case the filter specification. (I’ll also sneek in the specification pattern here)

    /// <summary>
    /// Interface to be implemented by objects that act as specifications
    /// </summary>
    /// <typeparam name=”T”></typeparam>
    public interface ISpecification<T>
    {
        bool IsSatisfiedBy(T item);
    }

    /// <summary>
    /// Interface to be implemented by objects that support filtering
    /// </summary>
    /// <typeparam name=”TypeToFilter”></typeparam>
    public interface IFilter<TypeToFilter>
    {
        IEnumerable<TypeToFilter> Filter(IEnumerable<TypeToFilter> completelist, ISpecification<TypeToFilter> specification);
    }

// For completeness of the sample….

    /// <summary>
    /// The Product interface.
    /// </summary>
    public interface IProduct
    {
        string Name { get; set; }
        Color ItsColor { get; set; }
        ProductSize Size { get; set; }
    }

    /// <summary>
    /// Enum defining the sizes
    /// </summary>
    public enum ProductSize
    {
        Small, Medium, Large, ReallyBig
    }

Now the refactored Filter object.

    /// <summary>
    /// The Filter class
    /// </summary>
    public class ProductFilter : IFilter<IProduct>
    {   �
        public IEnumerable<IProduct> Filter(IEnumerable<IProduct> completelist, ISpecification<IProduct> specification)
        {
             foreach (var product in completelist )
                 if ( specification.IsSatisfiedBy ( product ))
                     yield return product;
        }
    }

Now we have a Product filter object that accepts a complete list of products and specification that we can filter on. All we need to do now is provide the filtering specifications.

    #region -[ Specifications ]-

    /// <summary>
    /// Individual specification for a color filter
    /// </summary>
    public class ColorFilterSpecification : ISpecification<IProduct>
    {
        Color colorToMatch;

        public ColorFilterSpecification(Color colorToMatch)
        {
            this.colorToMatch = colorToMatch;
        }
        public bool IsSatisfiedBy(IProduct item)
        {
            return item.ItsColor == colorToMatch;
        }
    }
    /// <summary>
    /// Individual specification for a Size filter
    /// </summary>
    public class SizeFilterSpecification : ISpecification<IProduct>
    {
        ProductSize sizeToMatch;
        public SizeFilterSpecification(ProductSize sizeToMatch)
        {
            this.sizeToMatch = sizeToMatch;
        }
        public bool IsSatisfiedBy(IProduct item)
        {
            return item.Size == sizeToMatch;
        }

    }

    /// <summary>
    /// Without exploding this into a full blow specification pattern
    /// where you can “chain” specifications together in .. AND, OR..etc
    /// a very basic “And” specification
    /// </summary>
    public class AndSpecification<T> : ISpecification<T>
    {
        ISpecification<T> first;
        ISpecification<T> second;

        public AndSpecification(ISpecification<T> first, ISpecification<T> second)
        {
            this.first = first;
            this.second = second;
        }
        public bool IsSatisfiedBy(T item)
        {
            return ( first.IsSatisfiedBy(item) &amp;&amp; second.IsSatisfiedBy(item));
        }
    }

    /// <summary>
    /// Without exploding this into a full blow specification pattern
    /// where you can “chain” specifications together in .. AND, OR..etc
    /// a very basic “OR” specification
    /// </summary>
    public class ORSpecification<T> : ISpecification<T>
    {
        ISpecification<T> first;
        ISpecification<T> second;

        public ORSpecification(ISpecification<T> first, ISpecification<T> second)
        {
            this.first = first;
            this.second = second;
        }
        public bool IsSatisfiedBy(T item)
        {
            return (first.IsSatisfiedBy(item) || second.IsSatisfiedBy(item));
        }
    }

    #endregion

And to test all this actually works, here’s a very basic set of tests using MSTest built into the Visual studio

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
//using Reference to where your code lives.
using System.Drawing;

namespace _Tests_For_OOConcepts
{
    /// <summary>
    /// Summary description for FilterTests
    /// </summary>
    [TestClass]
    public class FilterTests
    {

        IEnumerable<IProduct> complete_list;
        IEnumerable<IProduct> results;
        IFilter<IProduct> System_under_test;
            �
        [TestInitialize]
        public void startup()
        {
            complete_list = Fake_list_of_products();
            System_under_test = new ProductFilter();
        }

        [TestMethod]
        public void List_only_contains_items_of_a_specified_COLOR()
        {
            results = Action_the_system_under_test_with(new ColorFilterSpecification(Color.Orange));

            foreach (var item in results)
                Assert.IsTrue(item.ItsColor == Color.Orange);
        }
    �
        [TestMethod]
        public void List_only_contains_items_of_a_specified_SIZE()
        {
            results = Action_the_system_under_test_with( new SizeFilterSpecification(ProductSize.Small) );
            foreach (var item in results)
                Assert.IsTrue(item.Size == ProductSize.Small);
        }
    �
        [TestMethod]
        public void List_only_contains_items_of_a_specified_SIZE_AND_COLOR()
        {
            var the_matching_criteria = new AndSpecification<IProduct>(new ColorFilterSpecification(Color.AliceBlue),
                                                                        new SizeFilterSpecification(ProductSize.Small));
                   �
            results = Action_the_system_under_test_with(the_matching_criteria);
            foreach (var item in results)
            {
                Assert.IsTrue(item.Size == ProductSize.Small);
                Assert.IsTrue(item.ItsColor == Color.AliceBlue);
            }
        }

        public IEnumerable<IProduct> Action_the_system_under_test_with(ISpecification<IProduct> the_filter_specification_to_use)
        {
            return System_under_test.Filter(complete_list, the_filter_specification_to_use);
        }
        public IEnumerable<IProduct> Fake_list_of_products()
        {

            yield return new FakeProduct(”apple”, Color.Red, ProductSize.Large);
            yield return new FakeProduct(”apple2″, Color.Red, ProductSize.Medium);
            yield return new FakeProduct(”orange”, Color.Orange, ProductSize.Medium);
            yield return new FakeProduct(”orange2″, Color.Orange, ProductSize.Large);
            yield return new FakeProduct(”bananna”, Color.Yellow, ProductSize.Small);
            yield return new FakeProduct(”bananna2″, Color.Yellow, ProductSize.ReallyBig);
            yield return new FakeProduct(”stuffed bear”, Color.AliceBlue, ProductSize.ReallyBig);
            yield return new FakeProduct(”stuffed bear2″, Color.Orange, ProductSize.Small);
        }

    }

    public class FakeProduct : IProduct
    {

        public FakeProduct(string name, Color theColor, ProductSize itsSize)
        {
            this.Name = name;
            this.ItsColor = theColor;
            this.Size = itsSize;
        }
    �
        public string Name {get;set;}
        public Color ItsColor {get;set;}
        public ProductSize Size { get; set; }
    }

}

So now we can vary the filter specification, add new specifications and extend the filtering object without actually modifying the source code of the Filter object.

Hope this helps
Zak

March 26, 2009

Chain of responsibility

Hi!

In an application I’m currently working on I have a need to process the file. The processing is determined by the type of file it is. Sounds like an ideal condidate for large complicated “if” block…. or chain of responsibility pattern. hmmmm.

COR seems like exactly what I want.. so first we need handlers ( these can handle the file ) then we need to tell each handler the next handler .. then have a means of determining if a handler can actually process the request, if not it passess this to the next handler in the chain.
Initially this is what I ended up with…

IHandler doc= new DocFileHandler();   
IHandler xl= new XLFileHandler();   
IHandler ppt= new PPTFileHandler();     // Setup the chain of responsibility.     doc.SetNextHandler(xl);    
xl.SetNextHandler(ppt);               // Throw the first handler the file request .    
doc.Handle(someFile);

It works, all goes well, but still…. all I want to do is tell the handler if it can’t handle the request to pass it on. There’s only a NEXT handler, not a list, so I used the following…

the interface ..

public interface {
void Handle(T itemToHandle);
bool CanHandle(T item);
}

and another class …

public class ChainedHandlers<T>:IHandler<T>
    {
        private readonly IHandler<T> first;
        private readonly IHandler<T> nextHandler;

        public ChainedHandlers(IHandler<T> first, IHandler<T> nextHandler )
        {
            this.first = first;
            this.nextHandler = nextHandler;
        }

        public void Handle(T itemToHandle)
        {
            if (first.CanHandle(itemToHandle))
                first.Handle(itemToHandle);
            else
            {
                nextHandler.Handle(itemToHandle);
            }
        }

        public bool CanHandle(T item)
        {
            return true;// a fake value ??
        }
    }

then …. as an extension class I created…

static public IHandler<T> add_next_handler <T>(this IHandler<T> first, IHandler<T> nextHandler )

{
 return new ChainedHandlers<T>(first, nextHandler);
 }

So far so good.. so using all this now I can do…

 var  docHandler = new DocHandler();
 docHandler
  .add_next_handler(new XlHandler())
                .add_next_handler(new PPTHandler())
                .Handle(someFile);
 

Points of interest : It’s an example of the Open/Closed Principle.  The behavior of the system can be altered by either adding handlers or changing the order of the handlers in the chain of responsibility without making any further code modifications.

Hope this helps!
Zak

Powered by WordPress