14-Design Concepts and Principles
14-Design Concepts and Principles
Principles
Instructor: Mehroze Khan
Design Principles
• Design principles are guidelines for decomposing a system’s required
functionality and behavior into modules
• The principles identify the criteria
• for decomposing a system
• deciding what information to provide (and what to conceal) in the resulting modules
• Six dominant principles (general):
• Modularity
• Interfaces
• Information hiding
• Incremental development
• Abstraction
• Generality
Modularity
• Modularity is the principle of keeping the unrelated aspects of a system separate
from each other,
• each aspect can be studied in isolation (also called separation of concerns)
• If the principle is applied well, each resulting module will have a single purpose
and will be relatively independent of the others
• Each module will be easy to understand and develop
• Easier to locate faults
• because there are fewer suspect modules per fault
• Easier to change the system
• because a change to one module affects relatively few other modules
• To determine how well a design separates concerns, we use two concepts that
measure module independence: coupling and cohesion
Modularity: Coupling
• Two modules are tightly coupled when they depend a great deal on
each other
• Loosely coupled modules have some dependence, but their
interconnections are weak
• Uncoupled modules have no interconnections at all; they are
completely unrelated
Modularity: Coupling
Modularity: Coupling
• There are many ways that modules can depend on each other:
• The references made from one module to another
• The amount of data passed from one module to another
• The amount of control that one module has over the other
• Coupling can be measured along a spectrum of dependence, ranging
from complete dependance to complete independence
Modularity: Types of Coupling
• Content coupling
• Common coupling
• Control coupling
• Stamp coupling
• Data coupling
Used Unit
Incremental Development
• A uses graph can also help us to identify areas of the design that could be
improved
• Unit A has a fan-out of three in Design 1 but a fan-out of five in Design 2.
• Goal in designing a system is to create software units with high fan-in and low
fan-out.
• High fan-out usually indicates that the software unit is doing too much and
probably ought to be decomposed into smaller, simpler units
Incremental Development
• The cycle in uses graph identifies a collection of units that are
mutually dependent on each other.
• Cycles are not necessarily bad. If the problem that the units are
solving is naturally recursive, then it makes sense for the design to
include modules that are mutually recursive.
• Large cycles limit the design’s ability to support incremental
development: none of the units in the cycle can be developed (i.e.,
implemented, tested, debugged) until all the cycle’s units are
developed
Incremental Development
• We can try to break a cycle in the uses graph using a technique called
sandwiching
• One of the cycle’s units is decomposed into two units, such that one of the
new units has no dependencies
• Sandwiching can be applied more than once, to break either mutual
dependencies in tightly coupled units or long dependency chains
Abstraction
• An abstraction is a model or representation that omits some details
so that it can focus on other details
• The definition is vague about which details are left out of a model,
because different abstractions, built for different purposes, omit
different kinds of details
Using Abstraction (Sidebar)
• Suppose that one of the system’s function is to sort the elements of a
list L. The initial description of the design is:
1. Sort L in ascending order
2. The next level of abstraction may be a particular algorithm:
DO WHILE I is between 1 and (length of L)–1:
Set LOW to index of smallest value in L(I),..., L(length of
L)
Interchange L(I) and L(LOW)
ENDDO
• The algorithm provides a great deal of additional information; however,
it can be made even more detailed
Using Abstraction (Sidebar)
3. The third and final algorithm describes exactly how the sorting operation will work:
DO WHILE I is between 1 and (length of L)-1
Set LOW to current value of I
DO WHILE J is between I+1 and (length of L)
IF L(LOW) is greater than L(J)
THEN set LOW to current value of J
ENDIF
ENDDO
Set TEMP to L(LOW)
Set L(LOW) to L(I)
Set L(I) to TEMP
ENDDO
Using Abstraction (Sidebar)
• Each level of abstraction serves a purpose.
• If we care only about what L looks like before and after sorting, then the first
abstraction provides all the information we need.
• If we are concerned about the speed of the algorithm, then the second level of
abstraction provides sufficient detail to analyze the algorithm’s complexity.
• However, if we are writing code for the sorting operation, the third level of
abstraction tells us exactly what is to happen; little additional information is
needed.
Generality
• Make a software unit as universally applicable as possible, to increase
the chance that it will be useful in some future system
• We make a unit more general by increasing the number of contexts in
which it can be used.
Generality
• There are several ways of doing this:
Parameterizing context-specific information: We create a more general
version of our software by making into parameters the data on which it
operates.
Removing preconditions: We remove preconditions by making our
software work under conditions that we previously assumed would never
happen.
Simplifying postconditions: We reduce postconditions by splitting a
complex software unit into multiple units that divide responsibility for
providing the postconditions. The units can be used together to solve the
original problem or used separately when only a subset of the
postconditions is needed.
Generality
• The following four procedure interfaces are listed in order of
increasing generality:
PROCEDURE SUM: INTEGER;
POSTCONDITION: returns sum of 3 global variables