Skip to content

Instantly share code, notes, and snippets.

@rebo
Created September 4, 2012 15:01
Show Gist options
  • Save rebo/3621999 to your computer and use it in GitHub Desktop.
Save rebo/3621999 to your computer and use it in GitHub Desktop.
DCI and Simple Facades
#
# Comparison of a dumb facade implementation to #extend.
# The principle advantage is that with caching it might be quicker that #extend,
# and it isolates the data_object so no behaviour
# changes persist after a context is finished.
#
require 'benchmark'
require 'singleton'
module Runner
def run
Math.tan(Math::PI / 4)
end
end
class IncludeUser
include Runner
end
class User
def initiailize
@one = :one
@two = :two
@three = :three
end
end
class DCIClassCache
include Singleton
attr_reader :cache
def initialize
@cache = {}
end
def get_rolified_class(object, role)
klass = object.class
role_name = role.name
if @cache[klass] && @cache[klass][role_name]
rolified_class = @cache[klass][role_name]
else
rolified_class = Class.new(object.class).send :include, role
@cache[klass] ||= {}
@cache[klass][role_name] = rolified_class
end
end
end
Benchmark.bm do |bench|
3.times do
bench.report('#include') do
1000000.times do
user = IncludeUser.new
user.run
end
end
end
end
Benchmark.bm do |bench|
3.times do
bench.report('#extend') do
1000000.times do
user = User.new
user.extend Runner
user.run
end
end
end
end
Benchmark.bm do |bench|
3.times do
bench.report('dumb_facade_with_cache') do
1000000.times do
user = User.new
# Get a 'template' class from a cache if it has been used before
klass = DCIClassCache.instance.get_rolified_class( user , Runner)
# instanciate facade object
basic_facade = klass.new
# copy the object's instance variables to the facade
user.instance_variables.each do |ivar_name|
ivar = user.instance_variable_get(ivar_name)
basic_facade.instance_variable_set(ivar_name, ivar)
end
basic_facade.run
# copy the facade's instance variables to the data object
basic_facade.instance_variables.each do |ivar_name|
ivar = basic_facade.instance_variable_get(ivar_name)
user.instance_variable_set(ivar_name, ivar)
end
end
end
end
end
Benchmark.bm do |bench|
3.times do
bench.report('dumb_facade_without_cache') do
1000000.times do
user = User.new
# Get a 'template' class from a cache if it has been used before
# klass = DCIClassCache.instance.get_rolified_class( user , Runner)
# instanciate facade object
basic_facade = Class.new(user.class).send(:include, Runner).new
# copy the object's instance variables to the facade
user.instance_variables.each do |ivar_name|
ivar = user.instance_variable_get(ivar_name)
basic_facade.instance_variable_set(ivar_name, ivar)
end
basic_facade.run
# copy the facade's instance variables back to the object
basic_facade.instance_variables.each do |ivar_name|
ivar = basic_facade.instance_variable_get(ivar_name)
user.instance_variable_set(ivar_name, ivar)
end
end
end
end
end
# Benchmarks ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.3.0]
#
# user system total real
# #include 0.700000 0.000000 0.700000 ( 0.719030)
# #include 0.640000 0.000000 0.640000 ( 0.640602)
# #include 0.640000 0.000000 0.640000 ( 0.638456)
# user system total real
# #extend 3.830000 0.010000 3.840000 ( 3.875515)
# #extend 3.900000 0.000000 3.900000 ( 3.958716)
# #extend 3.810000 0.010000 3.820000 ( 3.835442)
# user system total real
# dumb_facade_with_cache 2.500000 0.000000 2.500000 ( 2.658489)
# dumb_facade_with_cache 2.330000 0.010000 2.340000 ( 2.335742)
# dumb_facade_with_cache 2.340000 0.000000 2.340000 ( 2.352163)
# user system total real
# dumb_facade_without_cache 7.450000 0.010000 7.460000 ( 7.683932)
# dumb_facade_without_cache 7.370000 0.010000 7.380000 ( 7.519060)
# dumb_facade_without_cache 7.360000 0.010000 7.370000 ( 7.559644)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment