The Artima Developer Community
Sponsored Link

Weblogs Forum
Code Generation: The Real Lesson of Rails

42 replies on 3 pages. Most recent reply: Apr 6, 2007 12:21 PM by robert young

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 42 replies on 3 pages [ « | 1 2 3 | » ]
Devin Mullins

Posts: 7
Nickname: twifkak
Registered: Jan, 2006

Re: Code Generation: The Real Lesson of Rails Posted: Mar 17, 2006 12:39 PM
Reply to this message Reply
Advertisement
> Yes, we don't touch the generated code, because it isn't
> "source" code anymore.
Though, sometimes it isn't us touching the generated code, what with the Java IDEs and the autocompletion and the whatnot.

David Beutel

Posts: 29
Nickname: jdb
Registered: May, 2003

Re: Code Generation: The Real Lesson of Rails Posted: Mar 17, 2006 5:34 PM
Reply to this message Reply
I think you misunderstood his question. Let me ask it a different way. Instead of writing Java code that reads a DSL and generates Java code that does X, why not write Java code that reads a DSL and does X directly , without generating anything? It might be simpler. In other words, I can use a DSL without generating code.

Cheers,
11011011

David Beutel

Posts: 29
Nickname: jdb
Registered: May, 2003

Re: Code Generation: The Real Lesson of Rails Posted: Mar 17, 2006 5:39 PM
Reply to this message Reply
Oops, sorry, I see you already covered this in later posts. I didn't get the threading.

Cheers,
11011011

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Code Generation: The Real Lesson of Rails Posted: Mar 20, 2006 7:18 AM
Reply to this message Reply
> A few of the reasons we went the code generation approach
> in this case is to get more readability (as Sasha
> mentioned), to leverage static type checking (as Carl
> Manaster mentioned), and because in many cases in our
> example it was unwieldy to get all that stuff in one
> class.

It would seem to me that one of the main reasons you might use code generation is if the cost of generating the logic is fairly expensive. Code generation allows 'caching' of logic. In certain cases, ecapsulating the logic in runtime Objects might be quite quite expensive in terms of space usage. Acutally 'might' isn't the right word. I use a tool that does this and it is hoggish to a fault. A tool like this could definitely benefit from code generation. Another example would be python. When you load a module, it compiles the python code into bytecodes. Instead of processing through the interpretation over and over again, it caches the step in the form of generated code.

Scala Enthusiast

Posts: 7
Nickname: sashao
Registered: Jun, 2005

Re: Code Generation: The Real Lesson of Rails Posted: Mar 20, 2006 2:51 PM
Reply to this message Reply
Bill writes:

>>> When I want to write something a certain way, because it is a good design, but it still requires a lot of repetive coding ...<<<

Hmmmm, isn't good design supposed to avoid repetitive coding? :-)

Semantics aside, how about this example:

for(Field field : fieldsToTabulate)
tableRow.set(field, user.get(field));

instead of

tableRow.setField("first_name", user.getFirstName())
tableRow.setField("last_name", user.getLastName())
...(shake and repeat 10 times)...

The first has less code, but it can be also more flexible: it is easy to modify display by just manipulating the 'fieldsToTabulate' collection.

Ultimately, I would like to have both: generated attribute accessors for business logic that requires them AND the ways to manipulate attributes in bulk.

John Reynolds

Posts: 4
Nickname: johnrynlds
Registered: Jan, 2006

Re: Code Generation: The Real Lesson of Rails Posted: Mar 21, 2006 7:11 AM
Reply to this message Reply
> In each of these cases, Rails breaks long-standing
> conventions that Java framework designers have often held
> as sacred. Rails starts with a working schema and reflects
> on the schema to construct a model object.

I recently spoke with Ken Orr (http://weblogs.java.net/blog/johnreynolds/archive/2006/03/ken_orrs_advice_1.html)about his experiences (since coming up with Warnier-Orr diagrams in the 70's) and advice that he would offer to Java programmers... The lack of skill at data modelling is one of his prime concerns.

Java people (myself included) tend to believe that the Schema should be driven by the Object Model, but Data Warehouse people know that this just doesn't make sense in many cases (Objects are just one way of organizing the data). Ken's view gives a lot of credence to the idea of a "wrapping framework" for Java.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Code Generation: The Real Lesson of Rails Posted: Mar 21, 2006 10:18 AM
Reply to this message Reply
> Java people (myself included) tend to believe that the
> Schema should be driven by the Object Model, but Data
> Warehouse people know that this just doesn't make sense in
> many cases (Objects are just one way of organizing the
> data).

But this does not imply that the Object model should be driven by the schema. This is what Rails is doing according to the article. In fact it would suggest that the object model and the db schema should be designed somewhat independently.

Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Re: Code Generation: The Real Lesson of Rails Posted: Mar 21, 2006 11:21 AM
Reply to this message Reply
> Bill writes:
>
> >>> When I want to write something a certain way, because
> it is a good design, but it still requires a lot of
> repetive coding ...<<<
>
> Hmmmm, isn't good design supposed to avoid repetitive
> coding? :-)
>
Yes, but sometimes you can't get there by abstracting via OO mechanisms, at least not without sacrificing other good things such as static type checking, readability, and speed of development. It is hard for me to figure out how to describe it, but there are situations in which you are repeatedly doing the same class of thing, but for which you couldn't make a class.

An example from our web apps is our controllers. We do have a superclass Controller, but each subclass has different parameters coming in from the request. So it would be hard in a superclass to parse the parameters once into instance variables that can be used, because every different controller would need different instance variables. So we find ourselves typing this kind of repetitive code:


String firstName = request.getParameter("first");
String lastName = request.getParameter("last");


Different controllers have different parameters, so we can't really factor this code out anywhere. What Rails does is look at the parameters at runtime when the request comes in, and creates instance variables with the property names. What we do is list the parameters in our DSL, and generate code that grabs then and puts them into instance variables. Then when we need to use the first name in our controller subclass, we just say firstName. It has already been declared and filled with a value from the request.

> Semantics aside, how about this example:
>

> for(Field field : fieldsToTabulate)
> tableRow.set(field, user.get(field));
>

> instead of
>

> tableRow.setField("first_name", user.getFirstName())
> tableRow.setField("last_name", user.getLastName())
> ...(shake and repeat 10 times)...
>

> The first has less code, but it can be also more flexible:
> it is easy to modify display by just manipulating the
> 'fieldsToTabulate' collection.
>
> Ultimately, I would like to have both: generated attribute
> accessors for business logic that requires them AND the
> ways to manipulate attributes in bulk.

We haven't needed the latter, so if we need it we can add it. But we try very hard to not add any code until we have a need for it.

Charles Daniels

Posts: 4
Nickname: repoman
Registered: Apr, 2002

Re: Code Generation: The Real Lesson of Rails Posted: Mar 21, 2006 8:25 PM
Reply to this message Reply
Hi Bill,

Nice entry. I just wanted to add that dynamic code generation is also possible in Java with the help of such things as the BCEL (Byte Code Engineering Library) and libraries built on top of the BCEL, such as Javassist.

Of course, such dynamic code generation may or may not be appropriate in various cases and it may also take a bit more thought than generating code statically, but it's certainly viable. Using something such as Javassist, rather than BCEL directly, certainly helps to reduce the effort involved.

-- Chuck Daniels

John Reynolds

Posts: 4
Nickname: johnrynlds
Registered: Jan, 2006

Re: Code Generation: The Real Lesson of Rails Posted: Mar 22, 2006 8:47 AM
Reply to this message Reply
> > Java people (myself included) tend to believe that the
> > Schema should be driven by the Object Model, but Data
> > Warehouse people know that this just doesn't make sense
> in
> > many cases (Objects are just one way of organizing the
> > data).
>
> But this does not imply that the Object model should be
> driven by the schema. This is what Rails is doing
> according to the article. In fact it would suggest that
> the object model and the db schema should be designed
> somewhat independently.

Pardon me for not being clear... I think the Rails approach is a good one in many circumstances, and that the Java framework tendency to generate the schema from the object model is sometimes not a good approach.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Code Generation: The Real Lesson of Rails Posted: Mar 22, 2006 9:23 AM
Reply to this message Reply
> Pardon me for not being clear... I think the Rails
> approach is a good one in many circumstances, and that the
> Java framework tendency to generate the schema from the
> object model is sometimes not a good approach.

It's just never been my experience that the db schema is generated from the Object model. I've never heard anyone say this or seen it written that this should be done. It doesn't really even make sense as relation DBs are not OO. Generally, on the projects I have worked on the DB schema is much older than the Java Object model.

What I have seen is that Java Object models are generated from the schema (as in Rails) which doesn't really make sense either since Object models are OO and not relational. I've also seen this approach to be problematic in practice.

I was actually talking to a co-worker about this today. What happens in Rails if a table is normalized? What happens if other non-trivial (e.g. adding columns) changes are made to the DB? I can see how Rails makes it easy to develop code fast but I've never read anything about how easy it is to maintain Rails projects. I worked with a tool some peple may remember called PowerBuilder. This was also a tool that made it 'easy' to write client-server apps. However, after years of 'rapid application development' the application's maintainablilty deteriorated... rapidly. Small changes that would be trivial in a well designed Java app took more time and money than the initial development of the application. A small change to the DB schema would require a solid week of coding along with many more weeks of testing and bug fixes. What guarantees do we have that Rails' track doesn't lead into that valley of despair?

Maybe Rails does avoid this but I am getting feeling of deja vu all over again. It's as if no one remembers the problems that led people to use Java in the first place.

Slobodan Filipovic

Posts: 3
Nickname: topce
Registered: Jan, 2004

Re: Code Generation: The Real Lesson of Rails Posted: Mar 23, 2006 8:57 AM
Reply to this message Reply
I think that best solution for ORM problems will come from M$ http://msdn.microsoft.com/netframework/future/linq/

Charles Bell

Posts: 519
Nickname: charles
Registered: Feb, 2002

Re: Code Generation: The Real Lesson of Rails Posted: Mar 23, 2006 9:09 AM
Reply to this message Reply
Enjoyed your article Bill. Its got me thinking.

Good to hear from you,

Charles Bell

John Lopez

Posts: 2
Nickname: godeke
Registered: Jan, 2004

Re: Code Generation: The Real Lesson of Rails Posted: Mar 23, 2006 10:36 AM
Reply to this message Reply
I have heard said "code generation is a sign that your language lacks a high enough abstraction level".

I know that back when we were working in ASP with VBScript (please I'm quite aware how horrible that choice was) we used code generation to get around the poor support for true OO concepts (such as the lack of subclassing) and to cache some of the "hard work" required to abstract the database into objects.

I suspect there will come a day where the best of both worlds will be available: we will be able to point a tool at a schema and there will be "invisible" generated code ala-active record, and yet the types will be statically checked and the IDE will allow us to access them as if they were statically defined. I see a lot of use for code generation today, but I hope that IDE/language builders realize that each time people resort to code generation it is a strong indicator that improvement is needed in the language/toolchain.

Bruce Chapman

Posts: 8
Nickname: chappy
Registered: Mar, 2003

Re: Code Generation: The Real Lesson of Rails Posted: Mar 23, 2006 3:05 PM
Reply to this message Reply
Instead of calling person.get_name to set a property, you might use person.get(name) instead. At the cost of static type checking, you'd get a class built of metadata driven from a database

Ignoring the obvious mistakes, this comment triggered an interesting thought.

If name in person.get(name) were some sort of enum that used generics to carry some type information, then you don't need to give up static type checking.

To do this you need to abandon JDK5's enum, and revert back to the type safe enum pattern. (you might be able to extend Enum though and let it do most of the enum pattern donkey work)


class Person {
static class Columns<T extends Columns<T>> {
static final Columns<String> NAME = ...;
static final Columns<Long> ID= ...;
static final Columns<Date> DOB = ...;
private Columns() { ... }
}

<T> T get(Columns<T> column) { ... }
}


There's quite a lot of implementation missing, and probably Columns.get() would be abstract and implemented in subclasses specific to each type, but hopefully you get the idea.

Having done that you can now write

Person person = ...;
String name = person.get(Person.Columns.NAME);
Long id = person.get(Person.Columns.ID);


and it is all typesafe and casts aren't required.

I'd probably hoist the constants out of the enum class definition and place them in the outer class so you could write
String name = person.get(Person.NAME);

Bruce

Flat View: This topic has 42 replies on 3 pages [ « | 1  2  3 | » ]
Topic: Code Generation: The Real Lesson of Rails Previous Topic   Next Topic Topic: Back at OOPSLA

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use