Showing posts with label strategy. Show all posts
Showing posts with label strategy. Show all posts

Monday, October 1, 2012

Favor Composition over Inheritance - Conclusion

It all come down to the word "change". Change is the key to decided which one should be inherited and which one should be composite.

The base class Duck has-a name, and swim. So does the MallardDuck which inherited from Duck. It is-a Duck after all. MallardDuck also has-a behavior fly and quack.  But these two behavior are not inherited from Duck thou. Both are composite part of MallardDuck.

What make swim, different from fly? Can we consider swim as a behavior, and implement it in the same way as fly?
The answer is in the word "change". The swim does not change. All subclass has the same swim method. While, fly and quack are not the same in all subclass. Of course, nothing prevent us from implementing swim in the same way as we did with fly. But why do we need to do more complicate code if we don't need too. Inherited would work great for swim.

Can we just override and make change in the subclass as needed? 
Yes, we can. However, if the change are the same in two different subclass, then we code duplication! Consider, both MallardDuck and RedheadDuck can fly with wing. That means we would have to make the same change to MallardDuck and RedheadDuck. By implement the part of the duck that can be changed into module, we can pick and choose what behavior we want. You can see in the part 3, it is make much more sense, easily to understand and maintain.

Object vs Module, which one should I use?
Obviously, if you want ability to change the behavior at run time, you would have to use object approach. But that is not the only advantage object approach has over module. The object give you much control over namespace and help you avoid name collision.

Consider the module implementation, when we include the module, all the methods are defined in the same name space. Which means it's possible we can get name collision.  Specially, if the module are large, and very complicated, say 10 or may be 20 methods defined. It's possible two modules have the same method name but doing different thing. For example, if we happen to include both Behavior::FlyWithWing and Behavior::NotFly, one of the fly method will get overridden.

On the other hand, if we implement using objects, it's name collision won't happen, because all the methods would be contained in the object itself.

For the problem that is not so complex, the module would be a good choice, because it's easier to understand, and manage. Beside, with good naming convention, the name collision can be avoid easily.

Knowing when to use inheritance or composition is one of the most important skill to learn. What every way you choose to implement, separated part of the object that can be change, and use them to compost the new object is the key to handling change. If it's not change, just inherited it!

Always, start with the simple solution, but also know where are you heading help you make the right choice.

Thanks for reading this far. :)

Sunday, September 30, 2012

Favor Composition over Inheritance - Part 4

Previously in the programming series posts, I show how to use module to implement composition. One limitation of using module is, duck can not change behavior at run time. Such as MallardDuck can only fly with wing. How can we allow an instance of duck to change their behavior at run time? An answer is using object instead of module.

 To support this feature, the base class, now, hold all the behaviors  implemented for subclass. That quite different from using module, which the base class know nothing about subclass behaviors at all.
class Duck
  attr_reader :name
  attr_accessor :fly_behavior, :quack_behavior
  def initialize
    @name = "mallard duck"
    @fly_behavior = nil
    @quack_behavior = nil
  end

  def fly
    fly_behavior.fly
  end

  def quack
    quack_behavior.quack
  end
end

In this case, the base class by default has no behaviors. It's the subclass job to create, and assign default behaviors of the subclass when initiate an instance. For example, MallardDuck default behavior for flying is fly with wing, etc.
require './duck'
require './behavior/fly_with_wing'
require './behavior/quack_loud'

class MallardDuck < Duck
  def initialize
    @name = "mallard duck"
    @fly_behavior = Behavior::FlyWithWing.new
    @quack_behavior = Behavior::QuackLoud.new
  end
end

Saturday, September 29, 2012

Favor Composition Over Inheritance - Part 3





In part 2, I implement Duck with fly behavior. Now, I am going show how to add new behavior, quack . Let say, I want to add two quack behavior, Behavior::QuackLoud and Behavior::QuackSilent. Similar to fly behavior, each behavior is implemented in module, and put under directory [behavior].

...
 |+[behavior]
   |-...
   |-quack_loud.rb
   |-quack_silent.rb
The Behavior::QuackLoud is implement in quack_loud.rb module as shown here:
module Behavior
  module QuackLoud
    def quack
      puts "quack loud"
    end
  end
end
It's not hard to see how Behavior::QuackSilent is implemented.

Now, I want MallardDuck, which already be able to fly with wing, also can quack loudly. All I have to do is include Behavior::QuackLoud in the class MallardDuck. Of course, I need to require appropriate file:
require './duck'
require './behavior/fly_with_wing'
require './behavior/quack_loud'

class MallardDuck < Duck
  include Behavior::FlyWithWing
  include Behavior::QuackLoud
  ...
end

In the same way, I can define duck that can fly but not quack, or duck that can not fly but quack loudly. Different duck with different behaviors can be defined by including appropriate behavior module. A particular behavior defined in one place, and can be easily shared between different class of duck. As you can see, it's easy to understand, implement, and maintain.

Let recap a bit: Share behavior of all kind of Duck are implemented in base class. Then different behavior are separated out into modules, and then get included into class definition when that class need  it. We can say, duck class is composed with different behavior module.

Here, how the composition is done in ruby using module!

Next time, I will use different way of implementation to allow a duck to change behavior during run time. It's would be fun!

Favor Composition Over Inheritance - Part 2

In previous post I show how to do composition using Ruby Module. It's quite natural and easy to do. I also mention Ruby Convention on class/modules code organize, but I have not made it clear what it really means. Let get into this topic today. If you have not read the previous post , I recommend skim though it to get the idea.

By following ruby convention, each class have it own separated files. The namespace become a sub-directory, which contains module files. In this case directory behavior contains different fly behavior
+[duck_app]
 |-duck_app.rb
 |-duck.rb
 |-mallard_duck.rb
 |-redhead_duck.rb
 |-toy_duck.rb
 |+[behavior]
   |-fly_with_wing.rb
   |-not_fly.rb

The duck_app.rb is the main application which using ducks class. Here how it's look like:
require './mallard_duck'
require './redhead_duck'
require './toy_duck'

ducks = [MallarDuck.new, RedheadDuck.new, ToyDuck.new]
p ducks.map(&:name)
ducks.each(&:swim)
ducks.each(&:fly)
In this case, we simply ask their name. Let they swim and fly.

In order to use class MallardDuck, we have to tell ruby where is the MallardDuck definition are, by using "require" statement as showed. Similarly, in the mallard_duck, which reference to Duck, and Behavior::FlyWithWing symbols, we use 'require' statement to load the symbols definition:
require './duck'
require './behavior/fly_with_wing'

class MallardDuck < Duck
  include Behavior::FlyWithWing
  ...
end

With this convention, the code is organized into well defined places, which make it easy to find things.

That's it, for today!

Thursday, September 27, 2012

Favor Composition Over Inheritance

I have been reading "Head First Design Patterns" [1], which used Java to construct all examples. It's made me wonder what would it take to implement same pattern in Ruby. What would be the different, specially Ruby is not "type" language at all.

The first pattern that I am going to try is "Strategy" pattern. The principal behind "Strategy" pattern is "Favor composition over inheritance". It's interesting to see that at least two different way we can implement this principal in Ruby. One using module, another using class.

Let use the same design in the book, the duck design. Since all duck would have name, and can swim. The Duck base class would contain attribute name and method swim(). All duck swim, you know.
class Duck 
  attr_reader :name
  def initialize
    @name = "simple duck"
  end

  def swim
    puts "All duck can swim."
  end
end

However, not all duck are fly in the same way. MallarDuck and RedheadDuck will be able to fly with wing, while ToyDuck won't be able to quack or fly at all. To be able to share same behavior between MallardDuck and RedheadDuck, we create a module under then namespace Behavior
module Behavior
  module FlyWithWing
    def fly
      puts "Fly with wing"
    end
  end
end

module Behavior
  module NotFly
    def fly
      puts "no way I can fly"
    end
  end
end

class MallardDuck < Duck
  include Behavior::FlyWithWing

  def initialize
    @name = 'Mallard duck'
  end
end

class RedheadDuck < Duck
  include Behavior::FlyWithWing

  def initialize
    @name = 'Redhead duck'
  end
end

class ToyDuck < Duck
  include Behavior::NotFly
  def initialize
    @name = 'Toy duck'
  end
end

irb> ducks = [MallardDuck.new, RedHeadDuck.new, ToyDuck.new]
irb> ducks.each(&:fly)
Fly with wing
Fly with wing
no way I can fly
With proper directory setup, and follow convention. Ruby will be able to find the file that contain module and include it properly with no configuration at all.

In this case, each module would contain in each file under directory "behavior". By ruby convention, filename would have to match the module name. That mean the file would be name "fly_with_wing.rb", and "not_fly.rb"

We can also do the same with "quack" behavior, say Behavior::QuackLoudly, Behavior::NotQuack, etc.

As you can see, we can use ruby module to implement composition quite efficiently. It's seem natural to me to use module to break down object into different component and composed them.

Next time, I will describe more in detail of the implementation.

[1] Head First Design Patterns, Eric Freema, Elisabeth Freeman, O'Reilly 2004.