There are quite a few complex issues that must be worked out, at both high and low levels, in order to implement a suitable solution to this problem. Before writing one line of code you must have, at a minimum, a good idea of the direction you are heading design-wise.
A good place to start is by doing a basic noun-verb analysis of the project specification. The reason for completing such an analysis is to get your creative juices flowing. One good design idea can potentially yield many others. Table 20-2 offers a first attempt at such an analysis.
Nouns | Verbs |
---|---|
robot rat | move |
rat | move north |
floor | move south |
client | move east |
server | move west |
socket-based client | move north-west |
RMI-based client | move north-east |
protocol | move south-east |
thread | move south-west |
connections | connect |
client application | |
server application | |
user’s robot rat | |
rat’s position |
The list of nouns and verbs, although not exhaustive, is complete enough to allow you to march forward. At this point you know that the client and server applications will communicate with each other via sockets and RMI. The client application will send commands to the server application via the network. There will be two types of clients: socket-based and RMI-based. The server will receive the client commands and translate them into robot-rat movements upon the floor.
Armed with this high-level application operational description and the noun-verb lists it will now prove helpful to pick several nouns from the list that appear to be good candidates for classes and assign to them some responsibilities or make comments about their functionality. During this analysis you may discover other derived nouns and verbs ( derived requirements ) that can be included in the analysis as well. Table 20-3 makes a first attempt at class responsibility assignment.
Noun | Possible Class Name | Responsibilities & Design Comments |
---|---|---|
rat | Rat | Embodies a single rat object. Contains a reference to a rat image ( rat.gif or other developer-provided image) and its position upon the floor. The position could be a separate class but in this example the Rat class will contain x and y coordinates indicating its position upon the floor. There is one Rat object for each client session. This means there could potentially be many Rat objects on the floor at any given time. Clearly there must be a collection of Rats somewhere. |
collection of Rats | java.util.Vector | An instance of the Vector class will be used to hold a collection of references to Rat objects. When a new user connects to the server application their Rat will be added to the Vector. Maybe the Floor class can iterate through the Vector of Rats and draw each Rat’s image on itself after each move. |
robot rat | RobotRat | We need a class that can control the movements of individual rats. The responsibilities of the RobotRat class will include making rats turn in different directions and move about the floor. There will be a one-to-one mapping between a Rat object and its controlling RobotRat object. The RobotRat will need access to the collection of rats so it can insert its rat into the collection. The RobotRat class might also be a good candidate to implement the server-side RMI functionality. |
floor | Floor | A Floor is a graphical representation of the robot rat movement area. The Floor class will extend the java.awt.Canvas class as per the hint given in the project specification. How will the rat images get drawn to the floor? How will a rat image be updated on the floor after a user moves a rat? What does it mean to move a rat? Also, there will be only one floor object upon which all user’s rats are moved. |
Thread | ThreadedClientProcessor | The ThreadedClientProcessor class will be responsible for managing socket-based communication between the client and server applications. An instance of the ThreadedClientProcessor class will be created when the server detects a new incoming socket-based client connection. The Socket object retrieved from the server application’s ServerSocket object will be passed to a ThreadedClientProcessor object for client session processing. |
server application | NetRatServer | The NetRatServer is the main application class. Its responsibilities include overall server application initialization. When you start-up the server you are running an instance of NetRatServer. The NetRatServer must manage both the RMI- and Socket-based server application aspects. |
RMI-based client | RMI_NetRatClient | The RMI_NetRatClient class will implement the RMI client application. The RMI_NetRatClient class will display a GUI interface which will contain buttons that can be used to send commands to the NetRatServer application. |
socket-based client | Socket_NetRatClient | The Socket_NetRatClient class will implement the socket-based client application. The Socket_NetRatClient class will display a GUI interface which will contain buttons that can be used to send commands to the NetRatServer application. |
Table 20-3 offers a good start at assigning initial class responsibilities. There are still a few details to be worked out but there is enough information available to proceed with an initial design. Figure 20-10 offers a first draft class diagram that highlights the important relationships between the server-side classes.
Figure 20-10: First Draft Class Diagram for the NetRatServer Application
Referring to figure 20-10 — The RobotRat class will contain one static instance of a Vector and a Floor. The Floor will need to be drawn into a Frame so RobotRat will also contain a static instance of a JFrame. These three objects will be shared by all instances of RobotRat. Each RobotRat instance will manage its own private instance of Rat. The RobotRat class will also serve as the class that implements the server-side RMI functionality.
The ThreadedClientProcessor class will contain an instance of RobotRat and will translate socket-based client commands into RobotRat method calls.
The NetRatServer class will serve as the main application. It will start the RMI registry and bind an instance of RobotRat with its service name. The NetRatServer class will also listen for incoming socket-based client connections and pass the socket off to an instance of ThreadedClientProcessor for further processing.
For initial testing purposes the NetRatServer application can display a window with buttons to send test commands to robot rats. That’s why figure 20-10 shows NetRatServer extending JFrame.
With an overall design approach in hand and a good sense of direction it’s time to start coding. As you begin to implement the server application some aspects of the design will evolve as your understanding of the problem deepens. As usual, a good way to proceed with the implementation effort is to select a subset of the design, code it up, test it, reflect on the design up to that point, make changes where necessary, then repeat the process with another subset of the design.
Proceed first with a client-server project by giving sufficient analysis to the project specification. Use noun-verb analysis to discover candidate application components and actions. Sketch out a rough application design to use as an implementation road map. Make a list of candidate application classes and assign to them an initial set of responsibilities. The objective of the analysis and design phase is to provide a starting point for implementation and get the creative juices flowing.
Socket-based client-server applications will utilize classes found in the java.net package. RMI-based client-server applications will utilize classes found in the java.rmi package and its related packages. However, to fully implement a client-server application requires the utilization of many different Java platform classes.