Skip to content

Instantly share code, notes, and snippets.

@perplexes
Forked from nkallen/MODULARITY_OLYMPICS.markdown
Created February 15, 2010 21:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save perplexes/305033 to your computer and use it in GitHub Desktop.
Save perplexes/305033 to your computer and use it in GitHub Desktop.
I want to turn this into a programming contest. Everyone should do this using their favorite technique and language. But, I want to add three more challenges (that admittedly stack the deck in my favor).
1. create a stats collecting query decorate that measures the time it takes to execute the query
(assume you have a stats object that responds to #measure and takes a block: stats.measure { sleep 1.second }
2. read "configuration" from a hash like:
{ :timeout => 1.second, :stats => true }
that adds the timeout and stats decorators to the factory if present in the hash, otherwise not.
3. at the end write a program that REVERSES the order of the decorators. So if you did Timeout(Stats(Query)) make it Stats(Timeout(Query)). Note that you must do this programmatically so write a generic decorator reversing function. You may expand the proxy interface to have a method called "underlying", "delegate" or some such.
The contest is: do this in your language in as "elegant" a way as you like. The goal is clarity and modularity.
query_factory = MemoizingQueryFactory.new(TimingOutQueryFactory.new(Query, 1.second))
query_evaluator = QueryEvaluator.new(ConnectionPool.new(20), query_factory)
query_evaluator.transaction do |t|
t.select("SELECT ... FOR UPDATE FROM ...")
t.execute("INSERT ...")
end
class MemoizingQueryFactory
def initialize(query_factory)
@memo = Hash.new do |h, k|
h = query_factory.new(*k)
end
end
def new(connection, query_string, *args)
@memo[[connection, query_string, args]]
end
end
class QueryEvaluator
def initialize(connection_pool, query_factory = Query)
@query_factory = query_factory
@connection_pool = connection_pool
end
def select(query_string, *args)
@connection_pool.with_connection do |connection|
@query_factory.new(connection, query_string, *args).select
end
end
def execute(query_string, *args)
@connection_pool.with_connection do |connection|
@query_factory.new(connection, query_string, *args).execute
end
end
def transaction
@connection_pool.with_connection do |connection|
yield TransactionalQueryEvaluator.new(connection, @query_factory)
end
end
end
class TransactionalQueryEvaluator
def initialize(connection, query_factory)
@connection = connection
@query_factory = query_factory
end
def select(query_string, *args)
@query_factory.new(@connection, query_string, *args).select
end
def execute(query_string, *args)
@query_factory.new(@connection, query_string, *args).select
end
def transaction
yield self
end
end
class TimingOutQueryProxyFactory
def initialize(query_factory, timeout)
@query_factory = query_factory
@timeout = timeout
end
def new(connection, query_string, *args)
@query_factory.new(connection, query_string, *args)
end
end
class TimingOutQueryProxy
def initialize(query, timeout)
@query = query
@timeout = timeout
end
def select
Timeout.timeout(@timeout) do
@query.select
end
end
# ...
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment