in

 

AgileJoe

Answering all world issues with, "...it depends..."

March 2008 - Posts

  • PTOM: OCP revisited in Ruby

    I was playing with some Ruby code this weekend and thought I would show some OCP with Ruby.

    For more of an in-depth discussion on OCP please read my previous post.

    Now the first thing I want to point out is that dynamic languages are naturally by default open for extension. Since the types are dynamic, there are no fixed (static) types. The enables us to have awesome extensibility. It is the closure part of the equation that really scares me more than anything else. If you really aren’t careful when you are programming with dynamic languages you can quickly make a mess of things. This doesn’t take away from the power of a dynamic language you just have to exercise greater care that is all.

    So let’s use our OCP scenario template again and apply them to the example scenario.

    • The ProductFilter is responsible for filtering products by color
    • The ProductFilter is responsible for filtering products by size
    • The ProductFilter is responsible for filtering products by color and size

    Let’s go ahead and create the ProductFilter first.

    class ProductFilter
        
        attr_reader :products
        
        def initialize(products)
            @products = products
        end
        
        def by(filter_spec)
            
        end
    end

    For those that have never created a class in Ruby let me breakdown the syntax structures.

    class keyword is used to define a class followed by the name of the class. It is important to note that class names must be start with an uppercase letter. The uppercase letter signifies to the Ruby interpreter that this is constant, meaning that whenever the term “ProductFilter” comes up it will always reference this class structure.

    attr_reader keyword used to signify a read only accessor (read only property). The property name follows the colon.

    def keyword is used to declare a method block. The “initialize” method is the same as the constructor method in C#.

    The @ symbol denotes an instance variable. Notice that the “products” read accessor is never typed but is assigned in the constructor through @products reference. The instance variable @products is assigned to the products parameter variable that is passed into the constructor.

    Now that we are talking about products we have to create the actual product class.

    class Product
        attr_accessor :color
        attr_accessor :size
        
        def initialize(color, size)
            @color = color
            @size = size
        end
    end

    Nothing fancy here, just a class with two read/write accessors Color and Size.

    If you remember from my previous post I was using a template pattern to serve as the basis for extending the behavior of my filter class. Well I am going to do the same thing here (kind of) and define an Item_color_filter_spec class.

    class Item_color_filter_spec
        attr_accessor :color
        
        def initialize(color)
            @color = color
        end
        
        def apply_to(items)
            
        end
    end

    Now I have a class that accepts a color and has an “apply_to” method that accepts “items”. I have left out the implementation code of this method on purpose.

    The next thing I am going to do is create an array of products I can use against the ProductFilter class. Ruby makes this pretty painless:

    products = [
        Product.new("Blue", "Large"),
        Product.new("Red", "Large"),
        Product.new("Blue", "Medium"),
        Product.new("Red", "Small"),
        Product.new("Blue", "Large"),
        Product.new("Yellow", "Small"),
    ]

    So what’s going on here? I declared a variable called “products” and assigned it to array by using the square braces “[ ]”. Yup that simple!

    What you may have noticed is that I actually instantiated several new products in the array. To instantiate a class you simply use the “new” method that is part of the Object class that all objects in Ruby inherit from similar to C#.

    Now that I have a collection of products I am going to give to my product filter class.

    product_filter = Product_Filter.new(products)

    In the example below I am going to filter all the “Blue” products.

    blue_products = product_filter.by(Item_color_filter_spec.new("Blue"))

    At this point I am creating a new “Item_color_filter_spec” and giving the color “Blue” as the color to filter on. The ProductFilter class would then simply call the “apply_to” method on the “Item_color_filter_spec”.

    If you ran the code at this point nothing would happen because we haven’t actually written our filter code yet. So to do that we are going to modify the “apply_to” method of our “Item_color_filter_spec” class with the following code.

    def apply_to(items)
        items.select{|item| item.color == @color}
    end

    In the code above the “apply_to” method is expecting an array of items to be passed in. We then call the “select” method on the array class and pass in a filter “proc” by enclosing the statement in curly braces {} (In Ruby a “proc” is an object that holds a chunk of code but more on this later). The pipe block “||” is used to signify parameters to the proc similar to the parameters of a method. After the pipe block is the actual statement that is executed. We are trusting that the “select” method of the array object is going to enumerate over each object (product) it contains and pass it into Proc. Once in the Proc we simply determine if the color of product matches the instance variable “@color” of the “Item_color_filter_spec” in this case the color “blue”. When the Proc evaluates to true it passes the item to an array that the select method returns.

    You can possibly equate a “proc” to a lambda expression in C#.

    (Normally I would have used rSpec to govern everything I am doing but I didn’t want to explain BDD as well. I wanted to focus on the Ruby language in general.)

    Now if you run the code you will have three products in the “blue_products” variable. How do you know? Well let’s iterate over it by using the following code.

    blue_products.each do |product|
        puts(product.color)
    end

    Now remember “blue_products” is an array object. The array object has an “each” method (as do other objects in Ruby) that accepts a “proc” object. The “proc” block is denoted by the “do” keyword and terminated with the “end” keyword. In our block we expecting that the array objects “each” method is going to give us a product. As the each method iterates over each product it passes it to the “proc” and we simply tell Ruby to write it to the screen using the “puts” method. The result of this small statement block in the following:

    Blue
    
    Blue
    
    Blue
    

    So there you have it 3 blue products!

    I know, nothing special right? Well now let’s play with some Ruby sweetness!

    That sure is a lot effort to filter a product by color. Imagine if you had to keep adding different color filters. You would have to create several “color filter specs” over and over again. That is dull and most static languages have played this out! So let’s use some Ruby Lambda’s to accomplish the same thing as the “color filter spec”

    We are going to create a filter spec that filters all products that are yellow.

    Remember I told you that Ruby views all uppercase variable names as constants; well we are going to harness the power of this convention and create a constant to hold the reference to the lambda. After all DRY principles still apply here.

    YELLOW_COLOR_FILTER_SPEC = lambda do |products|
        products.select{|product| product.color == "Yellow"}
    end

    Nothing in the code block above should be foreign at this point except for the “lambda” key word. What the “lambda” keyword does is tell the Ruby interpreter to assign the “Proc” to the constant “YELLOW_COLOR_FILTER_SPEC”.

    We have to now modify our ProductFilter class to accept a Proc object. All you have to do is add the following method to the ProductFilter class.

    def by_proc(&filter_spec_proc)
        filter_spec_proc.call(@products)
    end

    This method has a parameter named “filter_spec_proc” but if you notice there is an ampersand preceding its declaration. This tells the Ruby interpreter to expect a Proc object to be passed in. Since we are expecting a Proc object all we have to do is use the "call" method and pass the products instance variable to the Proc.

    Now let’s wire the whole thing together.

    yellow_products = product_filter.by_proc(&YELLOW_COLOR_FILTER_SPEC)

    Pretty simple about the only thing you have to remember is that you have to place the ampersand before the Proc constant when you call the “by_proc” method on the ProductFilter class.

    But wait there is more!

    Our ProductFilter class now has a method that accepts a Proc object. In our previous example we passed it a constant that referenced a lambda Proc block. But since it accepts a Proc we can simply write the block in line with the method call like this.

    With our new found knowledge lets filter all the “Red” products.

    red_products = product_filter.by_proc do |products|
            products.select{|product| product.color == "Red"}
        end

    Parenthesis are optional in Ruby when you call a method.

    Pretty nice huh?

    Now for something really freaky for all you static type people!

    Lets say you aren’t dealing with products anymore and you are dealing with Cars.

    cars have 4 wheels but they also have color don’t they. Gee it would be nice if we could filter the Cars just like we are able to filter the Products. Wait! We can, we already wrote it!

    We have that “Item_color_filter_spec” class. We could use the ProductFilter class but that class already has a purpose but the “Item_color_filter_spec” is pretty agnostic.

    class Car
        attr_accessor :color
        def initialize(color)
            @color = color
        end
    end
    
    cars = [
        Car.new("Red"),
        Car.new("Blue"),
        Car.new("Red"),
        Car.new("Blue")
    ]
    
    blue_filter = Item_color_filter_spec.new("Blue")
    blue_cars = blue_filter.apply_to(cars)

    Wow talk about reuse!!!

    How is this possible? Well remember types do not exist in Ruby. There are objects but objects are duck typed when you ask them to perform an action. Meaning if it walks like a duck or quacks like a duck it must be a duck. The “Item_color_filter_spec” only cares that it is passed an array of objects. It is then going to iterate over the array of objects and call the “color” accessor on each object to check for equality against the instance variable that was passed in through the constructor. It doesn’t care if the array contains cars, products or both; just that whatever object it is has to have an accessor of "color."

    I know this is a ton on information to digest all at once but I am just very passionate about the Ruby language. I see tremendous potential in its future especially with its entrance into the .Net space through the IronRuby project. I can easily see it over throwing the Visual Basic crowd once it becomes more main stream in the .Net community.

    Posted Mar 30 2008, 10:54 PM by Joe Ocampo with 6 comment(s)
    Filed under: ,
  • Hanging your code out to dry

    I was speaking with Marcus Bratton the other day about code reviews. We both agreed that they are very valuable but finding the time is probably the most difficult aspect of any code review.

    Paired Programming helps to eliminate the need for code reviews but paired programming caries waste of its own when it comes to menial task that need to be accomplished such as HTML.

    We practice an approach we coined “Complexity Based Programming”. The approach allows us to focus our pairing on highly sensitive areas of our code and leave the lower risk task to single individuals. A problem occurs with both approaches in that certain refactoring exercises have failed to be accomplished due to pressure from management or the project in general. So developers begin to cut corners and compromise the integrity of the code base resulting in technical debt. The issue is that the code base isn’t transparent enough that you could readily see this.

    As Agilest we look to our CI server’s state to give us feedback on the health of our code base. We also use tools such as NCover to give us the test coverage state. But this doesn’t necessarily give us our health. It is the equivalent of looking at Lance Armstrong when he had cancer and saying, “This guy’s health is great, look at all the races he is winning.” Little did you know he had cancer growing in his body that is slowly threatening his life?

    Technical Debt is like cancer. If you treat it early on, the health of your software will be tremendous. Let it go or turn a blind eye to it and it will slowly eat its way through every bowl in your code to the point of complete system shut down.

    Tools such as NDepend are like the MRI scanners of medicine. They help to give us a picture into our codebase where we can view low cohesion and high coupling between software entities, which theoretically results in high technical debt. They ease the pains of understanding the COCOMO model and give us high degree of comfort when it comes to our overall health of our system.

    The problem with tools such as NDepend is you have to know how to decipher the data. Don’t get me wrong they do a great job of making it as painless as possible but there is a cost. You have to run the tool! You have to wait for the tool to complete its analysis. You have to be willing to sift through the data. A rewarding exercise but none the less an exercise.

    So we have lots of HiFi options but what LoFi options do we have. Well one that I read about recently peeked my interest.

    As you can see this low friction high value approach is well within anyone’s skill set to produce. What I am recommending is at the end of a given coding session that you simply print out the classes you worked on. Place a string somewhere visible in the lab and hang your code on it. If it is several pages long, tape the pieces of paper on the vertical and hang it out to dry.

    Then developers can walk by the “code line” as tell if you missed a spot or quickly see the 20 page mess you created for the rest of them. Think I am smoking crack? Take a look at a quick test I just did.

    Here is a screen shot of a class file from an awesome OSS project!

    Good_File

    As you can see nice, if you just performed a cursory glance of this code hanging on a line you wouldn’t be too concerned about your teams code.

    Now check this out!

    Bad_Need_Refactoring

    Yes this 30 page monster is ONE class!!!

    Guess which file needed refactoring? If you were to see this hanging on a “code line” would you be worried if you were on this team? If you were a lead or manager what would you do? After all, the test are green!!!

    What??? You didn’t need any fancy tools to discern this premise! I am not trying to take any value away from tools such and NCover or NDepend because they are needed but at the same time light weight approaches are much more valuable from my experience.

    The post I referenced before gives more insight into what to look for as far as margins and typography to determine possible refactoring opportunities.

    In the end all you tree huggers will be screaming fowl but at the same time if you are wasting tons of paper then that may be a indicator that your system is compositionally unstable. So the more you move towards wasting less paper and making the environmentalist happy, the more stable your system will become.

    Disclaimer: There were no trees harmed in the creation of this blog post. :-)

  • Hard to say goodbye

    Well yesterday was my final day at Wachovia.  It was really hard to say goodbye to all the wonderful friends and colleagues I have made there but it was time to move on.  It was really difficult to leave such a great team that has created so many wonderful applications over the last couple of years.  Their Agile mind sets have been cultivated to the point of self sustainability and only great things can come from this group in the future.

    My future path has lead to Rackspace where I will take on the role of an Enterprise Application Architect.  This will be a challenge for me since I really have a distaste for the term Architect as most of the individuals I have met in the past have little to zero exposure in application development.  This lack of experience has resulted in maneuvering this position as more of a governance and standards body, encroaching and decapitating development groups from producing great software under the guise of strategic vision and corporate guidance.  (Can you tell I am a little bitter?)

    My goal is to partner and help the application development groups ALL create great software.  Utilizing the agile and pragmatic tool box to find the best tool for any given job.  In the end, the standards and policies will reveal themselves through the result of working software and ONLY though working software.  Partnership, transparency and open communication will be the foundation of the architecture.  Well it is time to put my money where my mouth is and get er done!

    If anyone has been considering a job in San Antonio, I highly recommend Rackspace.  Their culture and principle help to foster creativity which results in creating a leading IT hosting provider.

  • PTOM: The Open Closed Principle

    The open closed principle is one of the oldest principles of Object Oriented Design. I won’t bore you with the history since you can find countless articles out on the net. But if you want a really comprehensive read please checkout Robert Martin’s excellent write up on the subject.

    The open closed principle can be summoned up in the following statement.

    open/closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification";[1] that is, such an entity can allow its behavior to be modified without altering its source code.

    Sounds easy enough but many developers seem to miss the mark on actually implementing this simple extensible approach. I don’t think it is a matter of skill set as much as I feel that they have never been taught how to approach applying OCP to class design.

    A case study in OCP ignorance

    Scenario: We need a way to filter products based off the color of the product.

    All entities in a software development ecosystem behave a certain behavior that is dependent upon a governed context. In the scenario above you realize that you are going to need a Filter class that accepts a color and then filters all the products that have adhere to that color.

    The filter classes’ responsibility is to filter products (its job) based off the action of filtering by color (its behavior). So your goal is to write a class that will always be able to filter products. (Work with me on this I am trying to get you into a mindset because that is all OCP truly is at its heart.)

    To make this easier I like to tell developers to write the fill in the following template.

     

    The {class} is responsible for {its job} by {action/behavior}

    The ProductFilter is responsible for filtering products by color

     

    Now let’s write our simple class to do this:

    public class ProductFilter
    {
        public IEnumerable<Product> ByColor(IList<Product> products, ProductColor productColor)
        {
            foreach (var product in products)
            {
                if (product.Color == productColor)
                    yield return product;
            }
        }
    }

    As you can see this pretty much does the job of filtering a product based off of color. Pretty simple but imagine if you had the following typical conversation with one of your users.

     

    User: “We need to also be able to filter by size.”

    Developer: “Just size alone or color and size? “

    User: “Umm probably both.”

    Developer: “Great!”

    So let’s use our OCP scenario template again.

    The ProductFilter is responsible for filtering products by color

    The ProductFilter is responsible for filtering products by size

    The ProductFilter is responsible for filtering products by color and size

    Now the code:

    public class ProductFilter
    {
        public IEnumerable<Product> ByColor(IList<Product> products, ProductColor productColor)
        {
            foreach (var product in products)
            {
                if (product.Color == productColor)
                    yield return product;
            }
        }
    
        public IEnumerable<Product> ByColorAndSize(IList<Product> products, 
                                                    ProductColor productColor, 
                                                    ProductSize productSize)
        {
            foreach (var product in products)
            {
                if ((product.Color == productColor) && 
                    (product.Size == productSize))
                    yield return product;
            }
        }
    
        public IEnumerable<Product> BySize(IList<Product> products,
                                            ProductSize productSize)
        {
            foreach (var product in products)
            {
                if ((product.Size == productSize))
                    yield return product;
            }
        }
    }

    This is great but this implementation is violating OCP.

    Where'd we go wrong?

    Let’s revisit again what Robert Martin has to say about OCP.

    Robert Martin says modules that adhere to Open-Closed Principle have 2 primary attributes:

    1. "Open For Extension" - It is possible to extend the behavior of the module as the requirements of the application change (i.e. change the behavior of the module).

    2. "Closed For Modification" - Extending the behavior of the module does not result in the changing of the source code or binary code of the module itself.

    Let’s ask the following question to insure we ARE violating OCP.

    Every time a user asks for a new criteria to filter a product do we have to modify the ProductFilter class?
    Yes! This means it is not CLOSED for modification.

    Every time a user asks for a new criteria to filter a product can we extend the behavior of the ProductFilter class to support this new criteria without opening up the class file again and modifying it?
    No! This means it is not OPEN for extension.

    Solutions

    One of the easiest ways to implement OCP is utilize a template or strategy pattern. If we still allow the Product filter to perform its job of invoking the filtering process we can put the responsibility of how the filtering is accomplished in another class by mixing in a little LSP to accomplish this.

    Here is the template for the ProductFilterSpecification

    public abstract class ProductFilterSpecification
    {
        public IEnumerable<Product> Filter(IList<Product> products)
        {
            return ApplyFilter(products);
        }
    
        protected abstract IEnumerable<Product> ApplyFilter(IList<Product> products);
    }

    Let’s go ahead and create our first criteria, which is a color specification.

    public class ColorFilterSpecification : ProductFilterSpecification
    {
        private readonly ProductColor productColor;
    
        public ColorFilterSpecification(ProductColor productColor)
        {
            this.productColor = productColor;
        }
    
        protected override IEnumerable<Product> ApplyFilter(IList<Product> products)
        {
            foreach (var product in products)
            {
                if (product.Color == productColor)
                    yield return product;
            }
        }
    }

    Now all we have to do is extend the actual ProductFilter class to accept our template ProductFilterSpecification.

    public IEnumerable<Product> By(IList<Product> products, ProductFilterSpecification filterSpecification)
    {
        return filterSpecification.Filter(products);
    }

    OCP goodness!

    So lets make sure we are NOT violating OCP and ask the same questions we did before.

    Every time a user asks for a new criteria to filter a product do we have to modify the ProductFilter class?
    No! Because we have marshaled the behavior of filtering to the ProductFilterSpecification. "Closed for modification"

    Every time a user asks for a new criteria to filter a product can we extend the behavior of the ProductFilter class to support this new criteria without opening up the class file again and modifying it?
    Yes! All we simply have to do is pass in a new ProductFilterSpecification. "Open for extension"

    Now let’s just make sure we haven’t modified too much from our intentions of the ProductFilter. All we simply have to do is validate that our ProductFilter still has the same behavior as before.

    The ProductFilter is responsible for filtering products by color: Yes it still does that!

    The ProductFilter is responsible for filtering products by size: Yes it still does that!

    The ProductFilter is responsible for filtering products by color and size: Yes it still does that!

    If you are a good TDD/BDD practitioner you should already have all these scenarios covered in your Test Suite.

    Here is the final code:

    namespace OCP_Example.Good
    {
        public class ProductFilter
        {
            [Obsolete("This method is obsolete; use method 'By' with ProductFilterSpecification")]
            public IEnumerable<Product> ByColor(IList<Product> products, ProductColor productColor)
            {
                foreach (var product in products)
                {
                    if (product.Color == productColor)
                        yield return product;
                }
            }
    
            [Obsolete("This method is obsolete; use method 'By' with ProductFilterSpecification")]
            public IEnumerable<Product> ByColorAndSize(IList<Product> products,
                                                        ProductColor productColor,
                                                        ProductSize productSize)
            {
                foreach (var product in products)
                {
                    if ((product.Color == productColor) &&
                        (product.Size == productSize))
                        yield return product;
                }
            }
    
            [Obsolete("This method is obsolete; use method 'By' with ProductFilterSpecification")]
            public IEnumerable<Product> BySize(IList<Product> products,
                                                ProductSize productSize)
            {
                foreach (var product in products)
                {
                    if ((product.Size == productSize))
                        yield return product;
                }
            }
    
            public IEnumerable<Product> By(IList<Product> products, ProductFilterSpecification filterSpecification)
            {
                return filterSpecification.Filter(products);
            }
        }
    
        public abstract class ProductFilterSpecification
        {
            public IEnumerable<Product> Filter(IList<Product> products)
            {
                return ApplyFilter(products);
            }
    
            protected abstract IEnumerable<Product> ApplyFilter(IList<Product> products);
        }
    
        public class ColorFilterSpecification : ProductFilterSpecification
        {
            private readonly ProductColor productColor;
    
            public ColorFilterSpecification(ProductColor productColor)
            {
                this.productColor = productColor;
            }
    
            protected override IEnumerable<Product> ApplyFilter(IList<Product> products)
            {
                foreach (var product in products)
                {
                    if (product.Color == productColor)
                        yield return product;
                }
            }
        }
    
        public enum ProductColor
        {
            Blue,
            Yellow,
            Red,
            Gold,
            Brown
        }
    
        public enum ProductSize
        {
            Small, Medium, Large, ReallyBig
        }
    
        public class Product
        {
            public Product(ProductColor color)
            {
                this.Color = color;
            }
    
            public ProductColor Color { get; set; }
    
            public ProductSize Size { get; set; }
        }
    
        [Context]
        public class Filtering_by_color
        {
            private ProductFilter filterProduct;
            private IList<Product> products;
    
            [SetUp]
            public void before_each_spec()
            {
                filterProduct = new ProductFilter();
                products = BuildProducts();
            }
    
            private IList<Product> BuildProducts()
            {
                return new List<Product>
                                   {
                                       new Product(ProductColor.Blue),
                                       new Product(ProductColor.Yellow),
                                       new Product(ProductColor.Yellow),
                                       new Product(ProductColor.Red),
                                       new Product(ProductColor.Blue)
                                   };
    
            }
    
    
            [Specification]
            public void should_filter_by_the_color_given()
            {
                int foundCount = 0;
                foreach (var product in filterProduct.By(products, new ColorFilterSpecification(ProductColor.Blue)))
                {
                    foundCount++;
                }
    
                Assert.That(foundCount, Is.EqualTo(2));
            }
        }
    }
    Posted Mar 21 2008, 07:47 PM by Joe Ocampo with 16 comment(s)
    Filed under:
  • Twhirl is a must for a desktop Twitter client

    If you are Twitterhaulic like Mr Chad Meyer.  I strongly recommend giving Twhirl a whirl!  (Sorry couldn't resist).  I am very impressed with the Adobe Air interface.  Very clean and stylish.

    Twhirl brings together tons of functionality leveraging the twitter API to the max.  I assume that since it is uses the Adobe Air framework that it should run equally impressive on a Mac as well.

    Twhirl

    Posted Mar 18 2008, 11:05 PM by Joe Ocampo with 4 comment(s)
    Filed under:
  • Some people have too much time

    So I gave my two weeks at my current employer around a week ago.  So I really wasn't expecting practical jokes until maybe the end of this week.  Well lets just say my team got creative and managed to wrap my entire cube in foil paper in less then 30 minutes while I was in a meeting today.  Very impressive!

    There attention to detail was astonishing.  They managed to wrap everything from the dry erase markers to every book on my shelf.  They even went so far as to wrap the thumb tacks I have on my board.  Like I said impressive! 

    Here are some images if their work.

    IMG00022

    IMG00023

    IMG00024

    Posted Mar 18 2008, 05:59 PM by Joe Ocampo with 6 comment(s)
    Filed under:
Copyright Los Techies 2007. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems