Here I accept James’ invitation to commence the discussion
Be aware: I enter pure brain storming mode
brain_storming_mode: ON
It looks like we want to achieve a greater level of DRYness while
keeping the benefits of low configuration rate.
As most part of Rails code shows, we can try to do that by applying
other important principles in a rigorous way:
- use convention, not configuration
- use composition, not inheritance
how to translate this in our case?
Well, here I guess we do need to add functionalities to the engines
plugin.
(I guess, and not know as a fact, because I haven’t yet studied the
plugin code, if not locally).
What we need is a sort of “communication bus” between engines that
enables inter engine communication.
The engines plugin could keep, for instace, a Register of the started
engines together with their skills and then spread this knowledge in the
registred engines community.
It could work like the following:
-
the engines, when started, tell to the Register which service(s) they
are offering (probably just a :symbol with the service name) -
when an engine needs a specific service, asks the Register a “pointer”
to whoever provides it and then uses it. -
by using a solid interface naming convention, we could enable the
possibility for the engines to load dinamically other engines behaviours
if, and only if, they are available.
To esemplify:
-
NeedyEngine needs somebody performing the do_hard_work service for
him. -
the Register looks up in itself and finds that the ExpertEngine has
registred offering the do_hard_work service. -
the Register returns to NeedyEngine a pointer to the ExpertEngine
-
NeedyEngine “calls”
ExpertEngine#do_hard_work({params}, :return_to => “a/next/action” ) -
The controll goes to ExpertEngine that can interact with the browser,
do all his work and then return to NeedyEngine#a/next/action -
[optional] NeedyEngine provides internally (not registered) a
do_hard_work dummy service implementing the Null pattern on itself.
Basically here we can use rules/conventions like:
-
rule: the “:return_to” parameter is mandatory
or
convention: if “:return_to” is not given, then is assumed :index -
We could even estabilish an authority (rails-engine.org ?) that keeps
a list of standardized services. This is a very important point to
discuss!
Imagine that you are writing an Engine and you need it to use
“authentication”.
You look on-line at rails-engine.org/services and see that there is a
definition for a standardized service named “authentication”.
Since the authority defines the standard parameters (like “:return_to”)
all the services are supposed to accept and keeps track of the service
specific parameters as well (i.e. :password, :user for the
“authentication” service), you can “use” the “authentication” service in
your new Engine code, assuming that somebody wil provide an
implementation for it (but don’t forget to write your dummy/default
“authentication” service!!!).
Whoever wants can write an engine that offers the “autentication”
service,
and as long as it is engines-authority-standard compliant, it will be
usable by your engine without any effort.
In other words: a huge Strategy pattern!!! (so we use “dynamic
composition” instead of inheritance or, even worse, copy & paste).
brain_storming_mode: OFF
Waiting for opinions,
Mauro
James A. wrote:
Both the User and Login engines could do with serious refactoring with
a view to making them much cleaner in terms of overriding behaviour. A
big part of this is probably going to be establishing a clear API for
both. Let the discussion commence!
- james
On 2/28/06, Bart M. [email protected] wrote:
session['return-to'] = '/books/create'
course copy the complete new action, but this goes against the DRY
user_controller just to change >one string. I’m not sure I can think of
integrate it all together, by integrating the new user partial into the
Bart