programmer

CS102

Algorithms and Programming II

Detailed Design Stage

Having decided on the requirements for a product and having established exactly what it will look like and how the user will interact with it, the time has come to figure out how to build it. This document offers some guidelines and suggestions about this stage of the project, the main aim of which is to specify the classes and methods that will comprise your program, and then divide up the implementation between group members.

Overview

The basic plan of attack for developing a detailed design for your project is this. Given the user-interface design, develop a class diagram (UML notation is introduced in the text book) for your project including attributes and methods and necessary pre- and post conditions. In particular, for each operation in the user-interface, specify a method which will perform this operation and decide about helper methods in the same class or in other classes. The specification should include a meaningful name, objective, any important preconditions, how the method will affect the object properties (above) and any relevant additional inputs it might need. This information should be enough for someone to actually go away and implement the module without having to worry about the rest of the program. Finally, give each group member primary responsibility for the implementation of a particular set of classes, making sure that you spread the work load as evenly as possible.

General Considerations

Our main concern is to identify the data requirements (classes and attributes) of the program and the sort of operations (methods) which need to be performed upon this data. In doing this we need to be aware of the constraints within which the design must work. Limitations which might need to be taken into consideration include time, efficiency, memory space and deadlines! Unfortunately, these factors tend to conflict with each other, such that, for example, a faster design might need more memory and be more complex, and hence take longer to implement, than a slower design. As with all engineering, it is a matter of tradeoffs; that is, rather than being a question of right or wrong, it is simply that one design will be somewhat better or worse than another (assuming, of course, that they do both function correctly). Thus, unless you have in mind extensions which would necessitate serious redesign if not planned for now, your design should be as complex as it needs to be, but no more.

What this means is that classes should be grouped in such a way that the memory requirements and the communication overhead is not too great, yet at the same time the required functions can be made to work fast enough for the tasks at hand and be implemented within the available time. In other words, you must select appropriate data structures and algorithms, and be able to justify your choice! In computer engineering there are a few "standard" data- structures and techniques which get used over and over again. It is a good idea to learn about these and to be aware of their characteristics so that you can quickly chose the most appropriate one for your application. These basic software "components" include objects with internal structures (or derived from containers) such as linked lists, stacks, queues and trees, together with various searching techniques such as hashing, and sequential and binary search, and sorting methods such as selection sort and quicksort. In addition, you may want to employ sequential and direct access files for persistent storage and data input. Some of these issues are explained in the course textbook; some you already know, others we will cover in lectures and some we may not have time to look at this semester. For this reason, you should consult with your project assistant and/or instructor before making a final decision on the detailed design of your project.

The Model-View-Controller Architecture

Designing and implementing programs with graphical-user-interfaces can be quite challenging and maintaining them can be even more fun! Experience has shown that providing a clean separation between the various functional parts of the program can make life a lot easier. This is what the Model-View-Controller architecture is all about. In essence, the code should clearly differentiate between the controls (buttons, scroll-bars, menus, mouse, etc.), the model itself (the internal representation of whatever real-world entity is being "simulated") and the view (the screen representation of the model or part of it.) Controls allow the user to effect changes in the model, which may subsequently be reflected in the visual representation of it that the user sees. This division of labour means that interface controls can be changed relatively easily, if necessary. For example, selection of a value from a list or by manipulation of a scroll-bar, could be substituted for inputting a numeric value from the keyboard. Such changes could be done without worrying about the code dealing with the model or the view. Similarly, such an architecture makes it easy to provide different views of the model, possibly at the same time.

Modern visual programming environments and object-oriented programming languages make it relatively easy to divide up your program in this way. You should thus try to analyse your problem with this separation of function in mind. Identify elements of the model and isolate them in their own classes, providing methods which can be called from the interface (controls) to manipulate it as necessary and to display it in a suitable form.

A Few Tips

Design is still more of an art than a science (thankfully, because that's what makes it interesting!) There is thus no substitute for experience and, since this is your first project, it is a good idea to consult with your assistant/instructor before progressing too far. Having said that, you should attempt to devise your own solution first.

It is perhaps a good idea to sketch out a high-level design for your program first. Several of the projects can be conveniently divided up into a client part (the bit users see) and a server part (which handles communication between clients and/or system data.) These would comprise two separate programs and, while I don't expect you to design and implement the server from scratch, you do need to be concerned with the interaction between these components. In essence this is no different to the communication between various sections of a single program, you just need to specify a set of methods to handle it. Some projects may even require that the server communicate with a database which comprises yet another element of your system. Within each of these major components you should also be able to identify sub-elements, for example, those concerned with administration, with communication, perhaps with registration procedures or with particular functions. It is quite possible that several of these share basic requirements. Try to identify such commonality since it will enable you to write a single piece of code which can be shared between the various program components. This will save you time and effort in the long run, by making the program easier to test, debug and maintain.

When it comes to identifying the objects/classes you need, the standard "method" is to look for the nouns and verbs in the problem specification. Nouns translate into objects and any attributes which may be associated with them are the object properties. Similarly, verbs indicate methods which affect the object. Having identified the objects involved in the model, attempt to generalise them into a set of classes. Remember, employing an object hierarchy and utilising polymorphism can make your program easier to write, test and maintain.

Object-oriented programming provides a natural metaphor (way) to structure your code, it can also ensure that those structures don't interfere with each other in unexpected ways. This is referred to as "encapsulation." As far as possible then, keep private data, private. It's very easy to make everything public, but doing so can lead to disaster later on, so don't do it! Objects can relate or work together in three ways; through inheritance (one class extends another), through composition (an object has another object as a part of it) and, finally, through use (one object uses the information in another object to complete its task.) It should be clear from your design which of these is being employed in each case.

The other major advantage OOP languages offer is reuse. Reusing existing code/classes can also save you a lot of time and effort, so look for opportunities to utilise the extensive program libraries now available and don't forget that you can always extend and modify them to better fit your needs! Nowadays, there are many books containing sample code, and the Internet provides a veritable warehouse of bits and pieces to get you going. If something exists and is freely available (i.e. not subject to copyright) then don't reinvent the wheel, use it (but remember to quote your sources, or else it may be classified as plagiarism!)

A Partial Example

Below is a partial design for the "Aid to Text Understanding" example used previously. The basic idea was to be able to change the manner in which various parts of an original plain text were displayed. This was achieved by applying different user-defined styles to the text. We thus need to store the styles themselves, as well as the original text and information about which parts of it to display in which style. The number of styles will vary during execution, however, we can assume that the maximum number of styles will be relatively low. This, and the fact that we will need to get fast access to individual styles, suggests that an array, vector or hash table are appropriate data structures. We choose a hash table.

Storing information about which parts of the text are to be displayed in which style is a critical part of the overall design. In essence it will be a set of items which specify the style, and the beginning and end points of the original text which is to be displayed in this style. It must allow for fast display of the text and also for efficient insertions, deletions and modifications. For this reason it is sensible to order the items by starting point and although an array could be used it seems preferable to employ a linked list. Such a data structure allows for very rapid insertion and deletion of items (compared to inserting an item in an ordered array which would necessitate moving lots of items to make room for the new arrival) and also takes only the amount of space actually needed (important since it is impossible to predict a reasonable maximum number of markups). Notice that we keep a reference to the style facilitating high-speed access to the style information during display. While saving and loading the view however, we must use the style name and reconstruct the references accordingly!

The following classes should thus form the basis of the design. Note that they are very incomplete, missing constructors and many of the set/get property methods, however, you should be able to understand the basic rationale.

Style

StyleSet

MarkUp

MarkUpSet

MarkedUpText

A graphical representation of the class diagram (partial) is given here:

(Partial) Class Diagram

Given such a breakdown,  all that remains is to assign individuals to work on the various groups of functionality. It makes sense to try to divide the work so that each person (or persons) is responsible for an independent set of classes. For example, the above problem might be divided such that one person looked after the styles, another the markups, another the view and another the actual user-interface. Each of these rely on the others for some of their functionality, however, providing you specify the methods properly, work can progress independently. Furthermore, when they are brought together they should work first-time.

Final Points to Remember

Time spent on this stage of the design will be repaid many times over during the implementation phase. Explicitly dividing the project into separate and independent modules, and writing clear specifications for the major classes, their properties and methods, means that the actual coding of them can be done concurrently by different people. It should also ensure that, when completed, they can be joined together without any problems to form a completely working whole. If (when) they don't you work properly you will realise that you didn't specify things precisely enough! Hopefully, you will then be able to do better next time.

This report is thus very much to your benefit. Having said that, time is running short, so I suggest that you concentrate on only the major functionality and omit the more simple, obvious bits this time. Again, please consult with your assistant before going too far. For drawing the UML diagrams there are a number of free tools available, for example: ArgoUML, UMLet, Creately, Violet, NClass, etc. Note that some of these are simple to use and "only" draw the diagrams, while others are more sophisticated. Some will export the outline Java code from your diagram, import existing Java code to create the corresponding UML diagram, and even offer suggestions for improving your design! Not all are actively maintained. Development environments including BlueJ, NetBeans & Eclipse might also be used (though the latter two, in particular, are large and have a steep learning curve!)

Your report must use the project reports template and include information about the model classes (not the UI ones), and a list showing which classes (including the UI ones) each group member will be responsible for.

----------------- O -----------------

(c) 1996-2003 David Davenport, 2007 David Davenport, Markus Schaal, 2011 David Davenport