views:

246

answers:

4

I have some classes that will do something based on some conditions . The conditions are sent as parameters to some methods . My questions is related to ruby coding style :

  • should the conditions be sent as lambdas/blocks , or as some objects that inherit from a condition class ?

  • which is more efficient in terms of OOP ?

Thanks !

+5  A: 

I don't know which is more efficient from an execution time perspective, but blocks are more efficient from a user interface perspective. The person using your method just writes the condition in a block instead of having to define a whole new class, create an instance, and pass it to your method.

Glomek
What about a large project ? Long term projects ?
Geo
Saving yourself time and code on boilerplate stuff is even more important in large projects.
Glomek
+3  A: 

Lambdas are more the Ruby way — and besides that, why define a whole big class for something a simple lambda does just fine? Alternatively, you could pass conditions as a Hash like Rails tends to do.

Chuck
What if I need to setup my classes with more than one condition ? Where would I store all the conditions ? A namespace containing a hash and a whole bunch of conditions as hash values?
Geo
You haven't given any information about the structure of your program beyond that it "will do something based on some conditions," so I have no idea where you'd store anything.
Chuck
+1  A: 

The only case in wich I would use inheritance in this situation, is if the conditions themselves use many common code, that can be completely implemented in the superclass (without need to override anything in the subclases), but the practice of using inheritance for java style interfaces is not usual in Ruby.

In any case, what you are doing is known as inversion of control and strategy patterns, read about that for more information. The key being the (good) decision of making the user of the code decide what the final behaviour of your code would be, as opossed to a configuration parameter or some other sort of branching in the implementation.

krusty.ar
+4  A: 

It's all negligible and it depends on what your actually doing and whether condition objects or procs could be cached, but in general blocks are the Ruby way and they are faster than object creation.

Here's a useless benchmark:

require 'benchmark'

# Useless parent class
class Condition; end

# Useless inheritance.  Duck typing FTW.
class AddCondition < Condition  
  def call
    1 + 1
  end
end

def with_object(condition)
  condition.call
end

def with_block
  yield
end

n = 100000
Benchmark.bm(10) do |x|
  x.report("object:") do
    n.times do; with_object(AddCondition.new); end
  end
  x.report("block:") do
    n.times do; with_block { 1 + 1 };          end
  end
end

And the results:

                user     system      total        real
object:     0.090000   0.000000   0.090000 (  0.087227)
block:      0.060000   0.000000   0.060000 (  0.063736)
Ryan McGeary
We could explain that because creating an object is more expensive than adding two values together.
Geo
@Donovan, it's more than just adding two values together; the block is created as well. There is still overhead in keeping a reference to the stack that is used by the _closure_.
Ryan McGeary
...but yes, Object creation is more expensive.
Ryan McGeary