Monday, April 03, 2006
Minimal Descriptions and Metaprogramming
My fellow socialite Pilu has opened a blog, Gurage, where he provides an introductive examples to Rails. He uses a simple inheritance example describing a Guitarist and a Singer as being two subclasses of Artist.
While reading his code, that describes a Struct-like class (more an holder of attributes than an holder of behaviours) I thought back to a discussion that we had at the Ruby Social Club meeting about metaprogramming tricks. My point was that through metaprogramming you can redefine the language in such a way that you can also provide stereotypical descriptions for classes and methods, so that you don't have to explicitly describe initializer, accessors, and so on.
For example, this code written by Pilu
This second form is no doubt more compact, but is it better?
Forget the fact that the full class definition already provides the 'space' to add in new methods and attributes. Assume that the code is done and you are simply reading it. What is better? and why?
Something tells me that I would like the more terse and compact form, but somehow I still find that the first form has got something that the compact form lacks. I just can't put my finger on it.
Following on from Pilu's example I would like to have a compact formalism that allows me to say something like:
Using metaprogramming is not too hard to generate this kind of Minimal Descriptions, although they would probably look like this:
I will leave the metaprogramming as an exercise for the reader :-D
The 'defined_by' is just wrapping a call to ' Struct.new', probably also adding a few extras such as a comparison operator and a prettier to_s method. The 'also_defined_by' is a method that has been injected into the Class class. It creates a new anonymous subclass, adding a few extra accessors and also overriding the initializer by adding some extra parameters.
We have seen how this is technically feasible, I just wonder if this is what we want.
The standard way of doing things shows us explicitly that we are dealing with a class. The 'class' and the 'end' words and the indentation highlight clearly a chunk of code and identifies it as being a class, an important concept within the narrative of our system.
The Minimal Description approach tries to hide away the whole concept of class. It simply cares about concepts and meaning and it abstracts away a big body of knowledge. The body of knowledge that is abstracted away is that we are defining classes and that these classes are related by inheritance. It is also assuming that we know that if something is defined by a certain characteristic, then this characteristic will have to be used when creating an instance of that concept.
What do you think? Is this a rightful use of metaprogramming and of Shaping code After Language, or is it a blatant abuse of metaprogramming power?
While reading his code, that describes a Struct-like class (more an holder of attributes than an holder of behaviours) I thought back to a discussion that we had at the Ruby Social Club meeting about metaprogramming tricks. My point was that through metaprogramming you can redefine the language in such a way that you can also provide stereotypical descriptions for classes and methods, so that you don't have to explicitly describe initializer, accessors, and so on.
For example, this code written by Pilu
could easily become something like:class Artist
attr_reader :name
def initialize(name)
@name = name
end
end
Artist = Struct.new :name
This second form is no doubt more compact, but is it better?
Forget the fact that the full class definition already provides the 'space' to add in new methods and attributes. Assume that the code is done and you are simply reading it. What is better? and why?
Something tells me that I would like the more terse and compact form, but somehow I still find that the first form has got something that the compact form lacks. I just can't put my finger on it.
Following on from Pilu's example I would like to have a compact formalism that allows me to say something like:
Artist defined by name
Guitarist is an Artist also defined by guitar
Singer is an Artist also defined by microphone
Using metaprogramming is not too hard to generate this kind of Minimal Descriptions, although they would probably look like this:
Artist = defined_by :name
Guitarist = Artist.also_defined_by :guitar
Singer = Artist.also_defined_by :microphone
I will leave the metaprogramming as an exercise for the reader :-D
The 'defined_by' is just wrapping a call to ' Struct.new', probably also adding a few extras such as a comparison operator and a prettier to_s method. The 'also_defined_by' is a method that has been injected into the Class class. It creates a new anonymous subclass, adding a few extra accessors and also overriding the initializer by adding some extra parameters.
We have seen how this is technically feasible, I just wonder if this is what we want.
The standard way of doing things shows us explicitly that we are dealing with a class. The 'class' and the 'end' words and the indentation highlight clearly a chunk of code and identifies it as being a class, an important concept within the narrative of our system.
The Minimal Description approach tries to hide away the whole concept of class. It simply cares about concepts and meaning and it abstracts away a big body of knowledge. The body of knowledge that is abstracted away is that we are defining classes and that these classes are related by inheritance. It is also assuming that we know that if something is defined by a certain characteristic, then this characteristic will have to be used when creating an instance of that concept.
What do you think? Is this a rightful use of metaprogramming and of Shaping code After Language, or is it a blatant abuse of metaprogramming power?
Comments:
<< Home
Funny, I've been pondering this just this morning, thinking about When I'll Write My Own Language(tm).
The main problem with using Struct.new or defined_by is that you introduce a non-common way of defning the class, so you're really using a ruby patois that other people may not appreciate.
OTOH I think that once you establish this application language in your dev team it may be a really useful thing, and not just a metaabuse :)
The main problem with using Struct.new or defined_by is that you introduce a non-common way of defning the class, so you're really using a ruby patois that other people may not appreciate.
OTOH I think that once you establish this application language in your dev team it may be a really useful thing, and not just a metaabuse :)
I love the term Ruby Patois (tm), I think I'll appropriate it :-)
I am slightly suspicious of the "common way of doing it" argument.
Occasionally you see uncommon ways of doing things that immediately make sense. Other times they don't make sense immediately, but they are cool after you understand them (eg Injection of Control)
You could even talk about different Coding Schools.
In this case, however, it is something different. On one hand the class keyword and the indentation make easy to immediately spot classes, and you can rely on your visual code browsing skills. You know, you just glance to pages of code and you get a 'feeling' for what is in there and how it is related.
On the other hand the Minimal Description style needs to be read. There is no visual cue telling you where a concept starts and where it ends. However, if you read it, it will make sense and it will be a shorter read too.
I have a theory: when we look at code we visualize little UML boxes where we see the class keyword and indented code.
I am slightly suspicious of the "common way of doing it" argument.
Occasionally you see uncommon ways of doing things that immediately make sense. Other times they don't make sense immediately, but they are cool after you understand them (eg Injection of Control)
You could even talk about different Coding Schools.
In this case, however, it is something different. On one hand the class keyword and the indentation make easy to immediately spot classes, and you can rely on your visual code browsing skills. You know, you just glance to pages of code and you get a 'feeling' for what is in there and how it is related.
On the other hand the Minimal Description style needs to be read. There is no visual cue telling you where a concept starts and where it ends. However, if you read it, it will make sense and it will be a shorter read too.
I have a theory: when we look at code we visualize little UML boxes where we see the class keyword and indented code.
No, no, it wasn't advice! :-) I am not even sure it is a good thing to do, yet. I guess I'll have to try and see if it works in practice.
However, you remind me that I should keep working on the metaprogramming posts. So little time...
Post a Comment
However, you remind me that I should keep working on the metaprogramming posts. So little time...
<< Home