The Artima Developer Community
Sponsored Link

Ruby Code & Style
Modular Architectures with Ruby
by Jack Herrington
October 10, 2005

<<  Page 3 of 4  >>

Advertisement

Making It Modular

All right, enough playing around with what the API should look like. It’s time to make it modular by creating a mods directory and taking parts of the original large file and chopping it up into a module for each format type.

Shown below is the source for the RDF module. It contains both the parser and the parser factory.

class RDFParser < Parser
  def parse( xml )
    # Parse the XML up and return some known format
    return nil
  end
end

class RDFFactory < ParserFactory
  def get_type()
    return "RDF"
  end
  def create()
    return RDFParser.new()
  end
end

ParserFactory.add_factory( RDFFactory )

The second file is the RSS parser.

class RSSParser < Parser
  def parse( xml )
    # Parse the XML up and return some known format
    return nil
  end
end

class RSSFactory < ParserFactory
  def get_type()
    return "RSS"
  end
  def create()
    return RSSParser.new()
  end
end

ParserFactory.add_factory( RSSFactory )

Then comes the updated modules library.

class ParserFactory
  def get_type()
    return ""
  end
  def create()
    return nil
  end

  @@factories = []

  def ParserFactory.add_factory( p )
    @@factories.push( p )
  end

  def ParserFactory.factories()
    return @@factories
  end

  def ParserFactory.parser_for( type )
    @@factories.each { |pfc|
      pf = pfc.new()
      if pf.get_type() == type 
        return pf.create()
      end
    }
    return nil
  end

  def ParserFactory.load( dirname )
    Dir.open( dirname ).each { |fn|
      next unless ( fn =~ /[.]rb$/ )
      require "#{dirname}/#{fn}"
    }
  end
end

class Parser
  def parse( xml )
    return nil
  end
end

The important part comes with the load class method which loads the modules from a specified directory. The loading is done with the require function that reads the code in from the module.

Figure 3 shows the relationship between the module files and the classes they contain and the classes in the host application.

Figure 3: The relationship between the files and the classes.
Figure 3. The relationship between the files and the classes

One thing that does trouble me is this statement to register each factory:

ParserFactory.add_factory( RDFFactory )

In Ruby we can do better because classes actually get notified when they are subclassed. No kidding. The code that follows replaces the add_factory method with a method called inherited which is a Ruby standard method.

class ParserFactory
  ...
  def ParserFactory.inherited( pf )
    @@factories.push( pf )
  end
  ...
end

The inherited method is called when one class inherits from another. The super class’s inherited function is called with the object for the subclass.

With that change the calls to add_factory can be removed.

<<  Page 3 of 4  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us