This one is rough, so we will go step by step. This principle states that classes should be closed against modification, but open for extension. In simple words, classes should be able to extend its behavior, without modifying existing code that can potentially affect other classes.

Metaprogramming and the Abstract factory pattern can help us in this situations. Imagine that we have a GarageBand class that depends on a DrumKit class with many subclasses which are initialized depending on the @style variable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class GarageBand
  #... rest of the class omitted

  def drums
   drum_set =
    case @style
    when :jazz
      JazzDrumKit.new()
    when :metal
      MetalDrumKit.new()
    when :pop
      PopDrumKit.new()
    end          
  end
end

But, what happen in the future when we need to add new subclasses like, Latin, Funk or Ethnic kits. We will need to modify a super class and add more case statements. This is like goto declarations and will become ugly code.

The key of the Abstract factory pattern is that it can instantiate objects whose subclass isn’t known until runtime. Here is how it look like:

1
2
3
4
5
6
7
8
9
10
11
12
class GarageBand
#... rest of the class omitted

  def drums
    drum_class =
    begin
     @style.to_s.classify.constantize
    rescue NameError
     'Invalid style'
    end  
    drum_set = drum_class.send(:new,self)  
  end
end

Whit this approach we can add as many new subclasses and there is no need to modify the GarageBand class. This class is open for extension but closed against modification.