Meaningless Drivel is fun!*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Excess functionality? 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 "Excess functionality?" Watch "Excess functionality?" New topic
Author

Excess functionality?

Mag Hoehme
Ranch Hand

Joined: Apr 07, 2002
Posts: 194
Hi,
in my assingment I am supposed to write a database client (which has to implement the same public classes as the database), and a GUI.
I am wondering whether I am adding too much extra functionality when I am implementing the following methods/functionalities:
1. an application specific method such as
public boolean book (int recno, int seats)
throws RemoteException, DatabaseException, BookingException;
Reason: "Booking" is a special kind of modification that involves only one data field.
2. a more elaborate modification method such as

to supplement the provided

Reason: I want to compare the original data to the database before writing the modifications to the database. I want to make sure that it is not possible to inadvertantly overwrite someone else's modifications.
If a ModificationException is thrown, the GUI will prompt the user and ask him to reload the data and modifying it again.
However, this design requires that I am keeping copies of the original records and submit them together with the modified records.
3. a callback mechanism for loading records:
Instead of returning an array of records, the records are individually passed to the client, which then adds them to the model.
Reason: Increasing the perceived performance.
I wonder whether this overhead associated with these features is within the assingment - or whether I am incurring the risk of being penalized for unrequired features.
Any comments are welcome.


Mag
Mike Piotrowski
Ranch Hand

Joined: Apr 24, 2002
Posts: 82
Mag,
I see no need to worry about any of that. As you said all that may happen is opening yourself up for deductions. Keep things simple and you will due fine. Just remember you have to make the decision and defend you reason. Good luck.
Mike
Michael Morris
Ranch Hand

Joined: Jan 30, 2002
Posts: 3451
Hi Mag,

1. an application specific method such as
public boolean book (int recno, int seats)
throws RemoteException, DatabaseException, BookingException;
Reason: "Booking" is a special kind of modification that involves only one data field.

Actually most have done that inside a Facade. There the facade hides the complexity of a booking operation from the client. You could implement this method inside Data or a subclass, but that really is not the responsibilty of the Data class. I feel that Data's limited scope is simply data retrieval, record modification/addition/deletion, and persistence.

Reason: I want to compare the original data to the database before writing the modifications to the database. I want to make sure that it is not possible to inadvertantly overwrite someone else's modifications.
If a ModificationException is thrown, the GUI will prompt the user and ask him to reload the data and modifying it again.

I'm confused here. Isn't that what locking is for?
Maybe I'm missing something, if you could elaborate as to the necessity of this (maybe paint me a picture) I would appreciate it.

3. a callback mechanism for loading records:
Instead of returning an array of records, the records are individually passed to the client, which then adds them to the model.
Reason: Increasing the perceived performance.

I think that's a pretty good idea. I wish I had considered it. But do remember, that performance alone is not a justification for this assignment.
Hope this helps,
Michael Morris
[ August 27, 2002: Message edited by: Michael Morris ]

Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius - and a lot of courage - to move in the opposite direction. - Ernst F. Schumacher
Mag Hoehme
Ranch Hand

Joined: Apr 07, 2002
Posts: 194
Hi Morris,
your answer is really a help to me! Thank you.
For the booking method:
I have a server called "DataAccess", which in turn has an instance of the Data.class. I feel that DataAccess is some kind of Facade to Data, and thus the appropriate place for business methods like book (int recno, int seats). In my design Data has only basic database functions.
What I am not so sure about is whether I should have a single instance of Data, which is accessed by all existing DataAccess servers, or have an instance of Data for each DataAccess server.
Any comments on this are welcome!!!
For the Modification:
I have the following use case in mind:
  • Branch Office 1 connects and loads all records.
  • Branch Office 2 connects and loads all records.
  • Branch Office 1 corrects a typo in a record and saves the modification.
  • Branch Office 2 modifies the same record and wants to save the modification. Since Branch Office 2 has not reloaded the data, they do not know about the modification Branch Office 2 has submitted.

  • I think that real-life applications must deal with such a use case. I can think of the following solutions, and I am not so sure how to deal with it in a more or less contrieved assignment application:
  • Don't care. Let Branch Office 2 overwrite the modifications of Branch Office 1.
  • (a) copy the record before the user modifies it in the client; (b) send the copy and the modified record to the server; (c) lock the record in question; (d) compare the copy to the database; (e) if the data is the same, modify the record and unlock it, otherwise throw an Exception to inform the user that the record was already modified.
  • allow only the manager to modify data (which would require authentification).


  • On the callback functionality and performance:
    I think that callbacks are a perfectly standard solution. But I am not so sure about this.
    And finally, the LockManager:
    While I am writing this, I have the idea of using the reference of the current thread as an ID within the lock manager! (I hope it's a good idea.)
    Thank you very much for your help!
    [ August 27, 2002: Message edited by: Mag Hoehme ]
    Michael Morris
    Ranch Hand

    Joined: Jan 30, 2002
    Posts: 3451
    Hi Mag,

    What I am not so sure about is whether I should have a single instance of Data, which is accessed by all existing DataAccess servers, or have an instance of Data for each DataAccess server.
    Any comments on this are welcome!!!

    I and probably most used a single instance of Data which greatly simplifies design. If you a have a specific solution in mind though that requires multiple instances then that's probably OK too. I did have a DataFactory class which mapped files to Data objects, so that different "tables" could be used, but there was still only one Data instance per file.

    For the Modification:
    I have the following use case in mind:
    ...
    I think that real-life applications must deal with such a use case.

    I think that you should probably forget about this since if such a use case were necessary, it would be spelled out in the requirements. First rule of preliminary design: Don't add use cases that aren't explicitly required. If you discover implied use cases at the intermediate stage so be it, but don't solve a problem that does not exist.

    On the callback functionality and performance:
    I think that callbacks are a perfectly standard solution. But I am not so sure about this.

    You can use a messaging system based on a publish-subscribe pattern. I used java.beans PropertyChangeListener and PropertyChangeSupport to keep most of my client classes decoupled from one another yet remain in sync by receiving and dispatching messages. This message paradigm is similar to UDP in that you just "fire" it and forget about it. Another alternative would be to use an Observer pattern, calling update on the Observer each time a new record came in. One final possibility would be to create an event (by extending EventObject) and creating an event based system with addXXXeventListener(), removeXXXeventListener(), and of course whatever callback method(s).

    And finally, the LockManager:
    While I am writing this, I have the idea of using the reference of the current thread as an ID within the lock manager! (I hope it's a good idea.)

    Not a good idea if you're using RMI. There is no guarantee of a one-to-one mapping of remote invocations to threads. In other words the same client may use two different threads to make two different calls or it may use the same thread throughout. I am not sure and probably shouldn't make this statement, but I presume that RMI is using some sort of thread pooling scheme. If that's the case then two different clients could use the same thread to make calls on different remote objects.
    Hope this helps,
    Michael Morris
    Michael Morris
    Ranch Hand

    Joined: Jan 30, 2002
    Posts: 3451
    It occurred to me during lunch (sometimes I'm pretty slow) that if you have multiple Data instances representing the same table, that Data's RandomAccessFile will need to be static. Controlling access to it may be a nightmare. It would certainly involve a lot of added code and there would be a high probability of dead lock if you aren't very careful. So, unless you are extemely daring, I would advise going with a single Data instance.
    Michael Morris
    George Lawniczak
    Greenhorn

    Joined: Aug 12, 2002
    Posts: 27
    What I did was to create a database abstraction layer that basically contained four methods: create,update,delete and insert. I also make the lock and unlock methods available to the business layer. I passed in HashMaps for each method. I left it the the layer to figure out how to format the database call (DataInfo, query statement creation).
    I have a separate business layer that calls the database abstraction, so in my Flight Business object, I would actually call update(HashMap values, HashMap whereClause), or Read (HashMap whereClause). WhereClause is a series of key/values corresponding to the records I want updated, and the values HashMap has the column and the value I want to update that column with in the updated records. I kind of use that as a primitive form of SQL. It allows me to conceivably update multiple rows at once.
    So for example, to retrieve all the records that have Dallas as its origin, I would put("Origin airport","DAL") into the HashMap and then pass this HashMap to the Read function in the data abstration layer. I created a resultSet object that holds an array of column names, as well as a String array of the data.
    This is what the Read function passes back to my business object. So my business object knows nothing about the Data object or the DataInfo classes.

    My business object has no knowledge of the client, it could be a Swing app, or a Servlet, whatever. That's why I make the method return a result set, instead of updating the Model directly there. The controller calls the business object method (Book, Search etc.) The controller then updates the JTable model using the contents of my result set object.
    My rationale for using the database abstraction layer is that it hides the complexity of the actual Data object from the business coder. He
    doesn't have to know anything about DataInfo, just call a basic "CRUD" method, passing in the appropriate HashMap objects. Therefore I could conceivably swap out the database, and in my abstraction layer, use JDBC calls, without having to change my code in the Business object.

    One thing that I am not comfortable with is how I do the updates in my business logic, I actually call "lock" and "unlock" in my business object, because it is difficult in the database abstraction layer to distinguish when I wish to read with a lock because I am in the process of updating, or just doing a basic read. I want to inspect the number of available seats and compare it to the number the user entered, this is only possible, if I first call "lock", then read. Of course I need to calculate the new number of available seats as well, and pass that value back to my update function. Thus, I performed that calculation also in my business object. Of course in my business object I have a "finally" clause that calls the unlock method.
    Maybe this approach is a bit much for this project, but it works, and it facilitates expansion of the application to encompass perhaps other tables, or databases.
    Michael Morris
    Ranch Hand

    Joined: Jan 30, 2002
    Posts: 3451

    Originally posted by George Lawniczak
    Maybe this approach is a bit much for this project, but it works, and it facilitates expansion of the application to encompass perhaps other tables, or databases.

    I think it's a great approach. You have already articulated your reasoning for this design and convinced me of it's merit. I'm sure that the assesor will like it too. The more abstraction you have the better in my opinion for the reasons you mentioned especially in the ability to change the various components. I also did some things that were "a bit much" but think I got a better score because of it.
    One potential flaw is that you are creating a proprietary protocol for communicating with the abstraction layer. Not that that is necessarily a bad thing, but such communication schemes can become untenable over time and be difficult to extend. All in all though, as I stated earlier, I think it's a great approach.

    Michael Morris
    [ August 27, 2002: Message edited by: Michael Morris ]
    George Lawniczak
    Greenhorn

    Joined: Aug 12, 2002
    Posts: 27
    One potential flaw is that you are creating a proprietary protocol for communicating with the abstraction layer. Not that that is necessarily a bad thing, but such communication schemes can become untenable over time and be difficult to extend. All in all though, as I stated earlier, I think it's a great approach.

    I admit I am not sure about this either, I toyed with the idea of just creating a standard SQL query, that could easily be fit to a JDBC statement call, but then again even SQL is proprietary to some degree. If there was a way to incorporate JDBC into this database, I would have loved to have done it, but short of writing my own JDBC driver (which is way beyond this project), I don't see how to do that.
    I tried to think in terms of, what if other applications wanted to use this database framework, how could I remove much of the complexity, and reuse the logic to perform standard "CRUD" functions. So this is what I came up with.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Excess functionality?