Monday, March 17, 2003
There is programming, and there is software development. You, dear TopCoder member, demonstrate weekly that you can solve well-stated programming puzzles quickly.
Yet solutions to real-world problems require more: deciding *what* puzzles must be solved, describing them thoroughly, developing solutions that are open to change, and verifying those solutions: design, documentation and testing. Together with the actual programming, these make up the software development process.
These are not new issues, and fortunately we have a set of common tools available when tackling these software development tasks. Object-oriented language was a major step forward for design, as was the Unified Modeling Language (UML) for describing software systems. Wide interest in standard "design patterns" has added to designers' common vocabulary of design solutions. Finally, standard open-source unit testing packages like JUnit have helped developers benefit from early and frequent testing.
Despite all this, it's still an art, not a science, and software development skill grows with real experience. Lucky for us then that TopCoder Software has done for software development what TopCoder did for programming, where members can compete to design and develop small software components. It's instructive to see a modern software development process in action on a small scale, and to learn through participation (and of course there is the lure of prize money.)
So, this article presents my own perspective on how to navigate the software *design* process. This being TopCoder, it is in the form of a brief 10-step guide to designing TopCoder Software components, but the ideas should be somewhat applicable elsewhere, since TopCoder Software's practices are common to many Java projects (i.e., Ant, JUnit, javadoc, UML). I hope to convince you that this doesn't have to be a difficult or time-consuming process, and thereby encourage even more TopCoder members to bring their skills to the competition, and also employ these software development processes in the real world. It can only make us all better designers and developers.
1. Pick your component; conceive your approach
2. Inquire about the component
3. Define your use cases
Get started on your model in Poseidon: start a new model, and create a use case diagram. Drop in an actor, create a use case bubble for each of your use cases, connect them, done!
4. Prototype it
5. Write your class diagram
TopCoder guidelines and example documents demonstrate exactly what you need to model (essentially, anything public - if there are important non-public elements, though, these can be modeled as well). This is the "map" for your component design, so strive for clarity - the point of the diagram is communication of ideas to another person like yourself. Make the diagram neat; the arrangement of diagram elements should visually communicate groupings. Don't model anything beyond the basics unless you really feel it's important; too much detail can obscure the basic structure.
Fill in javadoc as well according to TopCoder guidelines to the Poseidon diagram; this is the place to detail exactly what each public method and class does.
6. Write sequence diagrams
What to model and not model here is fairly subjective; again, remember that the purpose is to clearly communicate the high-level structure of the implementation to other developers. Capture all the major method calls and interactions between objects; skip the minor details, as they just clutter the diagram. If the diagram runs past two printed pages or so, it's likely too big - reduce your level of detail, or break the diagram into two if possible.
Sequence diagrams for TopCoder Software components are available on the web site; browse a few to develop a sense of how different designers like to model these items.
7. Fill out the component specification
8. Export skeleton code and add javadoc
9. Write test cases
Your tests verify that the functionality you have specified is provided in an implementation. If you say that a method should not accept null, test for this. Cover all public methods in your tests - this ensures that the tests won't even compile if any part of your API is not implemented. Write tests that verify all basic functionality.
See the example TopCoder design submission for an example of a JUnit test case.
10. Repeat if needed, and submit
Once satisfied, build your design submission and send it in!
This approach works well for me in practice at TopCoder Software, and during other real-world software development. It's not the only approach to be sure, nor necessarily the best, but I offer it to new and experienced developers alike as just another perspective "from the field." Cultivating good design habits turns good programmers into powerful software developers; I hope that more of TopCoder's strong programmers will contribute to and learn from participation in TopCoder Software design and development projects.
Would you like to write a feature?