Living in the Tech Avalanche Generation

A practitioner’s introspective on technology

Archive for the 'DLR' Category

GOF Series: Episode #4 [The Builder Pattern] - In IronRuby

So first up let me say that the balance of this series of posts on patterns will be presented using either C# or IronRuby as languages to express the GOF patterns. Why IronRuby you ask? I have taken to learning IronRuby and Silverlight as deeply as possible this year and decided to spice things up for myself by incorporating it in this series of posts. Never fear I will continue to demonstrate most of the remaining patterns in C# but will from time to time present the patterns in both languages. For now however it’s the Builder Pattern exclusively in IronRuby for the dynamic language enthusiasts.

IronRuby is a dynamically typed, object oriented language and runs in the Dynamic Language Runtime. We will demonstrate the builder pattern using IronRuby, Windows Forms and the Ruby In Steel plugin for Visual Studio.Net 2008.

The goal of the Builder Pattern is to separate or abstract away the construction of an object and to allow the same / common construction process to create the object regardless of its representation. The different representations of the object being constructed are created by concrete builders, specifically designed to create one and only one representation of the product class.

The players in the story:

  • The Director

    • Responsible for constructing the Product object via an interface (mixin in the case of this example using IronRuby) implemented by a concrete builder.
  • The Builder

    • Provides the interface (object in this case) that creates the Product(s) constituent parts and is implemented (included as a mixin with IronRuby) by concrete builders.
  • The Concrete Builder

    • Builds the constituent parts of the Product object.
  • The Product

    • The object whose parts are created by the concrete builder.

BuilderPattern

In C# or other statically typed languages such as java, the builder pattern relies on an abstract class design and inheritance. In IronRuby there is no concept of an interface therefore a different approach is required. We can use a mixin to provide the common behavioural aspects and use arguments to diverge the different concrete builders. The construction of the ‘Product’ is abstracted from the ‘Director’ by the ‘Builder’ and it’s Concrete implementations. To obtain different representations of the Product object new concrete builder objects are created. The Builder Pattern creates it’s Product object in parts via the Director and Builders abstract signatures, however an alternate approach with IronRuby is to substitute the abstract class for a mixin.

#Product
class FootballTeam

    def team_id?()
        self.hash
    end

    def team_type_name?()
        @team_type_name
    end

    def team_properties?()
        @team_properties
    end

    def initialize(name)
        @team_type_name = name
        @team_properties = Hash.new(“Staff Role does not exist!”)
    end

end

#Builder
module FootballTeamBuilder

    attr_reader :name
    attr_writer :name

    def footy_team?()
        @footy_team
    end

    def build_init()
        @footy_team = FootballTeam.new(name)
    end

    def build_players(number_of_players)
        @footy_team.team_properties?["Players"] = number_of_players
    end

    def build_ball_shape(shape_of_ball)
        @footy_team.team_properties?["ballshape"] = shape_of_ball
    end

    def build_games_per_season(number_of_games)
        @footy_team.team_properties?["games"] = number_of_games
    end

    def print_team_details()

        attributes =  “****************************” +
            “******************************\r\n”

        attributes += “Created a #{name} team with the “ +
            “following attributes :\r\n”

        @footy_team.team_properties?.each { |k,v|
            attributes += k.to_s + ” “ + v.to_s + “\r\n” }

        attributes += “\n***************************” +
            “*******************************\n”

        return attributes
    end

end

#Concrete Builder”
class AustralianRulesFootballTeamBuilder 

    include FootballTeamBuilder

    def build_all()
        self.name = “Aussie Rules”
        build_init()
        build_ball_shape(“Oval”)
        build_games_per_season(22)
        build_players(18)
    end

end

#Concrete Builder
class RugbyLeagueFootballTeamBuilder

    include FootballTeamBuilder

   def build_all()
        self.name = “Rugby League”
        build_init()
        build_ball_shape(“Oval”)
        build_games_per_season(24)
        build_players(13)
    end

end

#Concrete Builder
class SoccerFootballTeamBuilder

    include FootballTeamBuilder

    def build_all()
        self.name = “Soccer”
        build_init()
        build_ball_shape(“Round”)
        build_games_per_season(44)
        build_players(11)
    end

end

#Director Class
class GoverningBody

    def build_football_team(football_team_builder)
        unless football_team_builder.is_a?(FootballTeamBuilder)
            fail NoNewMethodError.new(“Cannot build with arguments that are “ +
                “not FootballTeamBuilder class objects”)
        end
        football_team_builder.build_all
    end

end
 
Here’s our form and its form load event method.
 
def Form1_Load(sender, e)

      #new up a Director
      f = GoverningBody.new

      #new up a concrete builder
      soccer_builder = SoccerFootballTeamBuilder.new

      #go again a second time with another builder
      aussie_rules_builder = AustralianRulesFootballTeamBuilder.new

      #go again a second time with another builder
      rugby_league_builder = RugbyLeagueFootballTeamBuilder.new

      #pass the bulders build to the Director
      f.build_football_team(soccer_builder)
      f.build_football_team(aussie_rules_builder)
      f.build_football_team(rugby_league_builder)

      #store the teams and details in arrays
      @team1 = [soccer_builder.footy_team?.team_type_name?,
        soccer_builder.print_team_details]
      @team2 = [aussie_rules_builder.footy_team?.team_type_name?,
        aussie_rules_builder.print_team_details]
      @team3 = [rugby_league_builder.footy_team?.team_type_name?,
        rugby_league_builder.print_team_details]

      self.listBox1.Items.Add(@team1[0])
      self.listBox1.Items.Add(@team2[0])
      self.listBox1.Items.Add(@team3[0])

end
ironruby_builder_ui
ironruby_builder_ide Used in concert with a Windows::Forms application (with some help from Ruby In Steel) we can build the following user interface to demonstrate our Builder(s) in action. The entire code can be found here and includes all the code and presentations from previous episodes in the series. Next in the series is the last of the creational patterns, the Prototype pattern.

Share/Save/Bookmark

3 comments

learning Ruby, IronRuby, the DLR, F# and DSL’s - so much to consider.

ruby I just cant seem to shake Ruby off. Often something comes up in my day to day job that pushes me get serious about Ruby and for as long I have the idea of the Polyglot programmer in the back of my mind, I feel compelled to find out more, even if it’s in microscopic increments. A while back I installed Ruby on my development laptop and played with the interactive console for a while and then predictably got distracted and didn’t follow up for months, until today when I  downloaded NetBeans (Ruby version only) and made a decision, that to understand Domain Languages better I wanted to learn more about a language that would help in that understanding. Ruby is well thought of with respect to being a useful language to ms rubydevelop internal DSL’s and given the other sentiment in this post, I thought it was as good a choice as any. I have been a C# developer since beta of the 1.0 Framework and now that IronRuby and DLR are close at hand, I feel compelled to let my interest in DSL’s, the DLR and learning a dynamic language begin to engulf me to the point that I have been stung into action. So with this in mind I am setting down the path to learn Ruby and hope that this provides a great springboard into taking up IronRuby. Of course the benefit of going deep into another development language and platform I believe will lead to a far richer appreciation of the platform I am currently so deeply invested in.

Last Minute Update:

After re-listening to the HanselMinutes podcast with Robert Pickering on F#, it would appear that F# is a potentially useful language for creating internal DSL’s. I have been thrown a little as I must confess this threw things into debate for a short moment. The argument that kept me down the Ruby path was the relationship that IronRuby has with the DLR and the upside that brings to the learning experience. FsharpYellow Last minute problem solved. Wait hold the press. VbX or Visual Basic 10 is on its way and it too will be a dynamic language. Dilemma. Given that I am almost  equally conversant in VB as C# (I prefer C# by choice), perhaps I should concentrate on F# and let my strong understanding of VB languages to carry me through the transition to VB10 which gives me the DLR leverage? Again I decide to take the Ruby path also because its not a Microsoft Language per se and I think the exposure to Ruby in general will do me good from a platform perspective. I would also like to use Ruby in exploring RESTful Web Services. So I have downloaded NetBeans and installed Ruby 1.8.6 and here I go.

Share/Save/Bookmark

1 comment

« Previous Page

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia