db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Van Couvering <David.Vancouver...@Sun.COM>
Subject Re: [jira] Commented: (DERBY-214) Remove System.exit() calls from the DB2jServerImpl.java
Date Fri, 29 Apr 2005 04:39:18 GMT
Whoa, I was just trying to fix the System.exit() problem :)

I agree with you that there is a bit too many responsibilities for one 
object, and that parsing of arguments should be separated from execution 
of logic.  However, I don't think that I should attack the separation of 
establishing a remote connection and driving the wire protocol as part 
of this bug.  I think we should log a separate bug for that issue, I 
think it's a great thought for a more flexible design.

For this bug, I could use it as an opportunity to take all command-line 
parsing *out* of DB2jServerImpl, that makes a lot of sense. 
DB2jServerImpl should only be called by NetworkServerControl anyway, and 
should present a more classic object abstraction and not have anything 
to do with argument parsing.  BTW, it was my mistake to use 
DB2jServerImpl in the example below, it should have been 
NetworkServerControl.

In this particular example, NetworkServerControl also has methods for 
each command, and the Derby docs explicitly document that this is how 
you work with the network server in embedded mode.  So an embedding app 
shouldn't ever have to or need to call main() or any routine that just 
takes an array of args, and doesn't need the model I propose below.

However, other Derby tools, however, like ij and dblook, don't have this 
command-based interface.  They do need some kind of "execute" method 
that matches the way it is invoked from the command-line.  As discussed, 
if the behavior of exit status when returning from main() is well 
defined by the Java spec, then we can just use main with no call to 
System.exit().  Otherwise, we should provide a separate execute() method 
for embedding applications.

If we decide upon a separate execute() method, my question still is, 
what is the easier way to invoke this execute method, using an arg 
array, or by instantiating an instance and setting bean properties?   I 
think this is an indepedent question from any separation of concern 
issues within the tool itself.  I personally think an arg array is 
easier, but perhaps I'm missing an important architectural issue.

Thanks,

David

Jeremy Boynes wrote:

> David Van Couvering wrote:
> 
>>
>> Also, the JavaBean approach assumes you create an instance of the 
>> beast, and I have noticed that many command-line classes have most of 
>> their code in static methods and use static variables (not that they 
>> should, but that's what they do).  Also, it might actually be easier 
>> to set up an array of Strings rather than call a bunch of set methods, 
>> especially if you can create the array in-place, e.g.
>>
>> DB2jServerImpl.main(new String[] { "ping", "-p", "2000"} );
>>
>> rather than
>>
>> DB2jServerImpl impl = new DB2jServerImpl()
>> impl.setCommand("ping");
>> impl.setPort("2000");
>> impl.execute();
>>
> 
> My concern here is coming from confusion in the responsibilities between 
> NetworkServerControl and DB2jServerImpl. For example, there are two ways 
> to set the maxthreads:
> 
> 1) new NetworkServerControl().setMaxThreads(100);
> 
> 2) NetworkServerControl.main(
>      new String[]{"maxthreads", "100"});
> 
> Ultimately these both end up calling DB2jServerImpl.netSetMaxThreads()
> 
> DB2jServerImpl is doing three completely different things here: it is 
> setting up the remote connection, it is driving the wire protocol to the 
> remote server (see the impl of netSetMaxThreads), and it is responsible 
> for parsing and verifying the command line arguments passed in. I think 
> these concerns can be separated resulting in a simpler implementation 
> that is easier to embed and use from other tools such as Eclipse.
> 
> I would first suggest factoring out the connection setup and teardown - 
> perhaps a NetworkServerConnection class with hostname and port 
> properties (perhaps username, password or other credential) and an 
> execute method that takes a command object e.g.
> 
> public class NetworkServerConnection {
>    public void connect() throws TransportException;
>    public void close() throws TransportException;
> 
>    public Object execute(NetworkServerCommand cmd)
>       throws TransportException, CommandException;
> }
> 
> Each command (ping, maxthreads, etc) is represented by an object that 
> implements NetworkServerCommand and which can be set up with the 
> appropriate properties e.g.
> 
> public class SetMaxThreadsCommand implements NetworkServerCommand {
>    public void setMaxThreads(int threads);
> }
> 
> Each command would know how to write itself to the wire; heck if you 
> were prepared to break backward compatibility you could simplify things 
> further by just using serialization.
> 
> For command line support, NetworkServerControl.main parses the 
> arguments, creates a NetworkServerConnection and the appropriate command 
>  and then submits it to the remote server. Basically it just contains 
> implementation for handling the command line syntax.
> 
> For embedded use, a tool can create and maintain a connection for as 
> long as necessary, getting the connection parameters any way it wants 
> (e.g. a host/user/password dialog). The commands can be created and 
> submitted in response to UI events just like any others. Both the 
> connection and the commands can use beaninfo to define their properties.
> 
> Although there are more moving parts in this, I think overall it is a 
> more maintainable solution as the concerns of connection, commands and 
> UI have been clearly separated.
> 
> -- 
> Jeremy

Mime
View raw message