# Rcr 13

**URL:** <https://www.ruby-forum.com/t/rcr-13/107962>\
**Category:** Ruby\
**Created:** [June 27, 2007, 9:51pm UTC](https://www.ruby-forum.com/t/rcr-13/107962 "2007-06-27T21:51:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [June 27, 2007, 9:51pm UTC](https://www.ruby-forum.com/t/rcr-13/107962/1 "2007-06-27T21:51:49Z")

</div>

Hi everybody,

In case you’ve been following the RCR’s, I wrote RCR 13 the other  
day. I intend to withdraw it for now, but I would still like to  
request comments from the list/usenet group. Here’s the text of the  
RCR – please note that I made a small change to the text in response  
to an objection by Robert K… While his objection was worthwhile,  
it can be fixed with a single line of intuitive code.

ABSTRACT

If a class mixes in a module implementing a particular API, then  
another implementing the same API, it cannot recover the first  
implementation by including the first module. A solution to this  
problem would be to modify rb\_mod\_append\_features function in Obj.c to  
append the methods in the inheritance chain even if they already  
exist.

PROBLEM

When writing a program utilizing a client-server architecture, one  
often wants to write server objects that respond to different “kinds”  
of client requests in a different manner, while still maintaining a  
stable API the client can use. Using mixins to solve this problem  
seems very natural. Consider the following code:

class Request  
attr\_reader :kind, :data  
def initialize(kind, data)  
@kind = kind  
@data = data  
end  
end

module Identity  
def process(data)  
return data  
end  
end

module Double  
def process(data)  
return data + data  
end  
end

class Service  
def initialize # implementation specific.  
end  
def run(request)  
self.instance\_eval(“extend #{request.kind}”) # different in  
RCR.  
process(request.data)  
end  
end

service = Service.new()

request = Request.new(“Identity”, 1)  
request2 = Request.new(“Double”, 1)  
request3 = Request.new(“Identity”, 1)

service.run(request) # returns 1  
service.run(request2) # returns 2  
service.run(request3) # returns 2 instead of the intended 1.  
-End of Code

As the last comment notes, service.run(request3) returns 2 instead of  
the intended 1. That is to say, this pattern cannot be implemented  
using the current semantics for Module.include.

PROPOSAL

This proposal does not affect Ruby’s syntax. The proposal is to re-  
implement Module::include so that the last included module in a class  
is appended to the inheritance chain, even if it has been included in  
the class previously. This will only affect Ruby code that relies on  
the behavior that a module can override another module’s methods, and  
spuriously attempts to load the original module.

ANALYSIS

A different solution for this problem already exists, but it is not as  
obvious or elegant. Instead of the class Service definition in the  
Problem section, we can write  
class Service  
def run(request)  
self.instance\_eval("#{request.kind}::process(#{request.data})")  
end  
end  
Indeed, we are no longer even using mixins. The semantics of the  
instance\_eval method and variable interpolation make this a confusing  
hack. This would also require running instance\_eval on every  
invocation of run, since the complete method named invoked by run must  
be passed to a different context each time. If my suggestion is  
implemented, the original class Service can be modified to

class Service  
def initialize # Unimportant details here.  
@last = “”  
end  
def run(request)  
unless @last == request.kind  
self.instance\_eval(“extend #{request.kind}”) # different in  
RCR.  
@last = request.kind  
end  
process(request.data)  
end  
end

effictively caching service’s role. Depending on how often service’s  
role changes, this can be significantly faster than the version using  
instance\_eval. On the other hand, if service’s role changes  
frequently, the modified version would likely be much slower because  
of the overheard of virtual class creation.

I have experimented with Object::send, but was unable to construct a  
run method that worked as intended.

Several other thoughts have occured to me. If my suggesting is  
implemented, duplicate Modules names should likely be removed the  
inheritance chain. Otherwise, the chain can grow arbitrarily long  
during a service objects lifetime. Indeed, this can occur even if they  
are removed, should an arbitrarily long list of roles be demanded of  
the service. But that would be poor design, not something we should  
really concern ourselves about. However, a mechanism to explicitly  
remove a module from a class’s inheritance chain can be implemented as  
well.

Mixins that vary through time seem like a natural extension of the  
mixin functionality. However, perhaps a new Module instance method  
could be implemented to automate module loading.  
implemented\_by :symbol would be my suggestion.

IMPLEMENTATION

It is my understanding that this proposal would require changes to  
Ruby’s interpreter. I am not good with C, so I shall leave this to the  
professionals.

–END OF RCR

Robert K. suggested that my original design in the code was  
flawed, since I presumably want different Service objects fullfilling  
different roles at run-time, and my implementation of including mixins  
at run-time was class-wide. I modified the code so that each Service  
object is extended by a module. Since obj.extend(module) is  
equivalent to class \<\< obj; include module; end, the problem raise in  
the RCR still stands. Robert also noted that the problem can be  
avoided completely using the delegator design pattern. I would  
suggest that because of Ruby’s use of virtual classes when including a  
module, my design is an elegant reformulation of the delegator  
pattern.

Trans suggested that a more general solution to my problem exists:  
Exposing the inheritance chain as an array. I would have no problem  
with this, as it would allow me to implement my hypothetical  
implemented\_by method. I would be happy to write an RCR based on this  
suggestion. So I welcome all your comments regarding RCR 13 and  
Trans’s suggestion. Other use cases for my suggestion or Trans’s  
suggestion would be especially appreciated.

Thanks!  
Alex
