Hi Tom, > Yep. I recall. Template Design Pattern. Didn't know that it had a name. Well, > it's what I did, as I don't think there is better way to do it at this point. > Thanks Peter. Actually your example above could prove to be a useful application of cflow. Suppose during compilation you'd have to do a number of tasks, and each has a number of subtasks, and each of those too, etc. Suppose that some of the tasks need to be run in a chroot environment, but you'd want to run as little as possible in a chroot environment (say because that minimizes security risks). You'd then have a main method called compile, and a bunch of methods that either need to be wrapped in a chroot or not, but you can't make a clear separation in the call tree between the two kinds of methods. I'll give a simple example: def compile # needs no chroot task1 task2 end def task1 # needs a chroot task2 task3 end def task2 # needs a chroot ... end def task3 # needs no chroot ... end For task1 we'd need to create the chroot environment. For task2 too, but not when it is called from a method that already created a chroot env. For task3 we need not create a chroot env, but we need to break one down when called from a chrooted method. If we have a number of tasks like this, it becomes cumbersome to code this in a consistent way. And thus we can use AOP techniques. And to see whether we are in a chroot environment already, we can use cflow. But we need to be able to limit it to the direct caller. But suppose we have some real small tasks that don't require a chroot environment, but are too insignificant to break down and rebuild the environment for. I remember saying that cflow is technically not required, you can do the same with just wrappers. So maybe we should do it explicitly in Ruby then. The only point of cflow is that if it's a recurring concept, it might be worth to have a separate notion of that in Ruby. But what I don't like about cflow is that unless we can find a much completer notion to describe conditions based on control flow, using it may cause troubles too. If the condition becomes more complex, then it's possible we can't describe it anymore in cflow logic and thus we need to make it explicit anyway. If it was explicit in the first place, we'd need to change less. I don't know if you're still with me... > It's all good. I have lots of stuff on my plate right now. I'll just keep > touching back on this as it developes in my mind. Have started some rework on > the wiki page. BTW, about [ruby-talk:86785]... Correct me if I'm wrong, but the idea there is that you want to have a wrap that is always the outermost wrap, even if methods are redefined in subclasses, much like the problem of the chroot environment you presented. But I think I still need to be convinced of the use of wraps in such cases because it can easily be done with current Ruby (using template patterns and alike). Granted, wrapping can do the same thing in-place. But is that necessary? If a wrap is supposed to stay in place, like in case of your chroot creation, it seems natural to use something template-like. OK, that exposes more methods, like the real_compile in my previous post, but that's a more general problem of visibility that's cross-cutting. It's the problem C++ tries to solve in a clumsy way using friend classes, and what Matz tries to solve using namespaces (but implementation-wise this is hard to do efficiently in a dynamic language as Matz mentions on his slides). And actually with wraps there's the problem that wraps are anonymous (unless we use indicators, or allow to index the wrap stack, which is definitely yuck), but using template-like things and subroutines, that's not a problem for all has a name. I'm just thinking aloud now, after reading up on AspectJ stuff. What bothers me is that while reading the AspectJ stuff again, my reaction is continually "so what, we can do that in Ruby already". (I learned Ruby after I learned about AspectJ.) The first picture they show in their talks is a schematic representation of the lines of code in the different source files of the apache web server code. They show that XML parsing code is located in 1 file. They show that URL pattern matching code is only in two files (because it's a class and it's subclass). But then logging is spread all over the place. But then I say to myself that we in Ruby don't have such a problem. We are not forced to place the code of one class or module by itself in one file. So we can perfectly move all the code concerned with logging into one file. We can even make it generic so we don't need to write the same code over and over again. This shows again that Matz wasn't born yesterday. A class-based source file system forces you to put all the code related to manipulating the same bit of data in one file, even if code has parts that are about completely different concerns. Ruby allows you to also split code based on the different concerns. If you combine that thought with the idea of mix-ins (which the AspectJ guys try to do using inter-class declarations, aka "open classes"), Ruby seems to have more advantages than AspectJ will ever have. I don't know if you see where I'm going. I don't know if I see where I'm going. But my conclusion seems to be that for internal wraps, we make things more complicated by using wraps, rather than solve things. What we seem to struggle with are things like the order of the wraps, removing wraps, redefining wraps, etc, and these seem really hard when there are wraps, but not when we'd use things like templates and subroutines etc because then we already have explicit power to manipulate all of that. However I do believe there is use in what we call external wraps, which are really just hooks that get called when another method gets called, but are not part of the intrinsic functionality of the method they wrap. The gain there is that they are really invisible to the rest of the program, only they know they are there. And for those wraps, things like the order of the wraps in the stack doesn't matter or removal on prime method redefinition. But I feel that for intrinsic wraps we seem to be using the wrong mechanism. It seems to take away explicit control, and we are now looking for a way to give it back. If you know what I mean. Maybe a final note... There are some features AspectJ has that we don't have in Ruby (or at least that I know of). In AspectJ a method can be called when a variable is read/assigned (easy for a compiled language). Also exception handlers are join points. Note that we could add hooks there, but not without the hooked ones explicitly providing that possiblity. Peter PS: I'm not crawling back, I'm just waiting for you to refute all I've been saying :-) PPS: Sorry for rambling on for so many kilobytes