CSC/ECE 517 Fall 2010/ch7 7a ed: Difference between revisions
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
=Novel Implementations of Design Patterns in Dynamic Languages= | =Novel Implementations of Design Patterns in Dynamic Languages= | ||
Dynamic languages such as Ruby and Javascript allow many novel implementations of the design patterns we cover in previous chapters, which would not be possible or feasible in complied languages such as Java and C. Language features only available in dynamic languages give developers an increased amount of flexibility in how they can implement design patterns. These language features and the some examples of the implementations they allow are detailed in this section. | Dynamic languages such as Ruby and Javascript allow many novel implementations of the design patterns we cover in previous chapters, which would not be possible or feasible in complied languages such as Java and C. Language features only available in dynamic languages give developers an increased amount of flexibility in how they can implement design patterns. These language features and the some examples of the implementations they allow are detailed in this section, with a focus on implementations in the Ruby language. | ||
=Language Features= | =Language Features= | ||
Line 11: | Line 11: | ||
Closures are a feature that allow blocks of code to be passed around as arguments to functions. Closures are also known as lambdas or procs in Ruby. The code in a closure has access to all variables in the scope where it was created, and it can have additional data passed in as parameters to the closure from the caller. [http://jibbering.com/faq/notes/closures/] | Closures are a feature that allow blocks of code to be passed around as arguments to functions. Closures are also known as lambdas or procs in Ruby. The code in a closure has access to all variables in the scope where it was created, and it can have additional data passed in as parameters to the closure from the caller. [http://jibbering.com/faq/notes/closures/] | ||
== | ==eval== | ||
In dynamic languages, any arbitrary code can be executed dynamically at runtime. This can include code that is generated from user input. This is a subset of metaprogramming. Eval is explored further in section 3E. | |||
In dynamic languages, | ==Reflection== | ||
Reflection is the ability of a language to inspect the different methods exist on an object. Reflection is explored further in section 1C. | |||
==Runtime Object Modification== | |||
Dynamic languages allow metaprogramming, or the ability of the program to modify itself, creating or adding to objects and classes. This is explored further in section 4G. | |||
==Dynamically Named Methods== | |||
Dynamic languages often allow objects to handle method calls to methods that do not exist. In ruby, method_missing provides this functionality. | |||
=Design Pattern Implementations= | |||
==Strategy Pattern== | |||
Using '''closures''', dynamic languages are able to simply pass in blocks of code that implement the strategy to be used. | |||
For example, the Ruby sort method accepts a closure block, with which you can pass in the sorting metric. | |||
>> list = ["10", "2", "5"] | |||
=> ["10", "2", "5"] | |||
>> list.sort{|a, b| a.length <=> b.length} # length strategy | |||
=> ["5", "2", "10"] | |||
>> list.sort{|a, b| a.to_i <=> b.to_i} # integer strategy | |||
=> ["2", "5", "10"] | |||
>> list.sort{|a, b| a <=> b} # string strategy | |||
=> ["10", "2", "5"] | |||
These strategies can also be stored and used later or chosen based on a conditional. For example: | |||
length_strategy = lambda {|a, b| a.length <=> b.length} | |||
list.sort(&length_strategy) | |||
==Command Pattern== | |||
Using '''eval''' or '''send''', one can implement the command pattern. This is implemented in Ruby on Rails' ActionController. A web application user enters a URL, which is the a form of a command. The URL typically contains the name of the controller and the action (command) that is to be executed on that controller. | |||
The application checks to see if the a method with the action name exists in the controller and runs that method if so. Checking to see if the method exists is an example of class '''reflection'''. Without this language capability, the controller would have to keep an external list of its actions. | |||
==Object Relational Mapping== | |||
Ruby on Rails' ActiveRecord implementation of the Object Relational Mapping (ORM) pattern uses '''runtime object modification''' and '''dynamically named methods''' to achieve a very clean implementation. | |||
===Runtime Object Modification=== | |||
Every ActiveRecord model contains accessors for each field in the corresponding database table. These accessors are created at runtime and do not require the programmer to manually create and update accessors for each field in the database. It does this by inspecting the database and adding accessor methods to the model's class for each field. | |||
[http://ar.rubyonrails.org] This allows for much cleaner model code. | |||
===Dynamically Named Methods=== | |||
By overriding Ruby's method_missing method in models, ActiveRecord can look for certain patterns in method calls on the models where no method is explicitly defined. One such example is <code>find_all_by_FIELD_NAME()</code>, where FIELD_NAME can be any field in the model's database table. Using these convenience methods, the models can be less cluttered, and Rails developers can write code that is easier to read. | |||
=Conclusion= | |||
Dynamic programming languages have several features which allow for novel ways to implement existing design patterns. These implementations are simpler and far less tedious than their compiled language counterparts. | |||
=References= | =References= | ||
# Wikipedia. Dynamic programming language. 2 October 2010. http://en.wikipedia.org/wiki/Dynamic_programming_language | # Wikipedia. Dynamic programming language. 2 October 2010. http://en.wikipedia.org/wiki/Dynamic_programming_language | ||
# Cornford, Richard. Javascript Closures. March 2004. http://jibbering.com/faq/notes/closures/ | # Cornford, Richard. Javascript Closures. March 2004. http://jibbering.com/faq/notes/closures | ||
# 37Signals. Active Record — Object-relation mapping put on rails. 27 June 2008. http://ar.rubyonrails.org |
Latest revision as of 06:41, 2 December 2010
Novel Implementations of Design Patterns in Dynamic Languages
Dynamic languages such as Ruby and Javascript allow many novel implementations of the design patterns we cover in previous chapters, which would not be possible or feasible in complied languages such as Java and C. Language features only available in dynamic languages give developers an increased amount of flexibility in how they can implement design patterns. These language features and the some examples of the implementations they allow are detailed in this section, with a focus on implementations in the Ruby language.
Language Features
"These behaviors can be emulated in nearly any language of sufficient complexity, but dynamic languages provide direct tools to make use of them" [1]. Some of the most helpful tools are as follows:
Closures
Closures are a feature that allow blocks of code to be passed around as arguments to functions. Closures are also known as lambdas or procs in Ruby. The code in a closure has access to all variables in the scope where it was created, and it can have additional data passed in as parameters to the closure from the caller. [2]
eval
In dynamic languages, any arbitrary code can be executed dynamically at runtime. This can include code that is generated from user input. This is a subset of metaprogramming. Eval is explored further in section 3E.
Reflection
Reflection is the ability of a language to inspect the different methods exist on an object. Reflection is explored further in section 1C.
Runtime Object Modification
Dynamic languages allow metaprogramming, or the ability of the program to modify itself, creating or adding to objects and classes. This is explored further in section 4G.
Dynamically Named Methods
Dynamic languages often allow objects to handle method calls to methods that do not exist. In ruby, method_missing provides this functionality.
Design Pattern Implementations
Strategy Pattern
Using closures, dynamic languages are able to simply pass in blocks of code that implement the strategy to be used.
For example, the Ruby sort method accepts a closure block, with which you can pass in the sorting metric.
>> list = ["10", "2", "5"] => ["10", "2", "5"] >> list.sort{|a, b| a.length <=> b.length} # length strategy => ["5", "2", "10"] >> list.sort{|a, b| a.to_i <=> b.to_i} # integer strategy => ["2", "5", "10"] >> list.sort{|a, b| a <=> b} # string strategy => ["10", "2", "5"]
These strategies can also be stored and used later or chosen based on a conditional. For example:
length_strategy = lambda {|a, b| a.length <=> b.length} list.sort(&length_strategy)
Command Pattern
Using eval or send, one can implement the command pattern. This is implemented in Ruby on Rails' ActionController. A web application user enters a URL, which is the a form of a command. The URL typically contains the name of the controller and the action (command) that is to be executed on that controller.
The application checks to see if the a method with the action name exists in the controller and runs that method if so. Checking to see if the method exists is an example of class reflection. Without this language capability, the controller would have to keep an external list of its actions.
Object Relational Mapping
Ruby on Rails' ActiveRecord implementation of the Object Relational Mapping (ORM) pattern uses runtime object modification and dynamically named methods to achieve a very clean implementation.
Runtime Object Modification
Every ActiveRecord model contains accessors for each field in the corresponding database table. These accessors are created at runtime and do not require the programmer to manually create and update accessors for each field in the database. It does this by inspecting the database and adding accessor methods to the model's class for each field. [3] This allows for much cleaner model code.
Dynamically Named Methods
By overriding Ruby's method_missing method in models, ActiveRecord can look for certain patterns in method calls on the models where no method is explicitly defined. One such example is find_all_by_FIELD_NAME()
, where FIELD_NAME can be any field in the model's database table. Using these convenience methods, the models can be less cluttered, and Rails developers can write code that is easier to read.
Conclusion
Dynamic programming languages have several features which allow for novel ways to implement existing design patterns. These implementations are simpler and far less tedious than their compiled language counterparts.
References
- Wikipedia. Dynamic programming language. 2 October 2010. http://en.wikipedia.org/wiki/Dynamic_programming_language
- Cornford, Richard. Javascript Closures. March 2004. http://jibbering.com/faq/notes/closures
- 37Signals. Active Record — Object-relation mapping put on rails. 27 June 2008. http://ar.rubyonrails.org