CPSC 333 --- Lecture 14 --- Wednesday, February 7, 1996 Structured Design This is a method to convert an "informal specification" including a *set of data flow diagrams* and process specifications into a design that could be implemented using a language like Pascal or C. As I will describe it, it *does not* produce designs that - take advantage of the newer features provided by object-oriented programming languages. While it provides some limited support for "encapsulation of data" (information hiding) it doesn't really support inheritance or templates, so it doesn't help you to take advantage of opportunities for *reuse of software* - are suitable for "highly interactive" systems --- in which the user interacts with the system using a mouse as well as a terminal and has more control over the order in which things are done, than is generally provided by systems that use a "command line" interface, or rely on simple menus that could be used with a terminal, rather than on a workstation or PC running a windowing system. These simpler interfaces were the only ones in widespread use when this design method was developed. - are useful for *real time* systems, or other systems in which performance requirements play a greater role than they do in "traditional" business systems. We will *continue* to assume, as is still usually the case, that it's sufficient (and therefore appropriate) to design and implement without much consideration of performance requirements --- and, *after that,* perform tests that include "performance tests," in order to look for evidence that resource requirements haven't been met, find bottlenecks, and then recode (and possibly also redesign) where needed. - lead to innovative or elegant designs. Techniques like these can be used to deal with the 90% (or more) of the system that is routine --- just like most of the same systems that solve this kind of problem --- and that can be dealt with well enough using straightforward, conventional methods. The use of this kind of method will (arguably) free up more of your time for those parts of the problem that *do* require innovation or expertise. However, it does provide usable, *maintainable* designs for the type of programs (and programming languages) it does support. As well, highly interactive and real time systems often *do* include subsystems that *can* be developed using this older method, so it may still be useful. Finally, some of the ideas we'll see by studying this method *have* been carried forward into some of the more modern design techniques. This method also (probably still) has an *advantage* over some of the more modern techniques: It has been used for a substantial period of time and is now relatively well documented, in enough detail for use in a course like CPSC 333. Components The method converts a set of data flow diagrams and process specifications into - a structure chart --- showing the system's modules and data areas, their control structure, and the I/O between them - a module specification for each of the modules in the structure chart (as well as for the interface for each data area) A module is drawn as a rectangle, labeled by the module's name --- which should also be a reasonable name for a function or procedure in the program being developed: ______________________ | | | | | Enter New Student | | | |______________________| This generally corresponds to a single *function* or *procedure* in a language like FORTRAN or Pascal, or to a single *function* in C or C++ (but, *not* to an "object" or "class" in C++). The above notation is used to represent modules for procedures we'll need to develop ourselves. It's also useful (or necessary) to show "library modules" that are part of the operating system (or windowing system, or, more generally, software library or libraries) that supports the system we're developing --- that is, modules that we *don't* need to develop ourselves. An extra vertical bar on each side of the rectangle is used to identify these: ______________________ | | | | | | | | | | Get Character | | | | | | |_|__________________|_| A structure chart includes one *main module* --- the module at the top of the structure chart, which corresponds to the "main" part of the program being produced. Each module is connected to all the modules that it calls directly. This connection is often shown by having an arrow pointing from the calling module to the module it can call --- and this is how I'll draw these connections (when I remember to!). If you check the references you'll discover that Pressman doesn't draw these connections on his structure charts as arrows --- he simply connects the two modules using a line, with the module being called drawn below that module that's calling it. A structure chart also include representations of "data areas." In our "first draft" structure charts we'll draw these by listing the data area's name between two horizontal lines --- _______________ Stack _______________ By the time the structure chart has been completed, we will have identified a set of "interface functions" used for *all* communication between the data area and the rest of the system. At that point, the data area (also now called an "informational cluster") will be drawn as ____________________________________ | | | | | | New | Push | Pop | Empty? | |________|________|_______|__________| | | | Stack | |____________________________________| ... where the boxes at the top are labeled with the names of each of the interface functions that can be used by the rest of the system to access (or change) the data area. In the "draft" structure chart, you would include arrows down from each one of the modules (in the rest of the system) that could access the data area, down to the top horizontal line in the representation area. In the "completed" structure chart, each of these modules (from the rest of the system) must call one or more of the "interface" functions --- so you'd draw the arrows down to the box (or boxes) for the interface function (or interface functions) that the module calls. You can also use this notation to group together a set of "interface functions" that collectively provide access to an I/O device, so that the part of the system that communicates directly with that device --- and would need to be modified if that device was replaced --- are grouped together, and easy to find. Unfortunately, you *won't* find any reference to these "informational clusters" in Pressman's books; they're included (in Chapter 7) in Page-Jones' book on Structured Design. I believe they're also a recent addition to the notation and the method, representing a good idea that's been borrowed from object oriented development --- namely, a good way to use "information hiding" as part of this design technique. The structure chart also includes *data* passed between modules (or between modules and interface functions for data areas or I/O devices). Two symbols are used for data items --- one for "regular" data items, and another for "control signals" --- which you can think of as corresponding to someone pushing a button (and which would be drawn on "augmented DFDs" using dashed arrows, as was described in the Friday, February 2 lecture). A "regular" item is drawn using a short arrow, with a hollow circle at the one end of the arrow (and the arrow head at the other). This is labeled by the name of the data item. A control signal is drawn using almost the same symbol: The circle at the end of the arrow is filled in, rather than hollow. It is labeled by the name of the control signal. The data flows are drawn close to ("flowing along") the connections between modules, or between modules and interface functions, and each point from the module or function sending the data to the module or function receiving it. Each of these connections between modules corresponds to a (possible) procedure call --- so you'd generally have data flows down to the called module corresponding to each of the inputs provided by the module calling it, and you'd have data flows back up from the called modules corresponding to each of the outputs that the called module might return. The structure chart *does not* generally include anything that corresponds directly to the "Terminators" on the DFDs --- that is, to the people or other systems that the system being developed interacts with. It also *does not* generally include any of the data flows between the system and these terminators. There is one more symbol that isn't "standard" --- you might not even find it in Page-Jones' book --- but that does seem necessary (and that is, in fact, a "standard" flow chart symbol) --- the "Off Page Connector." ____ | | | | \ / \/ I suggest that, if you've run out of room at the bottom of page then, instead of having an arrow down to another module that's to be called, draw the arrow as going down to the top of one of these connectors. Label the connector "To (name of module you're calling)" by writing this message inside it, and put the number of the page that will contain the module being called, beside the connector. Show the data flowing to and from the called module beside the arrow to the connector, just as you would if it pointed directly to the module instead. On the page that contains the called module, show a matching off page connector at the top. Label this with "From (module that did the calling)" and put the page number of the module that called this one beside the connector. Draw an arrow from the bottom point of the connector down to the called module and reproduce the data flowing from and back to the calling module along this connection. With the possible exception of my addition of an "off page connection," the notation described here matches the notation used by Page-Jones exactly, in his book on Structured Design. You can find *lots* of examples of structure charts in that book, if you'd like to see a complete one now. We'll be developing some in the next few lectures and labs. The design method Outline: A) Produce a "First Cut" Structure Chart B) Evaluate and improve the structure chart until a usable structure chart has been obtained Step A starts with the data flow diagrams and consists of lots of small decisions and tests. Step B provides a way to improve the result of Step A (which we don't *expect* to be very good). Since Step B does exist, it isn't necessary to worry too much about how to make some of the decisions in Step A if they aren't clear --- you *will* have an opportunity to improve the structure chart that you create by making these decisions later on. I'll spend most of the lecture time on step A (and may end up producing a handout that covers step B). Step A, in more detail: Step A: Produce a First Cut Structure Chart A.1) Produce *one huge* data flow diagram representing the entire system to be designed A.2) if the data flow diagram contains more than "a few" (say, two or three) processes then A.2.1) Determine the "flow type" for the diagram. This is either "transform flow" or "transaction flow" A.2.2) Partition the data flow diagram using either "transform" analysis or "transaction" analysis, depending on which kind of information flow was identified A.2.3) Perform *first level factoring* --- Create a main module for the structure (sub) chart as well as some number of "controller" modules for subsystems, that are called by the main module A.2.4) Perform *second level factoring* --- Map *some* of the processes to new modules and connect them to the structure chart. Partition the remaining processes into a set of smaller data flow diagrams that will be processed by recursively applying this method (that is, "Step A.2") else (the data flow diagram is trivial) A.2.5) if one is needed, create a main module; then map each process into a new module that is called by this main module end if A.3) Add data areas and data flows to the structure chart. In the handout, "More Information about Entity Relationship Diagrams," a method was briefly described for converting an entity relationship diagram into a set of *data tables*. This method should be applied, and each of the resulting data tables should be used as a data area on your first cut structure chart. It is possible that the data flow diagrams included data stores that corresponded to "registers" --- which store a small amount of data --- and that didn't correspond to anything on the entity relationship diagram. A data area for each of these "data stores for registers" should be added to the structure chart as well. The details of steps A.2.2, A.2.3, and A.2.4 depend on the type of "information flow" that was identified in step A.2.1, so I'll be describing two versions of each of these steps --- one for "transform analysis," and the other for "transaction analysis." You can think of this as a method that allows you to start with a large data flow diagram an "empty" structure chart, and progressively add controller modules as well as modules corresponding to DFD processes, so that you grow the structure chart from the top down --- while "using up" some DFD processes, and carving the rest of the DFD up into smaller pieces as you go --- continuing until there are no DFDs (or their processes) left to deal with. Steps A.2.1 -- A.2.4 will be described in more detail in the next lecture(s).