I have a few questions about desing of Data access class:
1. Why all use the cache? I think this is not a suitable solution for the database. Load all the data at once - it is very expensive. If data will be much the program will take a lot of resources. Perhaps the data will not be very many, because it is used reuse removed records. I want to do without the cache, but maybe I do not understand why.
2. I have read many posts and noticed that many make the data class as a Singleton. But I do not want to use it. Maybe this is part of the assignment, but I did not find it? I designed my Data access class so that it can be used multiple times.
The class has two constructors, all class methods are synchronized
public Data(String name, int magicCookie)
public Data(File file, int magicCookie)
In the future this will be connected to multiple files.
3. What would another program could not have access to the file, I block it with dbFile.getChannel ().lock ();
But FileLock - is part of the NIO. I cannot use it?
1/ There is no requirement at all which requires you to use a record cache at all. So you don't have to follow that approach. I did it, because I "believe" it simplifies my code. And of course it has some drawbacks, which I documented thoroughly in my choices.txt (with alternatives and possible solutions).
2/ If you mark all your methods synchronized, your threads need to work on the same object. If they don't you will have thread safety, but not on the same object, so your database file could get corrupted. There are many ways to enforce there will be 1 object of your Data class. Making it a singleton is one of them. But you could also use something like this:
3/ you are not allowed to use classes from the nio api (according to the official scjd page), but you don't need it at all, because only 1 program at a time will access your file (mentioned in the instructions). So you don't need to do that, just stick to the requirements in your assignment (instructions). You won't get extra credit for doing more than expected, you might only loose points!
p.s. no need to apologize for your english every time: a lot of us (like me) are not native English speakers, and all of us try to do the best we can to express ourselves in English, just like you.
David Kachen wrote:I do not like my class Data was Singleton, this limits its reuse.
True, but if you don't clearly document that you expect your Data class to be used as a static constant, so all threads use the same instance. Other developers may use your Data class wrongly (consequences: no thread safety, data file corrupted,...). With a singleton you are absolutely sure the Data class can't be used wrongly. But you loose a bit of code reusability.
Although my Data class is a singleton, with a few minor changes, it can be completely reused to handle a database file with customers for example.
Why should your Data class handle 2 different database files (db-1x2.db and db-1x3.db), unless these files contain different data (contractors and customers for example). In a RDBMS you also have just 1 contractor table and 1 customer table, so why would you want to support something similar with flat files? It is not mentioned in the instructions at all.
And as a final remark: I see you are developing against a class (your Data class to be more specific). you should program against an interface, so you minimize the number of changes you have to make when the implementation changes (from a flat file as database to a rdbms for example)
Hope it helps!
I not quite understand you. Next, I show my Data class design. I hope this will help us to understand each other.
Data Access class (d/p Facade) contains a data source and the manager of locks.
DataSource class is thread-safe. In one time, only one thread can access the file.
LockManager class is thread-safe. In one time, only one thread can lock/unlock record. If record already lock then thread wait for unlock or return 0 on timeout.
DataSource and LockManager is not part of API, only Data part of API.
In my opinion, Data class is thread-safe. In my program I use one file, but If anyone wants create own server with multiple databases, then it can easily do this using the Data class.
I decided to use this approach and it does not mean that other approach are bad. Of course, maybe I'm wrong and so I want to hear the views of professionals.
 complete code snippets are not allowed
First of all: posting complete code snippets of your solution is not allowed (because they could just be copied by someone else) (I deleted them from your post)
Secondly I understand your solution (without and your Data class is indeed thread-safe (can easily be tested with Roberto Perillo's Data class test, an excellent test case and 1 of the most valuable threads in this forum).
What I was trying to explain: your Data class is thread-safe <==> all threads work on the same instance. So your snippet will work without any problem, because you have just 1 instance per database file. But if another developer would create a business service and expose this service using the factory pattern through RMI (like described in the SCJD book by Andrew Monkhouse):
this solution will not be thread-safe anymore, because you will have multiple Data instances: each of them will be thread-safe but not together. And of course an easy fix would be just to mark data static. So you need to document how the Data class is supposed to be used. If your Data class is a singleton, it can't be used wrongly.
But like I already said your approach is completely fine (and will work without any problem)! This is just what this certification is about: making decisions and argumenting why you chose one above another.
With my final remark I just meant:
You are right, for the proper use of Data class that must be one file had access to only one Data instance.
First, I made the file lock (dbFile.getChannel().lock()) for each Data instance. Then I remove it, because I can not use the NIO API.
After your last post, I began to search for the suitable decision. In the end, I decided to use pattern Object Pool.
That should turn out that like it:
I think this is a normal solution. What do you say Roel?
 And of course, is to take care of thread-safe for open/close methods. I have this in mind, but will not display in the example.
David Kachen wrote:I think this is a normal solution. What do you say Roel?
That's an easy one: sounds like you are going to overcomplicate your application. Don't forget: an easy, simple to understand solution (by a junior programmer) is preferred above a complex one.
You can justify your decisions in choices.txt and explain how you would implement an enhancement or solve an issue, without having to clutter up your code and make it too complex. Like I already said my Data class is with some minor changes completely reusable (although it is a singleton), but I couldn't make these changes because I would break a "must" requirement, so I explained how I would have done it if I didn't had to meet that requirement.
My Data class also uses a record cache (this combination is the easiest approach possible, in my opinion), but a cache has some drawbacks and issues: memory, possible data loss,... I explained in the choices.txt possible solutions for these drawbacks, but I didn't have added any code to my solution to solve these issues.
The most valuable advice I can give: just keep it as simple as possible!
I think you are as always right. It is not necessary to complicate all. I have too taken a great interest.
I will not use the Object Pool. Singleton is a simple and good solution for Data class.
But access to the data I want to leave as is. The complexity of the implementation of direct access and access through a cache of about the same.
For myself, I made two sales, which would see the pros and cons of these approaches.
And yet I decided to use direct access. In my choices.txt I will describe both approaches and the reasons why I chose this approach.
Thanks for helping Roel.
I simplified my implementation of Data Access classes. And now I have a new question
It seems to me that I was too detailed description of my classes. In the javadoc for each class are described approaches (Patterns) which he uses.
Some classes implement multiple patterns. For example, the class LockManager implements Adapter, Single Threaded Execution, Guarded Suspension patterns.
Maybe this should leave only simple patterns? such as Singleton, Immutable, Adapter, Factory Method and etc.
Roel, according to Your advice we should program to an interface (and we know it's a good OOP practice :-) ), but what if the interface given is incomplete, we shouldn't extend the interface with custom methods and implement the extended interface, nor should we program to our class?
I am working on the URLy assignment, and I just did Data data = new Data() (not exactly, as my Data class is a Singleton), where my Data class has the necessary methods added (for eg. specifying the database file it will work on), but You made me rethink my solution :-)
What do You think the "correct" solution would be? Unfortunately it's not my biggest problem about my assignment :-) I'm just curious :-)
Update: sorry, on my next open tab I just read Andrew's post that says
Similarly I am an advocate for having the Data class be a Façade fronting separate classes that handle locking and file operations.
For some reason I just thought that "Your data access class must be called "Data.java"" as is written in my instruction means that Data must be the lowest level class and there's nothing between it and the database file.
You should program against interface and there is no restriction in creating your own interface, which extends Sun's required interface and has some additional methods you need. I adopted the same approach (and a whole bunch of other ranchers too).