Software Design
We will use the term "design" quite specifically in this course. It
is NOT the same as "development". It is not "anything you do before
coding."
Definition: (verb) Design is a problem solving process
whose goal is to find and describe a way to implement a system's
functional requirements subject to the contraints of the
non-functional and other requirements.
Definition: (noun) "Design is a meaningful engineering
representation of something that is to be built."
Example: A blueprint for a house is the classic example of an
architectural design.
Why do we need design? Imagine trying to build a house without a
blueprint. We need design to create a quality product. Design
avoids confusion and errors.
Unfortunately, often software development proceeds without
adequate design, using a "house of cards" approach. The result is
fragile, unstable, inflexible, error prone software.
What you need to know about design:
Design Methods (elaborated)
Software
Architecture and Design Patterns
Design Rationale Documentation
General software design approaches and
history
There are two prominent software design approaches: Functional and
Object Oriented
Each has many specific methodologies, but the most prominent are:
- Structured Design (functional)
- Unified Modeling Language - UML (object oriented)
The difference between the these two approaches is how they answer
this question: "Data or Algorithms, which to design first"
- A functional approach answers "Do algorithms first"
- An object oriented approach answers "Do data first"
Neither approach is superior. Each has advantages and disadvantages,
and is more appropriate for certain kinds of problems than
others. It's good to be familiar with both so you can choose
the best one for a given situation.
Historically, functional approaches came first. The reasons
are:
- Requirements are stated as functions, so functional design is
an obvious transition from requirements.
- Computer Architectures are functional, so early languages were
functional, and lend themselves to functional designs.
OOD is the "new kid" on the block, and it gets a lot of
hype. It solves some of the limitations of the functional
approach, but introduces others limitations of its own.
Design approaches in a nutshell
Functional design is a design approach which considers first what
functions
a system performs, and postpones consideration of data. It contrasts
with
OOD, which considers first what data comprise the system, and
postpones
consideration of its functions.
If you ever wrote a C program as one big main program with all
global data, you were doing
functional design (but poorly).
Functional design process
|
Object Oriented design process
|
1. Identify Functions |
1. Identify Classes and Attributes |
2. Identify Data |
2. Identify Operations |
3. Establish Hierarchy |
3. Establish Visibility |
4. Establish Interfaces |
4. Establish Interfaces |
Know how to choose between OO approach and Functional approach.
Four components of a design
Regardless which approach you take, your finished design must have
four components.
Mnemonic: PAID (Procedural, Architectural, Interface, Data)
"You won't get PAID until your design is complete."
Architectural design defines the structure and
relationships among major elements of the software. The
architecture is the framework of the solution, often comprised of
"design patterns." Examples: Class Diagram, Module hierarchy chart
(structure chart). "Architecture" when used to describe large
systems describes the major subsystems and their relationships
like client-server or peer-to-peer. When used within a subsystem
"architecture" is a class diagram.
Interface design describes how the elements of the design
will communicate with each other. It describes the "protocols" or
"contracts" that allow elements of the design to request services
of each other. Examples: C++ header file, Ada spec file, Java
interface. In OO design, this component is called Class Skeletons.
In a large system design, it means a communication protocol.
Procedural design describes how the functional aspects of
the software will work. It describes the logic and control
structures for the operations in the design. It's the algorithms
for each element in the solution. Examples: pseudocode,
flowcharts, sequence diagrams, n-s charts.
Data design describes the data structures which will store
the information used in the solution.
Usually each component has its own representation or notation,
but sometimes they are combined.
In a large system, this would include database design.
Design Principles
There are several principles which guide the design process. Three
important ones are decomposition, abstraction, and information
hiding.
Decomposition
Definition: To subdivide a solution into separable components that
are named and addressable.
Decomposition is the primary tool for attacking large problems,
by using a "Divide and conquer" strategy.
It helps us several ways:
- Allows for distribution of effort via parallel development.
- Makes testing easier by isolating errors
- Promotes reuse.
- Localizes changes for easier maintenance.
- Makes the solution simpler to comprehend
The disadvantage is the cost of integrating all the separate pieces.
Abstraction
Definition: To focus on the significant or essential aspects of a
situation or problem and ignore irrelevant details. In slang, it's
"Don't lose sight of the forest because of the trees."
Abstraction is a tool for coping with complexity. If you find
yourself feeling like there's too many things to keep in your head
at once, then invent an abstraction.
It helps us several ways:
- It simplifies a design by hiding low level details and keeping
the emphasis on the main features of the solution.
- It promotes implementation independence, meaning we
can change the implementation (low level) without affecting the
entire system (at a high level).
- It simplifies our thinking by allowing us to focus on the
problem domain and defer the details of the implementation until
later.
- It reduces errors by reducing the number of details we need to
hold in short-term memory.
Examples: "Sort" is a procedural abstraction, "Stack" is a data
abstraction.
Practice
Exercises
Abstraction and software evolution
Information Hiding
Closely related to abstraction, information hiding refers
specifically to suppressing (or keeping private) the internal
details of a program component. The internals of a component
are inaccessible to other components that don't have no need for
such information. Other components that wish to access it must
do so via the components public interface. Information hiding
gives a software design more integrity by controlling access to the
internals of a component.
Thoughtless or sloppy design can defeat the purpose of information
hiding. Read this example of a design which doesn't
respect encapsulation.
Document History
9/25/14 JD Added a few clarifying notes
2/9/04 JD Removed paragraph on encapsulation