I wrote my own DBFile-class, which manipulates data in the database file directly.
This DBFile-class works with a Record class (which is the representation of each record in the database file), but Data class operates with String arrays only, what is more primitive.
(The Record class can convert it self to String array and other way round from String array to an Record instance.)
I prefer the using of the Record class.
But if I start to convert the Record (in the DBFile) to an String array for the Data class and than convert this String array back to an Record instance in any other class which is using Data-class...
It looks not nice...
Can anybody give me some nice advice how can I solve this embarrassment?
Thanks in advance!
For my assignment in the DB interface I got from Sun to be implemented by my Data class
all the methods signature in the DB interface deal with String, therefore my Data class only knows
I created a Business Service Layer and there I created a Room Value Object that it is the representation
of the Data class String. My Room object only contains String, int and boolean.
In my Business Service Layer I convert String to Room and viceversa.
My GUI only deals with Room objects. This came handy to render booleans as a checkbox in my JTable.
My goal was to make my Data class as generic, reusable and loosely coupled as possible so it can be
used as a Data Access Object in other application domains different than a
Hotel Room Discount Broker.
Originally, my Data class had knowledge of a Room class, but after some thought I decided that it should not
have any knowledge of any other classes and to make it generic and reusable I decided it must only use String
as indicated in the signature of the methods in my DB interface to be implemented as a must requirement.
I don't think using a Record class in your Data class (or FileDB class) has any added value to your solution, because the interface you have to implement contains nothing more but String, so you are practically doing more conversions between Record and String (and the other way around) than actual logic.
Using a value object / transfer object on the client side (and in your business service, if you are planning to have one) has lots more of added value: simpler, less error prone, nice (built-in) rendering of the JTable,...
The only field updated in my GUI is the owner record - to make it flexible, I look up what column the 'owner' is, before updating the record. That way you can update the record even if the owner column shifts around between datasets. If it can't find the owner column, it throws an Exception. This has the benefit of flexibility - this is now a generic reader, that can read and update any data file that has the same file header as my database, and an owner column.
My project has not been graded yet - I'm going to submit it tomorrow though, and start my 6-week countdown timer.
My Data class is generic: you can read any database file with the same structure as the database file I had for the assignment, but of course it can have totally other (number of) fields. But the GUI in my case is especially designed for the room management (searching and deleting). Because in my opinion there is little added value in looking for an owner column if you simply have to take care of the customer management (name, address, city, country, telephone and email for example).
Let's say you have a database with 3 fields - hotel name, location, and owner....
and a database with these four fields: owner, hotel name, location, number of pets.
If you hard code '2' as the field to update, you will mess up your database when you go to update the second database. By saying 'get me the index of column owner', and using that dynamically-retrieved index as the column number to update, the same program will update both databases correctly.
If I were to beef this up to include updating all the fields, not just the owner, I would use the generic 'retrieve the column index for this string' method on ALL the columns.
Flexibility won out for me over business objects, for this small app. But business objects win out for larger, more complex apps, certainly.
But I didn't refuse completely using of the Record class, so class has private methods working with the Record objects.
Principle the Record class is an String array plus "deleted" flag and several methods...
By the way, my DBFile works closely with a Header class which has an information about the database structure and helps to sort information in our String arrays. Here I avoided partially the hardcoding.
On the business layer I work with a Room class which extends the Record class and has special methods.
Here I use hardcoding (getOwner/setOwner) because business layer lose the contact with low layer through Data class
In principle we can always say that the order of fields is specified in the task (see "Database schema" part).
Therefore I would say exactly in this case hardcoding may be the bad idea, but worse is to lose the time and make from your code a moster code.
And because I use a transfer object I also don't use getters and setters, just public data members.
And to pick up the discussion about the hard coding part in the assignment. Obviously the fewer you have to hard code, the better. But sometimes there is (in my opinion) not another choice: I'm curious about how you will develop the JTable (and eventually search criteria) if you don't use hard coding (what I did). And what if business rules require a complete other column order than in your database file.
Roel De Nijs wrote:And to pick up the discussion about the hard coding part in the assignment. Obviously the fewer you have to hard code, the better. But sometimes there is (in my opinion) not another choice: I'm curious about how you will develop the JTable (and eventually search criteria) if you don't use hard coding (what I did). And what if business rules require a complete other column order than in your database file.
I meant in my design in the Data class, since that's where he is asking originally. In my case
I read all of that directly from the schema in the database file.
In my Room class, I did have to define constants for the indexes when I convert String<->Room and also for the maximum lengths of each field
to be validated by the GUI (Book Room Dialog).
Why do you see a problem in the serializable hierarchy Record-Room and having any getter-setter methods in the serializable class?
If a write one initialized serialized object Room with data inside to file - it has 234 bytes.
Where approximately 60 bytes is an information about current room (hotel name, location, etc.)
Approximately 100 bytes is a description about all fields of both classes Room and Record.
The rest is the path to Room and Record classes.
I could make it smaller with renaming long field names to short abreviations.
For example if we rename field "recordNumberInTheDatabase" just to "number", we economize 19 bytes...
But we cannot make the serialized object smaller if we refuse to to use methods, because serialized object has no information about any method, just values for all fields and fields descriptions.
I do have a problem with extending the Record class, but it's just a minor problem from a design point of view. Not that it would cause your program not to run/compile. First of all I think you should keep seperate layers apart. You have a db layer, eventually a business layer and a representation layer. In my application no classes (even no exception) of the db package is propagated down to the gui. In my business service I catch the db exception and throw a business service exception, this exception is caught on the client. Secondly by inheriting from Record object your Room object may inherit properties which are of no use (like the status flag)
Another issue with your approach: why does your Record object has a status flag? I don't think the status flag is part of a record. If your flag indicates a deleted record, there is simply no record because it is deleted! So why would you create a Record object for a record that does not exist at all. If you compare with a RDBMS: if you execute delete from rooms where id = 1 statement, the record is simply gone and it does not exist anymore.
Just my 2 cents.
Thank you for your description, it makes me thoughtful.
I'll try to keep these layers separate.
I cannot say I'm realy agreed with your example about RDBMS.
You mix here a db layer and representation layer.
You know that records in the database are not realy deleted...
I need deleted flag because for "create new record" operation I MUST reuse
deleted records instead of just add new one.
But it's an interesting idea: do not read all records and than separate
they on deleted and not deleted, but during reading process manage whether
do we need all records or valid records only...
I think the value of the JavaRanch SCJD forum is that you have folks like Roel who got the perfect score
and you can brainstorm and share ideas and approaches about how to solve a problem but at the end
of the day when you submit your assignment you do what you think it's best in your own view and judgement
if you believe in it and you have to defend it and justify it when you have multiple options in
your choices.txt and during the Essay exam.
Personally, I am grateful about some of the discussions I had here that enlightened me to solve a certain
aspect of my assignment in a better and more elegant way and I didn't mind when I had to clean my Data class
so it would only use String instead of using a Room object to make it more reusable and generic and applicable
to other application domains.
I think that's why you have now a year to finish the assignment so you have plenty of time to complete it and
still balance with work and your personal life.
Cindy Carney wrote:Don't you wish we could show off to other programmers here?
This assignment is not about showing off at all, so no need to do that. Otherwise you could get such discussions about "my algorithm to retrieve/update a record is better/more performant than yours" and this assignment is not about who got the most performant or fastest application. It's just your view on the requirements, how you implement things, which choices did you make and most importantly: why did you make them.
Carlos Morillo wrote:I think that's why you have now a year to finish the assignment so you have plenty of time to complete it and
still balance with work and your personal life.
When I downloaded my assignment there was no time limit at all. But from the moment I started with the assignment it took me 5 months to complete, so 1 year should indeed be plenty of time.
Yeah, a year is plenty of time- that's enough time to finish it even for people that have full time jobs on the side, so that's good. It took me about 6 weeks to get it done, working at it full time. And I have 25 years experience in computer programming, most of it not in Java tho.
In some areas, I did more than the bare minimum required by the assignment - my GUI is prettier than most, I incorporated online help instead of a text file, I allow searching on all database fields (not just name and location), I allow regex searches in addition to simple 'starts with' searches, I allow for intuitive 'or' statements - enter multiple search criteria on a single line separated with commas will look for 'any' of those phrases (do an 'or' search), entering search criteria for multiple fields does an 'and' search (records must match all the criteria). I even implemented a multithreaded TCP server - that took a week or two, but I ended up discarding it in favor of the simpler RMI code.
But in some areas, I did the bare minimum. I didn't implement any method to add new rooms, or delete rooms - just update existing rooms. User feedback said they wanted dropdowns for the yes/no choices, and a lot of the other search fields on the screen, but I didn't implement that. Though the low-level 'DB' implementation has the required the 'create' and 'delete' methods, my higher level 'Database' interface implementation provides the bare minimum to provide the needed program functionality, which means it doesn't have a create or delete function.
I did implement extensive multithreading tests to ensure my DB portion satisfied the requirements, and wouldn't lock. I wouldn't call that overkill, because you don't know if you've really nailed it, until you've tested it.
Anyways. A lotta work, to earn this $600 certification. And now I'm leaving my Java job soon, and wish I had put in the effort into the Microsoft certifications, instead! But you never know what life is going to send your way. On the new job, I will pursue the Microsoft certifications - hopefully all those certifications, standing pretty in a row, will impress SOMEone SOMEday, and help me out somehow.
I called my topic "looking for nice advice", and not "give me nice ready code". That's why you can see here only discussion about.
But anyway, I'm sorry for your unpleasantness and wish you all the best.