Space

- Second Design/Code Attempt -



PURPOSE:

The purpose of this section of the Journal is to illustrate how I changed my initial design into my final design.

ANALYSIS OF FIRST DESIGN:

Before I attacked the design problems of my first run at the program I decided to make my OMT design as detailed as possible. I went back to my last OMT diagram and rearranged subsystems, added all of the GP superclasses that had been assumed before, color coded different parts of my system -- in general I just cleaned it up. In the following diagrams classes which are colored red are part of GP. Classes which are colored green are part of the cs015.SP package. Classes which are colored blue are top-level objects which comprise a smaller subsytem which have their own diagram. Classes which are colored black (obviously can't do a neat color tag here!) are classes I have no written yet. Finally, all classes which remain white are classes which I have created on my own.

This proved to be a very useful idea as it allowed be to even better understand the system I had created. In the analysis of my first design here were the problems/improvements I came upon:

  1. The code for the ShipBehavior and the WeaponBehavior classes was exaclty the same. These two classes should be able to be factored into one class that can manipulate both. In order to do this I will need to setup an interface which both Ships and Weapons can implement.

  2. The code inside of the subclasses of Key and Mouse also do everything the same. This code too should be able to be factored out. To solve this problem I am going to create ShipManipulator objects which encapsulate one specific action which can be executed upon a ship. As well as factoring code out of the Key and Mouse subclasses it will allow me to do away with them all together. I will only need one generic class which accepts a ShipManipulator and executes it whenever it is activated. As a side note there exists an interface in GP called a GP.Doable. This class will give me this functionality exactly. I am going to use it.

  3. The way I was using the GP.Components.ColorChooser was entirely wrong. I need to subclass off of this class in order to affect the Ship's color. This will be quite simple and should fix my current bug.

  4. I kind of felt that it was tedious for me to always have to be getting the reference to the Ship whenever I wanted to do something. Also, what happened if the reference to the Ship was null? I had no guarantee that I would always be getting a valid reference back when I called GetShip() on the ShipHolder. In order to fix this I decided to use a pattern I had heard one of my TAs talking about, the Proxy pattern. This pattern allows me to forward messages (method calls) off to an object and to let it worry about what to do. This seemed to fit in with the Delegation pattern we had always been told we were using so it sounded good to me. Now I could let the ShipProxy worry about whether or not it had a valid reference or not and I could just call methods on it.

    However there was one issue. A ShipProxy is not a Ship. So if I want to treat it like a Ship what can I do? The TAs told me I could create an interface that consisted of all the methods I wanted to call on a Ship. Then, both Ship and ShipProxy could implement them and I could pass messages anytime that I pleased.

  5. I also realized that as standing, I had a toggle button containing a row of buttons. This was happening in my MouseSelect and MouseController classes. Eventhough tis class wasn't graphically containing these classes it was modelling a containment relationship instead of the appropriate association relationship. To fix this error I made the Simulation class contain the MouseController and pass it as a parameter to InputChooser so that InputChooser could pass a reference on to MouseSelect.

  6. Another thing I decided to do was to make subpackages. When looking through my code I saw that I had a good amount of classes and that it might be nice if I created some more organization for them. For example my ShipManipulators could all be in one package, as could all of my Ship subclasses.

NEW DESIGN:

As I started to code up my new design I realized that my ship was still not moving at all. The only thing it could do is Activate. I decided to look into the problem. So I thre in some System.out.printlns to tell me if the ship was actually receiving the messages. It was. So what could the problem be? Aha! I realized that I hadn't set any default values in my Attacker subclass to govern how it moved.

After I set the initial values I recompiled and voila, it worked! Fantastic I thought. Time to move on. But all things were still not 100% up to spec. I still had not implemented the Explorer. Understanding that it should be easy to write, by definition, I decided to code it up.

And it worked as expected, but with one drawback. When I went to switch between the different ships the old one stayed on the screen. This was an easy fix. Eventhough I was "losing" my reference to the old ship GP was not. All I would have to do is Hide() it. This worked well.

A realization I made was that subclassing off of GP.Components.ColorChooser was the wrong thing to do. I didn't need to specialize at all. All I had to do was set the color of the ShipProxy to be a GP.Attributes.Colors.Chooser that was tied to the GP.Components.ColorChooser. But this didn't entirely work properly. Once I changed the ship the new ship was no longer tied to the color chooser! So to maintain persistance I added some code to the SetShip() method of the ShipProxy class that set the color of the new ship. This did indeed work.

Another problem I had was that I had made the Light for the Explorer a triangle. It looked terrible. So I modified this code so that it would project a a circle of light around the Explorer ship (whough the code doesn't care what kind of ship it is).

But this was a bit difficult because I wanted to have the light shine for a brief period of time and then die. After studying GP.Behaviors.Perpetual for awhile I decided that I could use the parameter double time that is passed in through Apply to count how long the behavior had been running for. Once it had run longer than the specified duration I would destroy the light and remove the behavior. Testing this out proved it to be a successful idea. I did, however, have to write a new behavior class called LightBehavior to handle the extra code.

By now my code was fully functional and it was time to continue to clean it up and make it look pretty. Here is my revised design and code for the end of my second run:

Design Diagrams and Code:


This page was last updated by Shoe on 03/05/98.
Comments or suggestions, should be sent to: ahs@cs.brown.edu
Space is copyright 1996-1998 by Andrew H. Schulak