Archive for the ‘design’ Category

blocks parameters list and metaprogramming

I have been playing with a Aquarium, the new AOP framework in Ruby. A point advice is create for example :

before :type=>A, :method=>:foo do |execution_point, *args|
  self.some_method() # call a class method from A
  other_method()     # call other class method from A
  # call a method from the caller object
  execution_point.context.advised_object.bar()  
end 

The DSL is nice but i found the access to the caller object is a tedious. I prefer something like this :

before :type=>A, :method=>:foo do |execution_point,this , *args|
  self.some_method() # call a class method from A
  other_method()     # call other class method from A
  # call a method from the caller object
  this.bar()  
end 

Dean Wampier think thats would be great if the user could specify combinations
like these:

|join_point, the_self, *method_args|
|join_point|
|the_self|
|the_self, *method_args|
|join_point, the_self|
|join_point, *method_args|

But the point is that the advices is create in the “definition time class” using some code generation at
runtime. How can i know the arity of the argument list.

module Kernel  
  def before (name, &block) 
    define_method(name){ 
      if block.arity == 1
        yield :only_one
      elsif  block.arity == 2
        yield :one,:two
      elsif block.arity == -2
        yield :one, :a , :splater, :argument
      end
    }
  end
end

class A  
  before :foo do |first|   
    puts first
  end
end

a = A.new 
a.foo

class A
  before :foo do |first , second|
    puts second
  end
end

a2 = A.new 
a2.foo

class A
  before :foo do |first , *splat_arg| 
    puts splat_arg
  end
end

a3 = A.new 
a3.foo

Thats great, the block can be acceded because its a Proc class. Now we can predict the number of parameter of that the user has write and create a more friendly DSL.

Ramdon tips for Rails

  • MVC as a constraint
  • Over do MVC
  • Don’t put any code in the view
  • Don’t do any DB operation in the controller
  • Set Default Values in Methods : Avoid unexpected behaviour.
  • Simple Hash as Default Method Parameter : This form allows you to add functionality to methods without breaking existing calls
  • Helpers are hard to test, its will turn Rails into PHP

A good API must :

 Ruby have a very good set of features to desing API and thats why rails and other pseudo-DSLs make us feel really comfortable.  Closures/code blocks,  metaprogramming and method_missing method are the mos important.

I have been watching Joshua bloch track “how to design a good api and why matters” , its a really iteresant video. I must think about some points :

  • Easy to learn
  • Easy to use, even w/o doc
  • Hard to misuse
  • Easy to read and maintain code that uses it
  • Sufficiently powerfil to satisfy requirements
  • Easy to extend
  • Appropriate to audience – no such thing as a “perfect” API for everyone

When we design an API we must :

  • Start with a small (1 page) spec
  • TDD for API design
  • Minimize accessibilty – maximize information hiding
  • Class Design
    • Minimize mutability
    • If mutable, keep the state space small and well defined
  • Method design
    • Spending time on the API to make it easier is more important than performance
    • Provide programmatic access to all data available in String form
    • Overload with care – no two with same number of args
    • Use consistent parameter ordering
    • Don’t use exceptions for control flow, only for errors