High-Level Design: A Quick Overview

Steven J Zeil

Last modified: Jan 29, 2020
Contents:

Abstract

High-level design is the process of breaking a large system into smaller manageable pieces that can work together to solve a larger problem.

This lesson presents a quick overview of classification, the dominant approach to high-level design.

1 Levels of Design

Software design is largely deivided into

Architectural Design
global decisions that affect nearly all components of a system.
High-Level Design
the division of a system into modular components
Low-Level Design
the selection of data structures and algorithms to implement an individual component
  • CS361 emphasizes this level of design



In current practice, the primary type of “component” that we seek is the class.

The process of discovering such classes is classification, and that is what this lesson will concentrate on.

2 Modeling Classes

We model classes by focusing on

attributes
the data components that conceptually make up or are “contained” within a class
methods
a.k.a. operations, the things we can to do to object of that class
relations
how does this class interact with the other classes in our design?

2.1 Attributes

An attribute of a class is a data property that is conceptually a part of that class.

 

For example, we might say that an duration or elapsed time can be broken down into hours, minutes, and seconds. Shown on the right is a UML diagram for a class with those three attributes.

2.1.1 Attributes $\neq$ Data Members

One possible realization of this class would be to indeed represent attributes as data members:

class Duration {
public:
    int hours;
    int minutes;
    int seconds;
}

Most class designers would balk at this however, preferring

class Duration {
private:
    int hours;
    int minutes;
    int seconds;
public:
    ⋮
    int getHours() const {return hours;}
    void setHours (int h) { hours = h; }
    
    int getMinutes() const {return minutes;}
    void setMinutes (int m) {minutes = m; }
    
    int getSeconds() const {return seconds;}
    void setSeconds (int s) { seconds = s; }    
}

Both of these are perfectly reasonable realizations of the idea that “a duration of time has attributes of hours, minutes, and seconds”.

This is another perfectly reasonable realization of that idea:

class Duration {
private:
    int secondsSinceMidnight;
public:
    ⋮
    int getHours() const {return secondSinceMidnight / 3600;}
    void setHours (int h);
    
    int getMinutes() const {return (secondSinceMidnight % 3600) / 60;}
    void setMinutes (int m);
    
    int getSeconds() const {return secondSinceMidnight % 60;}
    void setSeconds (int s);    
}

This implementation might be favored if we expect to do a lot of calculations on durations (e.g., adding times together).

This demonstrates that we can have the logical idea of an attribute that does not reflect the eventual data members. All of these possible implementations are still represented by the same UML diagram.

2.2 Operations

Operations are things we do to/with an object that are conceptually more complex than simple storage and retrieval.

 

It makes sense, for example, to add one duration to another. E.g., if I listen to a music track that takes 4 minutes, then another that takes 3 minutes and 30 seconds, then I have spent a total of 7 minutes, 30 seconds listening to music. Similarly if I say that one track takes 4 minutes and another takes 30 seconds less than the first, I should be able to compute the acutal duration of the second track by subtraction. I might also want to allow multiplication by an integer so that we could work with concepts like “twice as long as”.

In programming terms, operations will map onto public function members. (It is possible to model private members in UML, but that is generally reserved for the very late states of design.)

It’s possible to have classes that have the same attributes but different operations (and vice-versa).

 

Another idea of “time” is that of the time of day – a particular instant in time rather than a duration. The attributes are the same, but the operations would be different. It does not make any sense to add one time of day to another – you can’t add 12:30PM to 4:00AM and expect that to actually mean anything. But you might add a duration of 30 minutes to 12:30PM to figure out what time it is if you arrive for an appointment at 12:30PM and have to wait for 30 minutes.

2.3 Relations

So far we have talked about what is “inside” a single class. Relations describe important properties between pairs of classes.

2.3.1 Associations

 

The most basic form of relation is the association, which is simply any named relationship that we wish to discuss or focus on. We read these connections as meaning

Associations are very general, so much so that, without the label identifying what we mean by them, they would be too vague to be useful.

But when it’s time to write the labels for an association, there are a few of labels that occur so often in practice that they merit their own UML visual signal:

2.3.2 Aggregation

 

This new relation is aggregation, and can be read as “an Agenda is part of an Event” or “an Event has a(n) Agenda”.


As a general rule, aggregation relationships could be rewritten as attributes:

This…

 

…and this…

 

…mean pretty much the same thing.


Not all attributes, however, can be rewritten as aggregation.

2.3.3 Inheritance / Generalization / Specialization

In many real-world scenarios, we encounter pairs of classes where one class is a specialized form of the other. In programming languages, this is referred to as an inheritance relationship, and could be denoted as an association labeled as “specializes” or (in the other direction) “generalizes”, or, more simply “is a”.

For example, we might say that a Duration is a kind of “time”, and a TimeOfDay is another kind of time.

 

This diagram, for example, captures the ideas that

3 Classification

The Object-Oriented design philosophy states that

Every program is a simulation, and the quality of a program’s design is directly proportional to how faithfully it mimics the objects in the world being simulated and the way in which those objects interact.

Object-oriented design is all about designing software whose structure mimics the real world.

3.1 How Do We Discover Classes?

Remember, first and foremost, that classes are groups of objects and objects are things.

3.1.1 Look for “Things”

Look through the available documentation on the problem you are trying to solve. Talk to people who work in that world.

Look for the kinds of things (nouns or noun phrases) that get mentioned over and over in discussion the problem area.

3.2 How Do We Discover Relationships Among Classes?

Look through the available documentation on the problem you are trying to solve. Talk to people who work in that world.

Look for descriptions of how things interact.

3.3 Keep It Real!

Example: We have been tasked with automating the means by which public library patrons find books in the library.