File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes A complicated database design... Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "A complicated database design..." Watch "A complicated database design..." New topic
Author

A complicated database design...

Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18
I have the following design for my local/remote database, but it seems complicated...
1. Class Data implements interface DB as required by Sun
2. Interface Database that have all methods in DB and getMetaData(), all of them throws RemoteException
3. Interface LocalDatabase extends Database which overrides all methods in Database so that no RemoteException is thrown
4. Interface RemoteDatabase extends Database & Remote
5. Class LocalDatabaseImpl extends Data implements LocalDatabase
6. Class RemoteDatabaseImpl extends UnicastRemoteObject implements RemoteDatabase
7. Internally, RemoteDatabaseImpl delegates all requests to a LocalDatabaseImpl instance
8. Class RemoteDatabaseFactoryImpl, a factory binded to RMI registry for the RemoteDatabaseImpl
9. Adaptor Services at client side which has a reference to Database, either a local or remote one, to provide business methods
10. Client interacts with Services and be unaware of the nature of the database
All exceptions(remote or not) are caught in Services, and only the ServiceException is thrown from Services.
The same Services class is used for local/network mode, a violation of the requirement?
So many similar interfaces, which are confusing for a "junior programmer"...so marks deducted...?
what do you think?
Thanks!
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Hi Ryan,
My comments are interspersed in the following:
Originally posted by Ryan Tang:
I have the following design for my local/remote database, but it seems complicated...
1. Class Data implements interface DB as required by Sun
2. Interface Database that have all methods in DB and getMetaData(), all of them throws RemoteException
3. Interface LocalDatabase extends Database which overrides all methods in Database so that no RemoteException is thrown
4. Interface RemoteDatabase extends Database & Remote
5. Class LocalDatabaseImpl extends Data implements LocalDatabase
6. Class RemoteDatabaseImpl extends UnicastRemoteObject implements RemoteDatabase
7. Internally, RemoteDatabaseImpl delegates all requests to a LocalDatabaseImpl instance
8. Class RemoteDatabaseFactoryImpl, a factory binded to RMI registry for the RemoteDatabaseImpl
9. Adaptor Services at client side which has a reference to Database, either a local or remote one, to provide business methods
10. Client interacts with Services and be unaware of the nature of the database
All exceptions(remote or not) are caught in Services, and only the ServiceException is thrown from Services.
The same Services class is used for local/network mode, a violation of the requirement? No, it's
So many similar interfaces, which are confusing for a "junior programmer"...so marks deducted...? Yes, keep the ones and get rid of the ones.

I question the need for 3, 5, and 7. Possibly I just don't understand what value they add, but possibly they don't really add any value. I think 8 and 9 can probably be combined. 10 is a laudable goal and I think your design gets you there but I also believe you have some interfaces and implementation classes that may be excess baggage. My suggestion is to put into words exactly what each interface or class is buying for you. The ones that have a pretty weak justification are possible candidates for elimination. I think you're right to be concerned with the proliferation of interfaces and classes since they do make things harder to understand for any programmer, especially a junior one.
Hope this helps,
George
[ January 18, 2004: Message edited by: George Marinkovich ]

Regards, George
SCJP, SCJD, SCWCD, SCBCD
Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18
Hi George,
Thank you for your valuable comments!

I question the need for 3, 5, and 7. Possibly I just don't understand what value they add, but possibly they don't really add any value.

Why I do so? Because...
1. Restricted by the requirement, I must have the interface Database.
2. Much of the Database implementation is done by Data, but unfortunately, not all...
3. So I must have a class DatabaseImpl which extends Data and provide the additional implementation.
4. This DatabaseImpl should be used in remote mode, so I have my so-called delegation in point 7.
5. So in remote mode, Services has reference to the RemoteDatabaseImpl; in local mode, the DatabaseImpl.
6. But DatabaseImpl, used locally, has an interface that throws RemoteException(violation of the requirement?).
7. So I add the LocalDatabase, LocalDatabaseImpl...

I think 8 and 9 can probably be combined.

Based on my understanding (I hope it is right) on this thread, I choose to have point 8 & 9 being separated.

10 is a laudable goal and I think your design gets you there

Yes, I also want to have my UI not required to catch so many exceptions, but only a simple one by using exception chaining.
Trym Moeller
Greenhorn

Joined: Nov 25, 2003
Posts: 10
Ryan Tang: I have implemented the RemoteDatabase as you have delegating to the LocalDatabase.
George Marinkovich: And I don't see, what is wrong with this approach, can you please elaborate on this. Thanks in advance.
Regards, Trym
[ January 19, 2004: Message edited by: Trym Moeller ]
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Hi Ryan,
Thanks for the additional information. I'll comment on the new stuff first and then revisit the original points.

1. Restricted by the requirement, I must have the interface Database.
So Database represents your common database interface (for both common and remote access).
2. Much of the Database implementation is done by Data, but unfortunately, not all...
But Data could implement everything in Database, couldn't it? Not doing so is a design decision, but it results in your design having another interface that wouldn't be needed if Data fully implemented everything in Database. You said your design seemed a little complicated and I'm just saying that this seems like an opportunity for possibly getting rid of an (extra) interface (that may not be needed).
3. So I must have a class DatabaseImpl which extends Data and provide the additional implementation.
It's one way of doing it but as stated above it comes at the cost of having an additional interface and implementation. Maybe you think it makes Data easier to understand, and if so, then you should keep it.
4. This DatabaseImpl should be used in remote mode, so I have my so-called delegation in point 7.
I didn't mean to say anything against delegation, I really meant to say you could delegate to Data (if it implemented everything itself) rather than to DatabaseImpl.
5. So in remote mode, Services has reference to the RemoteDatabaseImpl; in local mode, the DatabaseImpl.
Instead of DatabaseImpl it could be Data, couldn't it?
6. But DatabaseImpl, used locally, has an interface that throws RemoteException(violation of the requirement?).
Maybe Database could throw IOException, then it could truly function as the base interface for local and remote database access. It would be the direct interface for the local database access. And a remote database access interface could extend Database and Remote.
7. So I add the LocalDatabase, LocalDatabaseImpl...
There's nothing wrong with having LocalDatabase and LocalDatabaseImpl, but if you're telling me you're concerned about the complexity of your design I'm saying that these seem to me to be candidates for elimination. If you are comfortable with the rationales for having LocalDatabase and LocalDatabaseImpl, then that's a defensible position, and you should feel better about the complexity. In that case, the design wounldn't be too complex, it would be just complex enough.
I have the following design for my local/remote database, but it seems complicated...
1. Class Data implements interface DB as required by Sun
Agree.
2. Interface Database that have all methods in DB and getMetaData(), all of them throws RemoteException
Maybe it could throw IOException if you want it serve as the common interface for both local and remote database access.
3. Interface LocalDatabase extends Database which overrides all methods in Database so that no RemoteException is thrown
If you accept the suggestion in 3, then perhaps this is no longer a problem.
4. Interface RemoteDatabase extends Database & Remote
Agree.
5. Class LocalDatabaseImpl extends Data implements LocalDatabase
Only necessary if your Data class doesn't already do it.
6. Class RemoteDatabaseImpl extends UnicastRemoteObject implements RemoteDatabase
Agree.
7. Internally, RemoteDatabaseImpl delegates all requests to a LocalDatabaseImpl instance
It could delegate to Data.
8. Class RemoteDatabaseFactoryImpl, a factory binded to RMI registry for the RemoteDatabaseImpl
I may have misunderstood what you were trying to do here. It may not be as closely related to 9 as I thought. If you say that RemoteDatabaseFactoryImpl gives you an object that implements RemoteDatabase (which itself implements Database), then I have no objection.
9. Adaptor Services at client side which has a reference to Database, either a local or remote one, to provide business methods
Is this the Controller from the MVC pattern? If so, again no objection.
10. Client interacts with Services and be unaware of the nature of the database
Still sounds good.[b]

Ideally, I think the assignment should require two interfaces: a base (local) and a remote interface. However, we've been given a DB interface by Sun that is really not suitable as the base (local interface) largely because of RMI implementation requirements, so one option is to create a common base interface that can serve as the interface to the local database and a parent interface for the interface to the remote database. I think your design has four interfaces, which is one more than I thought was necessary. Therefore, I would be tempted to eliminate what I regard as an unncessary interface. The "extra" interface isn't wrong (it just never occurred to me to use it). If you think it's necessary then I think you could make a good case for that. It's just not where my bias lies. All things being equal, there's probably less complexity in a three interface design versus a four interface design. However, all things rarely are equal and you may feel that there are benefits to having the extra interface that outweigh any neglible increase in complexity.
In my opinion the most important thing in this exam is that you understand your solution enough to make a strong case for it. I think that's even more important than having the most optimal solution (whatever that is). In other words, a reasonable solution that you can intelligently explain because you completely understand why you designed it that way, trumps a perhaps better (or perhaps not) solution that you don't understand as well and therefore are not in a position to give as strong an explanation of why you are using it.
Hope this helps,
George
[ January 19, 2004: Message edited by: George Marinkovich ]
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Hi Trym,
Originally posted by Trym Moeller:
Ryan Tang: I have implemented the RemoteDatabase as you have delegating to the LocalDatabase.
George Marinkovich: And I don't see, what is wrong with this approach, can you please elaborate on this.[ January 19, 2004: Message edited by: Trym Moeller ]

I wasn't very clear about what I didn't like about the delegation. The delegation is fine, I just didn't understand why Ryan was delegating to LocalDatabase rather than Database. After his explanation it's clear to me why he was doing it that way. All I meant to suggest was that delegating to Database (implemented by Data) would remove a layer of interface that I don't think is required. Other people could (and probably do) reasonably disagree with my opinion on this. I was trying to minimize the number of interfaces in my own project so Ryan's solution (the LocalDatabase, LocalDatabseImpl stuff) never crossed my mind. It might have some points in its favor, but again I never thought about doing it that way, so the benefits don't come immediately to mind.
What follows is just a general comment and is not addressed specifically to anything Ryan or you said:
In my opinion a reasonable design that pays proper attention to all the requirements (especially musts), is well understood by the candidate, and soundly implemented is what gets a high score. This is not to say that people who have more complicated, elaborate, and sophisticated designs that solve problems beyond the scope of the assignment aren't rewarded for their effort. But their reward is the experience and knowledge that they've gained and doesn't necessarily come in the form of higher scores.
Hope this helps,
George
Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18
Hi George,
But Data could implement everything in Database, couldn't it?

Sorry but I am not sure about what you mean. Do you mean having the getMetaData() method implemented in Data, but with...

Then how can my Services class has reference to Data via the Database interface?

Thank you again for your help!
Trym Moeller
Greenhorn

Joined: Nov 25, 2003
Posts: 10
Hi George
You cleared things up thanks. I agree with you about the simpler the better.
Regards, Trym
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Hi Ryan,
Here are some thoughts about the interfaces in the assignment:
1. DBMain (or whatever your Sun supplied interface is called) cannot be changed and it defines the basic database operations that you must allow to be performed on the database.
2. If you're using RMI and you find that you can extend DBMain for use as your remote database interface, then do it.
3. If you find DBMain is unsuitable for the purpose mentioned in 2 then it seems to me you're going to need another interface that is suitable.
4. It also seems to me that your new interface had better honor all the database operation promises made in DBMain.
5. The fact that the new interface is providing all the database operations promised in DBMain does not mean that it can't make other promises too (like something to get the metadata, perhaps).
6. Likewise, just because Data implements DBMain doesn't mean it can't do more.
7. In reference to the second question in your post here's something to think about. Given:

The following compiles:

and outputs:

Notice that B_class wasn't explicitly declared to implement A_interface, yet, in fact it does.
Hope this helps,
George
[ January 20, 2004: Message edited by: George Marinkovich ]
Ryan Tang
Greenhorn

Joined: Aug 20, 2003
Posts: 18
Hi George,
Thank you for your help! I also find that I can have...

provided that the implementation throws exceptions no more than that declared in any one of the implemented interfaces.
I think I will go into this approach to simplify my design.
Vishwa Kumba
Ranch Hand

Joined: Aug 27, 2003
Posts: 1066
Sorry George,
I am new to SCJD and still trying to understand this thread. But I didn't quite catch your example. The foll. code gives me a compile time error!

and the error is

Am I missing something here?
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Hi Vish,
Sorry. Maybe this will teach me not to post example code that I haven't actually compiled.
Yes, you are missing something, or rather the code that I posted is missing something rather important -- a cast. I've added it to the code below (it's in bold). Thanks for catching the error. It's embarassing because it wasn't a minor error, it was the whole point of the example.
Vishwa Kumba
Ranch Hand

Joined: Aug 27, 2003
Posts: 1066
thanks George!...
Now the code compiles, but I am getting a runtime exception(ClassCastException) now. No worries. I haven't understood the complete thread but will go thru it in detail later.
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Hi Vish,
Sorry. Maybe this will teach me not to post example code that I haven't actually run.
Actually it turns out there's a very good reason why we're having so much trouble with this example. Unfortunately, the entire point I was trying to make with this example is just WRONG. Even though a class "implicitly implements an interface" it's still not part of that inheritance hierarchy and attempting to do what I did in the posted code WILL NOT WORK. In fact, "implicitly implementing an interface" is apparently a figment of my imagination (but one that I really believed). (I feel like John Nash in "A Beautiful Mind" -- just the delusional part, not the brilliant part.) There's no such thing as implicitly implementing an interface; either you do implement an interface explicitly (using the Java keyword "implementing"), or you don't. Again, there's no such thing as implicitly implementing an interface (but it seemed so real!).
Fortunately for me, I didn't make this mistake in my project code. However, when I constructed the simplified example from my project code, the "implicitly implementing an interface" delusion took hold and I posted that truly awful code sample, which not only didn't compile (as written), but couldn't possibly have run if it had compiled. Thank you for pointing out the problem since it gives me an opportunity to apologize for the bad information and correct the example.
This example actually compiles and runs

and produces this output:

So, the point I'm trying to make now is that you can instantiate two objects (a and b) that implement two different interfaces (a_interface and b_interface), and because the two different interfaces exist in the same inheritence hierarchy (b_interface extends a_interface), one can invoke the method of the base interface (a_interface.method()) on either object (a.method() and b.method()).
So what? Well, if the A_interface is your common (local and remote) database access interface, if the B_interface is your remote database access interface, if A_class is the local database access class, and B_class is the remote database access class, then a client can declare a variable of the common database access interface, and assign an object to that variable that instantiates either the local database access or the remote database access class, depending on whether the database is local or remote. From that point on all the client database access calls can be made using the common database access interface. This allows the client code to be written the same regardless of whether the database is local or remote. This is very useful for the project because if you can write client code regardless of whether the database is local or remote then the same code can be used to support database access for standalone and network client operating modes.
Vishwa Kumba
Ranch Hand

Joined: Aug 27, 2003
Posts: 1066
John Nash? I always imagined that only the brilliant people had delusions as they have a beautiful mind.
Cheers George, for the detailed explanation. I am not sure if I can appreciate Ryan's 4 interface. But I am content with the approach of having the 3 interfaces and accessing the different client implementations
with the super interface containing the common methods.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: A complicated database design...