CSC/ECE 517 Fall 2009/wiki2 13 ncs: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
 
(46 intermediate revisions by 2 users not shown)
Line 1: Line 1:
=Introduction=
=Introduction=


Ruby allows much more concise implementations of design patterns for example a single line of code is enough to implement the singleton pattern. We will look at some design patterns and compare the implementation in Ruby vs Java with the goal to determine the following  
[http://en.wikipedia.org/wiki/Ruby_language Ruby] offers more concise implementations of certain [http://en.wikipedia.org/wiki/Design_pattern design patterns] than [http://en.wikipedia.org/wiki/Java_language Java] does. We will look at some design patterns and compare the implementation in '''Ruby vs Java''' with the goal to answer the following:
* Is this typical of dynamic object-oriented languages?


* can dynamic typed languages realize the design patterns more effectively than statically typed languages
* Are there design patterns that any [http://en.wikipedia.org/wiki/Dynamic_language dynamically typed language] can realize better than a [http://en.wikipedia.org/wiki/Type_system statically typed language]?


* Are there instances where a design pattern should be used in a dynamic language than a static language  
* Are there instances when a different pattern should be used in a dynamic language than a static language?


=Design Patterns Analysis=
=Design Patterns in Java vs Ruby=


==Singleton Pattern==
==Singleton Pattern==
Resticting the instantiation of the class to a single pattern.


The implementation of the pattern in JAV And Ruby is identical. We need to  
[http://en.wikipedia.org/wiki/Singleton_pattern Singleton pattern] is a design pattern used to restrict the instantiation of the class to one object.
 
* make the constructor private


The implementation of the pattern involves:
* making the constructor private
* declare a instance variable  
* declare a instance variable  
* implement a <code>getInstance</code> method and make the it thread safe.


* implement a getInstance method and make the it thread safe.
Below is the comparison between singleton class written in Java and Ruby.  
 
<todo> JAVA and ruby singletone examples here. </todo>


However in JAVA we would need to redo these steps for all classes that we want to be singleton whereas in Ruby we can simply include the singleton module that automatically gets us the functionality listed above.  
It is clear that Ruby provides a more concise way of implementing the singleton pattern. Ruby uses the singleton module which automatically provides all the functionality that we need to write manually in Java. By writing <code>include singleton</code> in Ruby, we prevent ourselves from having to repeat writing the same code for each class that we wish to make singleton. In contrast, we need to write the Java class below for every singleton objects we create.  


==Factory Pattern==
'''Java'''
Isolate the code to create an object from the concrete implementation of the class.


In JAVA we typically do something like
  public class SingletonExample {
    // declare instance variable
    private static SingletonExample singletonEx;
   
    // Make the constructor is private
    private SingletonExample() {
    }
    // make this thread safe use synchronize
    synchronize public static SingletonExample getSingletonObject() {
      if (singletonEx == null) {
          singletonEx = new SingletonExample();
      }
      return singletonEx;
    }
  }


<source lang="JAVA">
'''Ruby''' (using singleton module)
interface IObjectFactory {


IGear createObject();
  require singleton
  class SingletonExample
    include singleton
  end


}
==Factory Pattern==
 
[http://en.wikipedia.org/wiki/Factory_pattern Factory pattern] is implemented by isolating the code to create an object from the concrete implementation of the class.  
class ConcreteObjectFactory implements IObjectFactory{
 
IObject createObject() {
 
if ( ... some condition... )
 
return new XObject();
 
else
 
return new YObject();
 
}
 
class ObjectUser {
 
public void doSomething(IObjectFactory factory ) {
 
...
 
IObject my_Object = factory.createObject();
 
...


}
In '''Java''', we typically write a similar code as below: 


}
  interface IObjectFactory {
</source>
    IGear createObject();
We can technically do the exact same thing in Ruby however Ruby being a dynamic language there are no special classes or class methods in ruby. Ruby allows us to rename our factory method to be called new
  }
  class ConcreteObjectFactory implements IObjectFactory{
  IObject createObject() {
    if ( some condition )
        return new XObject();
    else
        return new YObject();
  }
  class ObjectUser {
    public void doSomething(IObjectFactory factory ) {
        IObject my_Object = factory.createObject();
    }
  }


<source lang="Ruby">
We can implement the same code skeleton in Ruby. However, there is no special classes or class methods in Ruby since it is a dynamic language. Instead, '''Ruby''' allows us to rename our factory method to be called new.
class ObjectFactory


def new()  
  class ObjectFactory
    def new()  
      if ( ... some condition )
        return XObject.new()
      else
        return YObject().new()
    end
  end


if ( ... some condition )
return XObject.new()
else
return YObject().new()
end
end
end
<source>
Our client class now becomes:
Our client class now becomes:


<source lang="Ruby">
  class ObjectUser
class ObjectUser
    def doSomething(factory)
      ...
      my_object = factory.new()
      ...
    end
  end


def doSomething(factory )
Ruby lets us redefine the new method and allows us to implement the Factory pattern with a class that looks very much like an ordinary class. The client does not need to know about the special <code>createObject</code> method.


...
==Iterator==
[http://en.wikipedia.org/wiki/Iterator_pattern Iterator pattern] is design pattern used to access the elements of an aggregate object sequentially without exposing its underlying representation.  


my_object = factory.new()
In order to use Iterator pattern, we need:


...
* An iterator declared and initialized to point to the collection
* Write a loop and use the iterator to get the value of the next sequential object in the collection.  


end
In Java, we will need to know the type of objects in the collection and cast them to the right type in order to use them. Whereas in Ruby, iterators are built right in.


end
Here are some examples that show the ease with which we can use iterators in Ruby:
<source>
* Iterates a block of code for each element in the <code>Array</code>


=Iterators= Iterators are design patterns used to access the elements of an aggregate object sequentially without exposing its underlying representation. To use iterators we need
  a = [ 10, 20, 30, 40 ]
  a.each { |element| print "The element is #{element}\n" }


* An iterator declared and initialized to point to the collection
* Iterates code for every line in a file


* Write a loop and use the iterator to get the value of the next sequential objec tin the collection.  
  Thread.list.each { |t| print "Thread: #{t}\n" }


In JAVA we will need to know the type of objects in the collection whereas in ruby iterators are built right in. here are some examples that show the ease with which we can use iterators in Ruby
* Iterates code for all active threads


a = [ 10, 20, 30, 40 ]
  ObjectSpace.each_object { |o| print "Object: #{o}\n" }


a.each { |element| print "The element is #{element}\n" }
* Iterates code for each object in the system


  open("data.txt").each_line { |line| print "The line is #{line}\n" }


Thread.list.each { |t| print "Thread: #{t}\n" }
=Conclusion=


ObjectSpace.each_object { |o| print "Object: #{o}\n" }
Design pattern is a concept that applicable to solve problems regardless of the languages we use to implement the solution. So I cannot think of a case where a specific pattern will be more useful or pertinent to be used in a dynamic language than a static language. However given the features of dynamic languages like Ruby that support meta-programming and reflection via Modules and Mixins and support extending/reopening classes and redefining methods at run time definitely make it easier to implement patterns with fewer lines of code. Ruby lets us hide the details of implementations of design patterns much more effectively. You can make a class a singleton with a simple <code>include Singleton</code> statement. You can make factories that look exactly like ordinary classes. These features in Ruby do make implementing design patterns very easy and let a programmer focus on solving the problem at hand rather than spending time implementing the design patterns.


open("data.txt").each_line { |line| print "The line is #{line}\n" }
=References=


<TODO> Some more patterns
* Gamma, Erich; Richard Helm, Ralph Johnson, and John Vlissides (1995). [http://en.wikipedia.org/wiki/Design_patterns_book ''Design Patterns: Elements of Reusable Object-Oriented Software'']. Addison-Wesley. ISBN 0-201-63361-2.


=Conclusion=
* [http://p-cos.net/documents/dynatype.pdf Dynamic vs Static Typing -- A Pattern-based Analysis] by Pascal Costanza, March 13, 2004.


Design patterns are concepts that are equally applicable to solve problems regardless of the language we use to implement the solution. So I cannot think of a case where a specific apttern will be more useful or pertinent to be used in a dynamic language than a static language. However given the features of dynamic languages like Ruby that support metaprogramming and reflection via Modules and Mixins and support extending/reopening classes and redfining methods at run time definitely make it easier to implement patterns with less lines of code. Ruby lets us hide the details of implementations of design patterns much more effectively. You can make a class a singleton with a simple "include Singleton". You can make factories that look exactly like ordinary classes. You can define visitors with a couple of curly braces. All of this allows you to compress out the details and simply say more interesting things in each line of code.
* Olsen, Russ (2007). [http://www.amazon.com/Design-Patterns-Ruby-Russ-Olsen/dp/0321490452 ''Design Patterns in Ruby'']. Addison-Wesley. ISBN 0-321-49045-2.

Latest revision as of 21:08, 15 October 2009

Introduction

Ruby offers more concise implementations of certain design patterns than Java does. We will look at some design patterns and compare the implementation in Ruby vs Java with the goal to answer the following:

  • Is this typical of dynamic object-oriented languages?
  • Are there instances when a different pattern should be used in a dynamic language than a static language?

Design Patterns in Java vs Ruby

Singleton Pattern

Singleton pattern is a design pattern used to restrict the instantiation of the class to one object.

The implementation of the pattern involves:

  • making the constructor private
  • declare a instance variable
  • implement a getInstance method and make the it thread safe.

Below is the comparison between singleton class written in Java and Ruby.

It is clear that Ruby provides a more concise way of implementing the singleton pattern. Ruby uses the singleton module which automatically provides all the functionality that we need to write manually in Java. By writing include singleton in Ruby, we prevent ourselves from having to repeat writing the same code for each class that we wish to make singleton. In contrast, we need to write the Java class below for every singleton objects we create.

Java

 public class SingletonExample { 
    // declare instance variable
    private static SingletonExample singletonEx; 
    
    // Make the constructor is private
    private SingletonExample() {
    }
    // make this thread safe use synchronize
    synchronize public static SingletonExample getSingletonObject() {
      if (singletonEx == null) {
         singletonEx = new SingletonExample();
      }
      return singletonEx;
    }
 }

Ruby (using singleton module)

 require singleton
 class SingletonExample
   include singleton
 end

Factory Pattern

Factory pattern is implemented by isolating the code to create an object from the concrete implementation of the class.

In Java, we typically write a similar code as below:

 interface IObjectFactory {
    IGear createObject();
 }
 class ConcreteObjectFactory implements IObjectFactory{
 IObject createObject() {
    if ( some condition )
       return new XObject();
    else
       return new YObject();
 }
 class ObjectUser {
    public void doSomething(IObjectFactory factory ) {
       IObject my_Object = factory.createObject();
    }
 }

We can implement the same code skeleton in Ruby. However, there is no special classes or class methods in Ruby since it is a dynamic language. Instead, Ruby allows us to rename our factory method to be called new.

 class ObjectFactory
   def new() 
     if ( ... some condition )
        return XObject.new()
     else
        return YObject().new()
   end
 end

Our client class now becomes:

 class ObjectUser 
   def doSomething(factory)
     ...
     my_object = factory.new()
     ...
   end
 end

Ruby lets us redefine the new method and allows us to implement the Factory pattern with a class that looks very much like an ordinary class. The client does not need to know about the special createObject method.

Iterator

Iterator pattern is design pattern used to access the elements of an aggregate object sequentially without exposing its underlying representation.

In order to use Iterator pattern, we need:

  • An iterator declared and initialized to point to the collection
  • Write a loop and use the iterator to get the value of the next sequential object in the collection.

In Java, we will need to know the type of objects in the collection and cast them to the right type in order to use them. Whereas in Ruby, iterators are built right in.

Here are some examples that show the ease with which we can use iterators in Ruby:

  • Iterates a block of code for each element in the Array
 a = [ 10, 20, 30, 40 ]
 a.each { |element| print "The element is #{element}\n" }
  • Iterates code for every line in a file
 Thread.list.each { |t| print "Thread: #{t}\n" }
  • Iterates code for all active threads
 ObjectSpace.each_object { |o| print "Object: #{o}\n" }
  • Iterates code for each object in the system
 open("data.txt").each_line { |line| print "The line is #{line}\n" }

Conclusion

Design pattern is a concept that applicable to solve problems regardless of the languages we use to implement the solution. So I cannot think of a case where a specific pattern will be more useful or pertinent to be used in a dynamic language than a static language. However given the features of dynamic languages like Ruby that support meta-programming and reflection via Modules and Mixins and support extending/reopening classes and redefining methods at run time definitely make it easier to implement patterns with fewer lines of code. Ruby lets us hide the details of implementations of design patterns much more effectively. You can make a class a singleton with a simple include Singleton statement. You can make factories that look exactly like ordinary classes. These features in Ruby do make implementing design patterns very easy and let a programmer focus on solving the problem at hand rather than spending time implementing the design patterns.

References