Hi guys.
As I had commented in my previous post I have almost finished my project, but I found another "possible" weakness. I'm using a thick client because of the use of cookies. So in the client side reside the gui, a controller and the services. The server has de database connection.
A big issue that most of the candidates had found with this thick client is that the DB interface doesn't throw the RemoteException in its methods when we decide to use RMI. After searching approaches in this forum and reading alternatives in other sources I opted for implementing the Proxy
pattern to have the DB interface in the client and the server side.
What I did in concrete was to develop a remote adapter interface that has the same methods that the DB interface but I added a RemoteException in each one. The implementation of this remote interface is essentially an wrapper of my Data class. Then I simply register this object in the RMI registry. Of course this is in the server side.
In the client side I created a Proxy class that implements the DB interface and in the constructor I look up the remote adapter object registered in the RMI. I found this approach pretty simple.
Now the "dark" side of this solution is: The proxy class is an wrapper of a remote object but still somehow has to deal with the RemoteExceptions. I don't rememember well but in one
thread in this forum I read that someone wrote "and the proxy class eliminates the RemoteExceptions". My mind was blowing because I had learned that I should not swallow these exceptions just because the DB interface doesn't throw them!!!.
Then my solution was to create a NetworkException that extends a RuntimeException and declare it as part of the API of the DBProxy class.
The compiler is happy and so do I. Everything still is simple.
Now, which class is going to use this DBProxy that implements the DB interface?, of course a SubcontractorServices class. This class takes a DB interface in its constructor . Also, this class implements a bookSubcontractor method and a searchSubcontractors method. Then a programmer knows that these two methods depend only of the structure of the DB interface methods.
However, things get glommy when you reason this: what if I pass a DBProxy class in the constructor. This is valid because the DBProxy class implements the DB interface that is what the SubcontractorServices class needs. But what if in the middle of one operation for example, the DBProxy read method throws a NetworkException, how the programmer knows that he has to catch this exception if is not documented in the DB interface.
I as the developer of these classes know that I have to catch this NetworkException(RuntimeException).
The solution is simple again, I just have to catch the NetworkException in a catch that accepts an NetworkException. But again, I am the developer and know that someone could pass either a Data class (standalone mode) or a Proxy class (client mode), and thus I am aware that I have to catch this unchecked NetworkException.
But.....someone that is not the developer will not have a clue that the read method could throw the NetworkException simply because is not documented in the DB interface. If a junior programmer reads the code he may think, where the hell does this NetworkException come from???.
My idea is to simply document in the SubcontractorServices class that a DBProxy class could be passed and this class throws the unchecked NetworkException in each one of its methods.
What do you think, it is enough to document this "ghost" exception in the SubcontractorServices class? The logic of the application is simple at least for me. In the standalone mode you first create your Data class and then pass it to the SubcontractorServices class. In the client mode you first create your DBProxy class and then pass it to the SubcontractorServices class.
Regards!!.