[Opensource] DBObject vs. JDBCDataObject [was
dbobject.getTargetTable() deprecation [REALLY LONG WINDED :)]
larry hamel
expresso at codeguild.com
Mon Jul 28 10:45:25 PDT 2003
thanks, that gives me a broader perspective. I'm 100% OK with deprecating the method.
Let me ask a question that grows out of this discussion, just for clarification.
Here's what I understand so far about the new hierarchy:
DataObject is the general superclass
JDBCDataObject is a subclass for JDBC
DBObject subclasses JDBCDataObject
What is the purpose of DBObject relative to JDBCDataObject? In other words, what parts of DBObject could not be put in either the general DataObject or the less general JDBCDataObject?
the Javadoc for DBObject reflects its former mission, which is now accomplished by its superclasses, it seems:
<p>DBObjects are the pure core of the Expresso framework. They are object oriented
* wrappers for some sort of data. Currently they are used for database tables,
* but in the future, they will be designed to grab any sort of managed data
* source.</p>
thanks,
larry
At 03:39 AM 7/27/2003, you wrote:
>At 03:48 PM 7/25/2003 -0700, you wrote:
>
>>Okay, thanks for the clarification.
>>
>>so DBObject subclasses JDBCDataObject, and thereby has the inherited method
>>
>> public final JDBCObjectMetaData getJDBCMetaData() {
>> return (JDBCObjectMetaData)getMetaData();
>> }
>>
>>Will this break for DBobjects which are not using JDBC?
>
>DBObjects that aren't using JDBC will only implement DataObject and not JDBCDataObject. So at that point, getTargetTable() will be unavailable since it wouldn't necessarily make sense.
>
>Let me clarify why I keep saying this :) Time for a Expresso 5.1 development history lesson:
>
>There's much need for DBObjects to be able to expand to beyond the straight JDBC realm. An example is hooking into IBMs MessageQueue system. Entity EJBs would be another. But I won't continue beating a dead horse on whether we need it or not.
>
>So the obvious thing was that we needed an Interface to define DBObjects and use implementation of interfaces to allow for interaction with the various sources. But what to include?? I must have sat down on what to include in this interface maybe 10 times. But I kept hitting a wall: DBObject has, at my last count, about 125 Methods(!!) Talk about superclass anti-pattern!! That sure didn't allow me to easily figure out what was important. [I should add that I was not the first developer to attempt an interface extraction, but previous attempts had all failed. ]
>
>So a couple of months ago, an idea hit me and I took a different tact. I reimplemented DBMaint and it's classes to accept DataObjects instead of DBObjects. I figured that since DBMaint allows you to do basically what any 'outside' client of DBObjects would want to do in a generic way, this would give me a good idea of what was important for the Interface. My goal was to provide a series of functions that would still give me the same functionality as before, even if it was called slightly differently.
>
>That was the primary effort that bore the current DataObject API as you see today.
>
>The second step to test the API was to create a new type of DataObject that DBMaint could use. So I created the class:
>
>com.jcorporate.expresso.core.dataobjects.jdbc.JoinedDataObject
>
>This was a rewrite of MultiDBObject that was XML configurable and more importantly, implemented the DataObject API in such a way that you could see database joins through the DataObject right smack dab in DBMaint.
>
>Although it wasn't a trivial task, it took me about 2 weeks working 1/2 days on it; the API basically stood as-is. I added a couple of more 'optional' interfaces such as Securable and Defineable that took care of some specific issues such as how do you differentiate classes that are defined differently through XML config files, but have the exact same classname. It was here that I believe that the API had some legs to stand on.
>
>So why am I telling all you guys (and gals!) this? Well I found out something:
>
>- There seem to be two different 'views' to DBObject programming: (a) Programming from within DBObjects [such as overriding add(), etc] and (b) From 'outside' the DBObject, ie calling DBObject.add() from your controller.
>
>The net result is that from 'outside'... I NEVER call getTargetTable(). On the inside? I do it all the time. So by and large, the 'outside' controller could give a rip whether the DataObject is JDBC based or not. [I say, by and large] However, there are times when I have VERY JDBC specific needs. So what do I do? I have in my parameters JDBCDataObject instead of DataObject! Plain and simple. It may limit my options for non-JDBC environments for the classes that use this, BUT the point is that if I'm dropping to lower level JDBC-style objects, then I probably have a good reason for it, and want to exploit a JDBC specific feature.
>
>For example, JoinedDataObject HARDLY makes sense for anything outside of the JDBC realm. So I feel free on its inner code to pass JDBCDataObjects to and fro. But that's on the inside and it still doesn't break the DataObject API contract, and thus DBMaint can still use it!
>
>>Anyway, this is exactly the kind of convenience that I'm looking for. could we redefine getTargetTable() as
>>
>> public String getTargetTable()
>> throws DBException {
>> return getJDBCMetaData().getTargetTable();
>> }
>
>Sure... at this point, getDef and getJDBCMetaData() are essentially synonyms with getDef eventually being removed. Of course I still want DBObject.getTargetTable() as deprecated.
>
>>Whatever protection is necessary to allow getJDBCMetaData() to be accessible from any DBobject could be reused for getTargetTable(), no? shall we introduce some NotImplemented exception, testing with instanceof?
>
>Again, usually only the DataObject _implementation_ would ever need getTargetTable() except for a few super minor cases. The way I see getting the 80% case is to deal with JDBCDataObjects in your parameters where you NEED it, use DataObject where you don't. You'll start finding entire subsystems that don't NEED it and thus we slowly ween ourselves away from API bloat.
>
>After all, the DataObject API is going to ALWAYS be a case of sometimes dealing with the base interface, sometimes dealing with lower level implementations. It wouldn't be, as Raul so kindly put it, "lightening fast", if we tried to apply the same API for all types of data sources. We would loose power. After all, JDBC folks still want to specify "distinct rows" and "custom where clauses" in their queries. Part of Expresso's power and usability is the ability to drop down to lower level stuff when you need it, use the higher abstractions when they work better.
>
>So even in a full fledged API. DataObject will be the least common denominator, JDBCDataObject will have JDBC-specific additions, EJBDataObject will have Entity Bean-specific additions, and CSVDataObject will have Flat File specific additions. If we tried to move all the 'cool functions' to the base class, we suddenly have bloat in DataObject and it becomes nearly impossible to implement a class based upon DataObject. So that's why I don't believe getTargetTable() should be moved up to DataObjectMetaData, I think it does very well in JDBCObjectMetaData, and I provide the convenience for those that are working in the JDBC realm.
>
>Make sense?
>
>I'd also like to add something to those folks that have been astutely watching (or even might not be! :) ) may have been wondering about. There have been a LARGE number of functions @deprecated [I think about 30 at this point in time]. If you look at the functions that were marked deprecated, you'll see that by and large the implementation was something like:
>
>getDef().getDescription(); or something like that.
>
>Since the DataObject API provides a 'Metadata' interface, the underlying class that represented all the metadata about the DBObject now exposes that interface publicly. [Man, what kind of a list are we talking about public exposure and all! :) .....(Hey, it's late! If you don't like the jokes just skip 'em! ;) ) ]
>
>So now you have to use: DataObject.getMetaData().getDescription() instead of DBObject.getDescription(). Now that may sound like a typing pain in the rear, but there's something specific I want to point out.
>
>Remember the old implementation of DBObject.getDescription()? It called a function called getDef(). Now that function performed a concurrent reader HashMap lookup. Now hashmap lookups may be fast.... BUT! I've seen enough abuse of things like getTargetTable() and getDescription(), that the hashmap read to get the metadata is now showing up on the "profiling radar", taking, perhaps 3-5% CPU time in the requests.
>
>Now 3-5% CPU time may not be much. But if instead of just calling getDescription() and getThis and getThat whenever you needed it you did:
>
>JDBCObjectMetaData metaData = myObj.getJdbcMetaData();
>metaData.getDescription();
>metaData.getThis();
>metaData.getThat();
>.....
>
>You've just saved yourself 2 synchronizing hashmap lookups! Now, this is contrived, but I find many areas where the number of hashmap lookups was much more serious than 2. And using this method is a quick and EASY way to get the hashmap lookup to drop off the CPU chart once again.
>
>[The good news is that Expresso is getting optimized enough in many areas where multiple hashmap lookups ARE showing up on the radar now! I'm getting happy ;)]
>
>So there you have it, probably more about Expresso DataObjects than you ever wanted to know. :) (Sure wish I had an editor to take these long winded posts I do and put it into the doc set! <grin>) So I guess the next question is, does this answer your concerns or should I write another 10 MB post :)
>
> -Mike
>
>_______________________________________________
>Opensource mailing list
>Opensource at jcorporate.com
>http://mail.jcorporate.com/mailman/listinfo/opensource
>Archives: http://mail.jcorporate.com/pipermail/opensource/
More information about the Opensource
mailing list