Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007
SuperFriends teach teamwork
We intend for this case to be used by future students of cs2340, or its subsequent incarnations, to learn how to develop a project in a team environment. Consequently, we based this case study on Milestone 2. While completing milestone 2, our group moved from four people who had met only briefly to a working team. We find this process quite interesting and believe that the exploration of the development of a team will be useful to future students. Hopefully, by observing the process through which we completed the second milestones, future students can gain an understanding of the difficulties and rewards
of building a successful team.
A few important notes include the following:
- Though we would like to, we will refrain from using some smurf-like dialect in which every key word is squeakingly replaced by the word ësqueak.í
- As stated in the introduction, we consider the process more important than the final product, so the focus of this case will be the process by which we came to our final product.
- Finally, to make this case study user friendly, a somewhat informal tone will be adopted. Please bear with us as we may make a few puns and jokes along the way.
Description of the assignment
This summer we were required to create a math equation generator. The generator was expected to display fractions, superscripts, subscripts, and Greek characters. Moreover, it was expected to appropriately size the components of the equation. In Milestone 2, the milestone on which this case study is based, the user developed the equation through a graphical user interface, and the generator displayed the resultant equation as a graphical object.
Milestone 1 required us to create the display, while allowing the user to develop the equation using a command line interface. We based milestone 2 on one of the team memberís milestone 1 project. An important consideration for us throughout was the set of later milestones. We designed the project with the knowledge that further modifications, such as milestone 3 and milestone 4, would need to be made, and the better we wrote the code the first time, the less work we would do later.
Selecting a team
Fortunately, our team worked well together, as we have become super friends. I, in a constant fear of being left out arising from my always being picked last for any sporting event, was eager to find teammates. Early into the semester, I began searching for teammates. Specifically, I looked for people that I knew to be hard workers and that were interested in earning a good grade. Also, I wanted people with whom I would be comfortable spending a lot of time.
Our first challenge was finding time to get together and work. Not only was it difficult to find the time, but getting in contact was also difficult. We used a variety of techniques from email and aol to cell phones and (gasp) personal contact. Often there is a tendency to want to talk in class, but please donít. If you want to meet during class, at least step outside. Another problem we encountered was trying to share code. We managed this by using projera, codeveloped by teammate Tommy Unger, and email attachments. Further, we found AOL instant messenger file transfer to be useful.
Another problem we encountered was trying not to overlap work. Techniques for handling this problem will be discussed in more detail when we discuss the design phase of the project. For now, please note that we did not develop clear roles for our team until we had a solid vision our design. Once we recognized how we would build the project, we could identify who would be best suited to complete which parts.
As the project progressed, we passed through several phases McCraken calls "storming, forming, norming, and performing." Although at first we doubted the validity of that pattern, it became apparent how true that description was. At first, we found communication somewhat difficult as we were not familiar with one anotherís thought processes. Later, as we became more comfortable with one another, we went through a phase where not much was accomplished. We spent more time laughing and eating kool korners sandwiches than actually working. Next, during the norming phase, we started to get work done. We began to use vocabulary specific to our project, such as the front end or the text editor, that we all understood. Also, we began to understand our roles within the group.
Finally, towards the end of the semester, we entered the performing phase where everyone completed their part of the project with minimal contact with one another. We consider this to be the most exciting phase as it happened with out a concerted effort at building a team.
Where do we start?
As with the transition from four people to one team, the creation of a functioning project from a somewhat vague assignment required a good deal of work. At first, we were unsure even how to begin, so we just read the assignment several times and made sure we fully understood the task. While doing this, we began suggested broad, incomplete solutions. We spent several meetings, each of which lasted several hours, making sketches and writing down random ideas. During this time, we not only developed a clearer vision of the solution, but we also got to know each other. Our suggestion is to be prepared to spend several hours that seem unproductive. Though a clear solution may not appear until later, this time is invaluable as a tool to understand the problem and each other.
The solution slowly progressed from sketches of the interface to the functionality behind the interface. At this point, we had to consider whose milestone 1 to use. We finally decided to use the one that seemed most suited to further projects. Although it was not the best working project, its design separated the model view and control in a way that would although easy maintenance. We called this part of the project the backend because it handled the manipulation of the model.
Next, we began designing the implementation of a frontend that worked with the backend. We already had a clear idea of how the user interface would look, but we had yet to figure out how it would work. So we began by writing down a lot of classes that we thought might be useful. After we had a solid list of classes, we began making crc cards. They were especially helpful in evaluating which classes were necessary, and which werenít. For example, we noticed that we had specified several classes that would serve as components for the GUI, such as a button panel. We decided it would be easier just to have each editor create a panel specific to that editor in an overridden method. Conversely, we noticed that we needed to extend a general editor class into a Greek text editor and an Equation editor (pictures of the editors).
Finally, we started writing the uml. Although at first this step seemed extraneous, we are all extremely glad we put so much effort into making complete uml diagrams. We spent several hours discussing all the methods necessary in each class. Even though it was tiresome to talk out all the methods, and we all just wanted to start coding, we forced ourselves to complete the uml first.
This strategy had two consequences for which we are all grateful. First, coding our individual parts was very simple. All you had to do was look on the diagram, pick a method, and code. There was no need to hold a constellation of methods and plans in your head while trying to code. The second, and more rewarding consequences, was that although we coded the frontend and the backend separately with no substantial communication between the coders, the two ends worked seamlessly with one another. We intentionally defined a very simple interface between the two ends consisting of methods whose purpose and parameters were understood. That allowed use to implement the ends in whatever manner was necessary for that component, as long
as it interacted in a standard fashion. This technique proved to be very useful later on when we were required to change the user interface.
We divided the project into two "sub-teams," along the division of the frontend and the backend. Within those teams, we found it was useful to have one person doing exploratory coding, and one coding the solution. The person doing the exploratory coding was responsible for exploring squeak and understanding the source already provided. Through these teammates we learned about the use, for example, of pluggable components and color forms.
Another advantage to have everyone working somewhat independently was that everyone was free to code the solution however he saw fit, within the constraints of the design. In this way, we avoided micromanaging one another. However, we all followed the agreed upon design and uml. If we had to make a change, we discussed it with the group first.
It is important to note that we commented as we went. Although it seemed convenient to do all the commenting all at one at the end, we all know that does not work. By the time you are finished coding, you have no desire to go back through and comment your code. Further, the comments are more thoughtful and helpful if they are made while coding because you have a clear understanding of what you are doing.
One final topic is that of debugging. Squeak has a wonderful debugging tool if you cause an exception. However, if your code is working correctly, according to squeak, but it just is not doing what you want, then you have several options. One useful method is to place:
This allows you to see the status of certain objects within your code. Also, the tried and true debug print statements work well. Printing to the transcript works well, but just donít forget to open it before you test the code! Finally, we also noticed that coding very functionally, meaning focussing on writing small, encapsulated code facilitated debugging.
So we have talked so much about how we built this thing, so letís see it. We decided on two input screens. One allowed the user to input the basic math operations, while the other accepted the text, including the Greek text. It works is by building the objects, then filling them in. That is, if you make a subscript, you must build the script before you build the main part. However, once you are in the script part, it can be made into a fraction, a scripted object, text, or whatever else. When you want to enter text, simply click the String button. That takes you to the text editor where the text, including Greek text can be entered. When finished, clicking done returns a form. Feel free to explore the code and the project by downloading a zip file that includes the st files: superfriendsp2.zip
As stated, we divided the project into the frontend and the backend. The frontend consists of two editors, one for the equations and one for the text. An important design decision was to build an editor object from which the two editors extended. Since both editors shared the need for an input area and a display area, we built that into the superclass. For the specifics of the display, we subclassed the editor class. In general, we find that it is important to look for objects that will have shared characteristics and extend them from the same parent. Only areas in which the objects diverge should be implemented in the child classes.
The backend also had several design characteristics that made it maintainable. First, as with the frontend, an inheritance hierarchy was stablished. We developed a mathobject that would hold data, return the data as a form, and modify its data as necessary. MathObjects could hold either text, in the form of a MathString object, or other MathObjects, such as a MathFraction or MathScript object. But because fractions are different from scripts in their form, we chose to have them separately subclass the mathobject. This allowed each type object to store data in a manner suiting its distinct needs. The MathFraction, for example, held two more MathObjects, a numerator and a denominator. And because of that scary word, quot;polymorphism," those MathObjects could be other fractions, strings, etc.
Another very important feature was the toForm method. This method generated a form (an instance of the squeak class form) from the data the object held. Each subclass of MathObject had its own way of developing a form representation of itself. For example, the MathSubscript knew to place its script below its body. The interesting point is that because the script and the body were themselves MathObjects, the MathSubscript only needed to call their respective toForm methods to get the forms to place on top of and below the line. This allowed us to change the way in which one object displayed itself without having to change any others. Similarly, to accommodate the need for the text to decrease its font size as it was moved into a fraction or a script, each object had a makeSmaller method. These methods called the makeSmaller method of each of its data objects, thereby reducing the size proportionally of all the objects held within that object.
We hope you have enjoyed our case study, and we would only like to make these final, closing comments. The development of a quality project requires time and commitment. You must be careful whom you selected as teammates, and then be willing to spend the time necessary to develop an understanding within the team. Also, you must devote a large amount of time to designing, as a good design will substantially lighten the load later on. When designing, we found the most important concept to be encapsulation. The more implementation and interface are separated, the easier the code is to change (and believe us, you will change it :)). Finally, recognize that you will not find the solution all at once. Only by work and perseverance, and a large amount of time feeling dumb and hopeless, can you complete a project you are proud of. (Sorry to get so preachy, but we believe this to be fundamentally true.)
Link to this Page
- Cases last edited on 30 July 2011 at 2:33 am by r59h132.res.gatech.edu