From: Paul S. <pau...@ne...> - 2002-02-06 22:44:56
|
My 2cents worth below. PaulS :) Doug Currie wrote: > Wednesday, February 06, 2002, 3:28:06 AM, Gavin wrote: > >>>Yes. I currently use Persistent in two ways. >>> >>>1. When computing the inheritance graph. As classes are added to the >>>set to be analyzed, I construct this graph (well, actually a set of >>>trees since Java is single inheritance). The lack of a Peristent >>>interface tells me when to stop climbing superclass links to insure >>>that all requisite classes are included >>> > >>I take it you mean you stop climbing the tree looking for _classes_. >>Properties from superclasses _should_ be included.... >> > > Ah. I did misunderstand this. I assumed properties of non-Persistent > classes were transient. I will fix it. > > <snip> > >>Another suggestion: >> > >>One possible hueristic that "solves" both problems is to see if something >>there looks like an ID property. If theres none, its a component or a >>non-persistent superclass. A command line switch could even set a list of >>property names the user uses for IDs. At the risk of over-comlicating what should be a simple task - could we use some kind of *simple* config file in addition to the command line settings (perhaps at a later stage when it's more stable)? One of the reasons that I like Hibernate so far is that it fits with my philosophy of toolset / framework design: simple things are easy, complex stuff is possible (to whatever degree the tool decides to comlicate itself). A lot of the discussion so far seems to go with this: wherever possible use reasonable defaults or make some reasonable assumptions about how people are going to write their code (e.g. they're always going to use the same attribute name for an ID attribute). But in this area I think it would be good to perhaps stretch this a little to maintain what I think is a really good design goal - you just point the tool at the code and *most* of the time "magic happens" and you've got persistence. And when you do something outside what the USB-attached-crystal-ball can cope with it's not traumatic to figure out how to deal with it. So maybe setting up some simple config options that are exceptions to the rules (like ID attribute names or sub-tree roots that we want to force into separate tables) life for the developer throughout the development cycle is still painless. Make code changes, run "ant all" and fire up my app each time I change something. > >>I kind of like this solution because it isolates as much possible >>dodgy guessfulness in one single rule that the user can understand and >>control, rather than having ten different rules that interact in wierd >>and unpredictable ways. >> > > I like it, too, especially for climbing the superclass chain, since > there is exactly one ID at its root that they all share. So, the user > can specify a class and an ID property (and optionally a generator) > and this completely specifies (a path through) the tree. > > If the user wants multiple subclasses from different paths in the same > table, a list of fringe subclasses could be specified with one ID > property. For example, using the notation X[Y,Z] where X is a direct > superclass of Y and Z, in A[B[C],D[E]] with A's ID specified... > > listing classes yields table > --------------- ------------ > B A{B} > E A{D{E}} > C,D A{B{C},D} > > I suppose it's possible to specify a different list of subclasses and > get another table with the same or different root class. For example, > for class E with D's ID, you'd get table D{E}. > > Now, I believe the rule is one table per class. > So this combination is legal: A{B} and D{E} > but this combination is illegal: A{B} and A{D{E}}. > Right? > > The current implementation would yield A{B,D{E}} in either case. But > if we add the extra ID argument, separate A{B} and D{E} tables becomes > possible. > > As far as using IDs for choosing between association and component, I > am not as happy, but at least it is something. > You could achieve the same by only specifying the exceptions to the rule, i.e. the roots of the *sub* trees. In this case D. > >>>Currently the following must be true of a class before it is added as >>>a persistent [super]class: >>>the class >>>C1. is not Primitive >>>C2. is not an Array >>>C3. is not an Interface >>>C4. is not nested (an inner class), i.e., c.getDeclaringClass() == null >>>C5. is not Abstract >>>C6. has a public default constructor (0 arguments) >>>C7. implements Persistent >>> > >>C3 I _guess_ is reasonable, though not essential. >> > > I don't think Interfaces can have properties unless they're > implemented in the concrete class. The real purpose of this rule is to > prevent command line specified Interfaces from appearing in the table. > The code would never find an Interface in the superclass chain.> > >> C5 I dont think is right. >> > > OK, I can easily remove it. What happens if the user tries to > instantiate an abstract class, e.g., with a query? > > >>C6 is changed to: it has a default constructor of any visibility level. >> > > OK. But perhaps a warning is in order (?) since private 0-arg > constructors usually signal non-instantiable classes. I disagree. >>From Java Lang Spec 2nd edition: > If the intent is simply to prevent instantiation of a class, the > proper way to express this is to declare a constructor (§8.8.8) of no > arguments, make it private, never invoke it, and declare no other > constructors. A class of this form usually contains class methods and > variables. The class Math is an example of a class that cannot be > instantiated The key phrase being "and declare no other constructors". It's common to NOT have a default constructor so that objects are forced into a "valid" state (from a business rule perspective) at creation. Sometimes a static helper method is used if this is complex, but that's *mostly* a hangover from C++ days when throwing exceptions in constructors was problematic. >>>Determining property roles is much more difficult. Currently I am >>>using the following heuristic >>> > <snip> > >>Nothing should default to Serializable. Its almost always a bad idea to >>store things in serialized form. (Unless they are, genuinely a stream >>of bytes. eg. a JPEG or something.) >> > > Agreed. I was lazy (Serializable is easy to determine, > component-izable isn't). I will fix the code. > > An administrative question for Gavin: > > Currently the MappingByReflection is implemented in a single Class > with several nested classes. Before tackling the above changes I > should probably refactor the code into a few top level classes; this > will facilitate its use by the eventual GUI tool and make maintenence > easier, I think. Can I claim package cirrus.hibernate.tools.reflect or > would you prefer it somewhere else? > > e > > > _______________________________________________ > Hibernate-devel mailing list > Hib...@li... > https://lists.sourceforge.net/lists/listinfo/hibernate-devel > > > |