The Artima Developer Community
Sponsored Link

Java Community News
Gavin King on Being Explicit

18 replies on 2 pages. Most recent reply: Sep 27, 2007 10:29 AM by Morgan Conrad

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 18 replies on 2 pages [ 1 2 | » ]
Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

Gavin King on Being Explicit Posted: Sep 21, 2007 12:39 PM
Reply to this message Reply
Summary
In a recent blog post, Gavin King, instigator of both Hibernate and Seam, compares convention-based configuration with more explicit methods, such as annotations or XML.
Advertisement

In responding to comments by Daniel Spiewak, creator of the ActiveObjects persistence framework, Gavin King contrasts the configuration-by-convention style of database mapping—used, for instance, in Rails' ActiveRecord component—with the more explicit mapping declarations used in Hibernate and the Java Persistence API:

To solve this non-problem of mountains of XML, Daniel was inspired by Ruby's ActiveRecord. The code example he gives is the following:

class Person < ActiveRecord::Base  
   belongs_to :company  
end

class Company < ActiveRecord::Base  
   has_many :people  
end

At this point, most developers are thinking um, ok, so how the hell am I supposed to know what attributes a Company has by looking at my code? And how can my IDE auto-complete them?

Of course, the Rails folks have a quick answer to this question Oh, just fire up your database client and look in the database!. Then, assuming that you know ActiveRecord's automagic capitalization and pluralization rules perfectly, you will be able to guess the names of the attributes of your own Company class, and type them in manually.

King shows a comparable declaration using Hibernate:

@Entity
public class Company extends Entity {  
   private String name;  
   private String tickerSymbol;
   @OneToMany private Person[] people;

   public void getName() { return name; }  
   public void setName(String name) { this.name = name; }

   public void getTickerSymbol() { return tickerSymbol; }      
   public void setTickerSymbol(String tickerSymbol) { this.tickerSymbol = tickerSymbol; }

   public Person[] getPeople() { return people; }
   public void setPeople(Person[] people) { this.people = people; }
}

King notes that the Java class is much more verbose than the Ruby/ActiveRecord entity class, since in the appropriate property accessors are added to the Ruby class dynamically, based on the database columns. Still, King believes that the more explicit Java code is easier to work with:

Somehow, excitement about the Ruby language has warped their perceptions to such an extent that these people actually believe that this is a good thing!...

I really don't think this code is significantly more complex or difficult to type than the ActiveObjects version (in fact, in a modern IDE, it probably requires fewer keystrokes to produce). Even better, I don't need to use any funny API to instantiate this class. I can just use new and be done with it.

And I think the code is a lot clearer and more explicit than the ActiveRecord version. Object orientation was very much intended for modeling business domain objects like Company and Person. It seems more than strange that Rails would essentially delegate the business domain model to the database.

What's your take on working with more verbose, but possibly more explicit, code versus relying to a great extent on automatically generated code and artifacts?


Kevin Klinemeier

Posts: 7
Nickname: zipwow
Registered: Dec, 2002

Re: Gavin King on Being Explicit Posted: Sep 24, 2007 10:07 AM
Reply to this message Reply
There has to be some kind of middle ground here. I agree with Gavin's concern about having to query the database in order to know the properties. At the same time, writing the get/set methods is bad, whether my IDE generates them or not. I read more code than I write, and all that auto-generated boilerplate code becomes noise in my file.

I think Groovy is pretty close to the right thing in this regard: you define your properties in the file, which implies get/set methods. If you need your get/set methods to do something other than the default, you add them. Their existence in the file is an explicit warning that something different than usual is happening. That's an efficient use of code.

Wilfred Springer

Posts: 176
Nickname: springerw
Registered: Sep, 2006

Re: Gavin King on Being Explicit Posted: Sep 24, 2007 10:13 AM
Reply to this message Reply
I agree to some extent with Gavin. However, ideally, I would love not be bothered with this:

public void getName() { return name; }
public void setName(String name) { this.name = name; }

public void getTickerSymbol() { return tickerSymbol; }
public void setTickerSymbol(String tickerSymbol) { this.tickerSymbol = tickerSymbol; }

public Person[] getPeople() { return people; }
public void setPeople(Person[] people) { this.people = people;

This is just a ***vvveeerrrryyyy*** long way of declaring some of your private data to be public instead. Mind you, I don't expect people to all of a sudden expose all of their inner state as public members. I just would love to have something in Java to export members at will, without having to write all accessors myself. Annotations come to mind, and that would be fine with me.

Remember, the actual amount of code you would have to write is actually more. To keep checkstyle and your manager happy, for instance. All code accessors would have to be documented with the same boring boiler plate comments over and over again.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Gavin King on Being Explicit Posted: Sep 24, 2007 10:31 AM
Reply to this message Reply
> This is just a ***vvveeerrrryyyy*** long way of declaring
> some of your private data to be public instead. Mind you,
> I don't expect people to all of a sudden expose all of
> their inner state as public members. I just would love to
> have something in Java to export members at will, without
> having to write all accessors myself.

XStream does this and although it is geared to a different type of serialization/persistance, it seems to me that there is no reason that the same couldn't be done in Hibernate. Actually, are you sure Hibernate doesn't already allow this? I thought that it did. Maybe I'm thinking of something else.

On a side note, I don't like the idea of putting persistence specific details inside a class whether it be annotations or anything else. The convenience of having that information in the class (I understand the attraction) is too tightly bound to a persistence mechanism. The downside of external persistence configuration can be mitigated with intuitive and consistent organization.

nes

Posts: 137
Nickname: nn
Registered: Jul, 2004

Re: Gavin King on Being Explicit Posted: Sep 24, 2007 12:29 PM
Reply to this message Reply
Gavin’s code violates DRY. If you want to add a new field to a table you have to remember to change it in two places: the database and your Java program.

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: Gavin King on Being Explicit Posted: Sep 24, 2007 3:49 PM
Reply to this message Reply
> Gavin’s code violates DRY. If you want to add a new field
> to a table you have to remember to change it in two
> places: the database and your Java program.


With a relational database, you need to do this whether you have explicit getters/setters or not. You've got to add the field to your code somewhere. And you have to update the schema, a non-trivial task. (Google on "schema ownership conflict" and "dual schema problem")

<ducks for cover>
Of course, if you used an OODB then you only need to change it one place, in your code. OODBs are DRY!
<stays ducked...>

qinxian xiang

Posts: 5
Nickname: moonlight
Registered: Dec, 2006

Re: Gavin King on Being Explicit Posted: Sep 25, 2007 1:57 AM
Reply to this message Reply
Hi springer,
I think there are some more choice at property.
public data, just public.
private data and public setter/getter, just internalize inner state and java just use this style, and that style say, you know my behaivor but no property, just like your private property should be known by youself.
public data and private setter/getter, just publish data, hide action, it says, I have this feature, but you cannot know how I do for/to.
And though you not feel veerryy long keystore for java version property implementation, someone maybe tired toooooooo no-use keystore for that case.
So IMO java missing this property feature.
And this case some like Mr. Page says:
let cow.throwOut(milk) or milk.dropFrom(cow), it's a problem:-)
Regards,
Qinxian

Alex Fabijanic

Posts: 71
Nickname: aleksf
Registered: Aug, 2006

Re: Gavin King on Being Explicit Posted: Sep 25, 2007 4:35 AM
Reply to this message Reply
> It seems
> more than strange that Rails would essentially delegate
> the business domain model to the database.

One can argue one way or the other and, as usual, there is no silver bullet. To say that it is "more than strange" to delegate the business domain model to the database is, well, more than strange. The database is there. And it should be modeled in accordance with the business domain. Why then not take advantage of it?

nes

Posts: 137
Nickname: nn
Registered: Jul, 2004

Re: Gavin King on Being Explicit Posted: Sep 25, 2007 10:40 AM
Reply to this message Reply
> > Gavin’s code violates DRY. If you want to add a new
> field
> > to a table you have to remember to change it in two
> > places: the database and your Java program.
>
>
> With a relational database, you need to do this whether
> you have explicit getters/setters or not. You've got to
> add the field to your code somewhere. And you have to
> update the schema, a non-trivial task. (Google on "schema
> ownership conflict" and "dual schema problem")

I don’t know what specific page you wanted me to look at, just clicking on the first link on Google for "dual schema problem" I got a page saying that "Rails essentially solves the dual schema problem":

"A variety of solutions to the Dual Schema problem have evolved, primarily outside the hallowed halls of enterprise vendors (i.e. MS and others like us). One such solution is Ruby on Rails. In a Rails environment, I simply declare the existence of a given persistent entity:
class Person < ActiveRecord::Base
end
The ActiveRecord base class (a standard part of Rails) will dynamically create methods and attributes on the Person object at runtime, based on the schema of the People table in the database. (Rails is smart enough to understand English plurals, hence the automatic connection of Person and People.) So technically there are still two schemas, but the in-memory version is automatically derived of the on-disk version.
(Note, DLinq provides a conceptually similar tool - SqlMetal - that can generate the static types from a given database schema. However, as static types they have to be defined at compile time. So while SqlMetal reduces the effort to keep schemas in sync, it doesn't eliminate it the way Rails does.)
By slaving the object schema to the database schema, Rails essentially solves the Dual Schema problem. The problem with the Rails approach is that defining a database schema requires a significant amount of skill and effort. Defining classes is typically trivial in comparison.The fact Rails allows you to implement a persistent entity with almost no code doesn’t help you much if you have to write and maintain a ton of SQL code to define your database schema."

http://devhawk.net/2006/03/28/The+Dual+Schema+Problem.aspx

Morgan Conrad

Posts: 307
Nickname: miata71
Registered: Mar, 2006

Re: Gavin King on Being Explicit Posted: Sep 25, 2007 12:04 PM
Reply to this message Reply
"Rails is smart enough to understand English plurals, hence the automatic connection of Person and People"

Given the vagaies of English, I wonder how sophicticated their dictionary is. For example, would Rails automatically connect Goose and Gaggle? (even Goose -> Geese is tricky)

Another issue with auto creating your objects from a DB is that the DB tables, usually, aren't particularly OO. So the resultant auto-created objects tend to be only minimally OO. Depending on your needs and philosophies, the ease of creating them may or not be worth the issues working with them.

Wilfred Springer

Posts: 176
Nickname: springerw
Registered: Sep, 2006

Re: Gavin King on Being Explicit Posted: Sep 25, 2007 10:11 PM
Reply to this message Reply
XStream and Hibernate may be able to declaratively specify the attributes that need to be serialized/persisted, even when it involves private members, but that's not the point.

In order to access that private data, you need to create all of these accessors yourself. You could argue that - if all you want is get and set those values - you might as well make these fields public. But then you end up using two different paradigms for accessing data of the object, and I don't like that either.


// First piece of data I'm trying to access
String value1 = object.value1;

// Next piece of data I'm trying to access.
// Hold on. I need to use a getter here. Aha,
// I guess that reveals something of the way
// things are implemented.
String value2 = object.getValue2();

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Gavin King on Being Explicit Posted: Sep 26, 2007 5:54 AM
Reply to this message Reply
> XStream and Hibernate may be able to declaratively specify
> the attributes that need to be serialized/persisted, even
> when it involves private members, but that's not the
> point.
>
> In order to access that private data, you need to create
> all of these accessors yourself. You could argue that - if
> all you want is get and set those values - you might as
> well make these fields public. But then you end up using
> two different paradigms for accessing data of the object,
> and I don't like that either.

I'm not sure I understand your point here. I often have private members that I provide no public accessors to. In addition, I don't understand what this has to do with XStream and Hibernate because they don't force you to expose accessors either.

Frank Silbermann

Posts: 40
Nickname: fsilber
Registered: Mar, 2006

Re: Gavin King on Being Explicit Posted: Sep 26, 2007 6:39 AM
Reply to this message Reply
I don't like either approach. I think it would be better to supply a mapping to a factory that constructs the Person class. You would then use reflection to instantiate elements of this class.

The mapping could contain a list of tuples of the form:

<DB_field_name, PL_property_name, PL_datatype>

(PL stands for Programming Language; DB stands for Database.) For convenience, "PL_property_name" could default to the field name, and the datatype should default to a standard datatype based on the field's datatype.

This way, it is easy for the reader of the program to know the properties he's using without having to examine the external system, and without having to write or generate a lot of boilerplate code, and has the opportunity to provide clearer names for fields and special datatype needs.

For the times when the code is completely generic, e.g. an application that displays the arbitrary contents of a database table or query, an empty set of tuples could default to "all database fields, with using the standard datatype mappings."

Because you're putting the same information on two distinct and independent logical systems (the application server and the database server), you cannot avoid compromising the DRY prinicple. You cannot in general rely on a single point of data entry because neither system can always be made subordinate to the other.

Jim Jewett

Posts: 11
Nickname: jimj
Registered: Apr, 2005

Re: Gavin King on Being Explicit Posted: Sep 26, 2007 7:10 AM
Reply to this message Reply
> In order to access that private data, you need to create
> all of these accessors yourself.

Even having to read them is ugly, though I suppose it goes away in some IDEs -- but at that point you're treating the code as the binary output of an IDE generation step.

> You could argue that - if
> all you want is get and set those values - you might as
> well make these fields public. But then you end up using
> two different paradigms for accessing data of the object,
> and I don't like that either.

Python handles this well.

The default is to just use the attribute (public field), but if you want some sort of filter, you can stick in a property -- which is an internal detail, transparent to users of the API.

With y as the normal case, and X needing special attention


>>> class FancyX(object):
def _get_x(self):
print "getting X"
return self.__x
def _set_x(self, val):
print "setting X to", val
self.__x = val
# We won't let them delete X
X=property(_get_x, _set_x, None, "property demo")

>>> f=FancyX()
>>> f.X
getting X

Traceback (most recent call last):
File "<pyshell#61>", line 1, in <module>
f.X
File "<pyshell#59>", line 4, in _get_x
return self.__x
AttributeError: 'FancyX' object has no attribute '_FancyX__x'
>>> f.X=3
setting X to 3
>>> f.X
getting X
3
>>> del f.X

Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
del f.X
AttributeError: can't delete attribute

>>> f.y

Traceback (most recent call last):
File "<pyshell#65>", line 1, in <module>
f.y
AttributeError: 'FancyX' object has no attribute 'y'
>>> f.y=4 # no property here
>>> f.y
4
>>> del f.y

Porter Woodward

Posts: 3
Nickname: woodie
Registered: Mar, 2003

Impedance Mismatch and Dual Schemas Posted: Sep 26, 2007 7:43 AM
Reply to this message Reply
Firstly - Rails is a good framework. If it wasn't so many people wouldn't be using it. It solves a problem in a way that people want it to be solved.

What people have to realize is that not everyone wants the problem solved that way.

One of the chief issues that I tend to see is (as someone has already observed) an impedance mismatch between object and data models. A good relational model is not necessarily a good object model. By placing the database schema in the primary position it's then in the driver's seat. And we typically see that with the MVC structure of Rails - there is typically a high degree of exposure of the schema all the way out to the view.

OO purists would probably hold that the Controller should be hiding the model (at least somewhat) from the view. Even better, the Controller probably shouldn't be having business logic all coded up in it.

Interestingly Hibernate comes with (and 3rd party tools are available) tools to induce a schema from an object model, or vise-versa. So it's entirely possible to not violate "DRY" even when using Hibernate. Additionally being explicit has some advantages - a few of my friends and co-workers who do work in Rails are occasionally irritated by the dynamic splicing in of methods and fields - and think it would be nice if you could more easily see them in the class definition.

The chief problem (which I alluded to with the MVC criticism) is that by placing the database schema in control as your "object model" you end up with deeply anemic objects; as the database doesn't encapsulate business logic or "object behavior" very well. Where does that end up living - should it live in the model? the controller?

It's a careful balance that needs to be struck on any given development project - between convention and explicitness. Sometimes the conventions need to be explicit.

Flat View: This topic has 18 replies on 2 pages [ 1  2 | » ]
Topic: New Meta-Programming APIs in Groovy 1.1 Previous Topic   Next Topic Topic: Actuate Sponsors BIRT Developer Exchange

Sponsored Links



Google
  Web Artima.com   

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