1
SOFTWARE ENGINEERING
Design Concepts and Principles
Design Engineering
2
Design Principles, Concepts, and Practices lead to the development of a
high quality system or product
Design principles and philosophy guides the designer Understand Design concepts designing Goal of design engineering is to produce a model or representation that is
Bug free (firmness) Suitable for its intended uses (commodity) Pleasurable to use (delight)
Software design practices are evolving
Design Concepts and Principles
3
Design: Design is a meaningful engineering representation of some software to be built. A design should be traceable to the customer's requirements. Design transforms requirements model into design models that describe the details of the data structures, system architecture, interfaces, and components. Review: Each design product should be reviewed for quality before moving to implementation.
Analysis Model to Software Design
4
Design Specification Models
5
Data design
Data dictionary and ERD Data structures, Files and DB
Architectural design
Relationships among the major structural elements of the software
Interface design
Communication between software components Communication with other systems Communication with human users
Component Level Design
Procedural descriptions of software components using information obtained from the PSPEC, and STD
Deployment Level Models
Quality Design Guidelines
6
Implement all explicit and implicit requirements
Be readable and understandable guide for those who write code, test components, or maintain
Provide a complete picture (data, function, behavior) of the software from an implementation perspective Exhibit good architectural structure Be modular Contain distinct representations of data, architecture, interfaces, and components (modules)
Quality Design Guidelines
7
Lead to data structures that are appropriate for the objects to be implemented and be drawn from recognizable design patterns Lead to components that exhibit independent functional characteristics Lead to interfaces that reduce the complexity of connections between modules and with the external environment Be derived using a repeatable method that is driven by information obtained during software requirements analysis
Design Principles
8
Design Process should not suffer from tunnel vision
Should be traceable to the analysis model
Should not reinvent the wheel Should minimize intellectual distance between the software and the problem as it exists in the real world Should exhibit uniformity and integration Should be structured to accommodate change Should be structured to degrade gently, even with bad data, events, or operating conditions are encountered Design is not coding, coding is not design. Should be assessed for quality as it is being created Should be reviewed to minimize conceptual (semantic) errors
Design Principles
1.
2.
The design process should not suffer from "tunnel vision." A good designer should consider alternative approaches, judging each based on the requirements of the problem, the resources available to do the job, and the design concepts. The design should be traceable to the analysis model. Because a single element of the design model often traces to multiple requirements, it is necessary to have a means for tracking how requirements have been satisfied by the design model.
3.
4.
The design should not reinvent the wheel. Systems are constructed using a set of design patterns, many of which have likely been encountered before. These patterns should always be chosen as an alternative to reinvention. The design should minimize the intellectual distance between the software and the problem as it exists in the real world. That is, the structure of the software design should copy the structure of the problem domain.
5.
6.
The design should be uniform and integrated. A design is uniform if it appears that one person developed the entire thing. Rules of style and format should be defined for a design team before design work begins. The design should be structured to accommodate change. The design concepts (discussed next) enable a design to achieve this principle.
The design should be structured to accommodate in any condition. Well-designed software should be designed to accommodate unusual circumstances, and if it must terminate processing, do so in a graceful manner. 8. Design is not coding, coding is not design. Even when detailed procedural designs are created for program components, the level of abstraction of the design model is higher than source code. The only design decisions made at the coding level address the small implementation details that enable the
7.
9.
10.
The design should be assessed for quality as it is being created, not after the fact. A variety of design concepts are available to assist the designer in assessing quality. The design should be reviewed to minimize conceptual (semantic) errors. There is sometimes a tendency to focus on details when the design is reviewed, missing the forest for the trees. A design team should ensure that major conceptual elements of the design (omissions, ambiguity, inconsistency) have been addressed before worrying about the syntax of the design
FURPS Quality Factors
14
Functionality Usability Reliability Performance Supportability
About Design
15
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies, and other way is to make it so complicated that there are obviously no deficiencies. The first method is for more difficult. (C.A.R. Hoare)
Fundamental Software Design Concepts
16 1.
Abstraction
2.
3. 4. 5. 6. 7. 8. 9. 10. 11.
Refinement
Modularity Software Architecture Control Hierarchy Data Structure Software Procedure Information Hiding Patterns Refactoring Functional Independence
1. Abstraction
17
The psychological notion of "abstraction" permits one to concentrate on a problem at some level of generalization without regard to irrelevant low level details
Abstraction is one of the fundamental ways that we as humans cope with complexity. Grady Booch Forms of Abstraction
Procedural abstraction: named sequence of events Data abstraction: named collection of data objects Control abstraction: control mechanism without specifying internal details
Encapsulation is the grouping of related ideas into one unit, which can thereafter be referred to by a single name.
2. Refinement
18
Process of elaboration where the designer provides successively more detail for each design component Stepwise Refinement
1969
A top-down design strategy originally proposed by Niklaus Wirth Article published in 1971
Abstraction and refinement are complementary concepts
BOOK: Algorithms + Data Structures = Programs
Abstraction & Refinement: Example
19
Please enter the number of integer values: 5 Please enter 5 integer values. 0 1 2 3 4 Please enter 5 integer values. 5 6 7 8 9 0 + 5 = 5 1 + 6 = 7 2 + 7 = 9 3 + 8 = 11 4 + 9 = 13 Sum = 45
main
ReadArraySize
CreateArray
ReadArray
AddArrays
SumArray
PrintArrays
PrintSum
DestroyArrays
PrintRow
DestroyArray
int main() { int *x, *y, *z, sum, size; size = ReadArraySize(); x = CreateArray(size); y = CreateArray(size); z = CreateArray(size); ReadArray(x, size); ReadArray(y, size); AddArrays(x, y, z, size); sum = SumArray(z, size); PrintArrays(x, y, z, size); PrintSum(sum); DestroyArrays(x, y, z); return 0;
20
int ReadArraySize() { int size; cout << "Please enter the number of integer values: "; cin >> size; return size; }
int* CreateArray(int size) { int* ptr; ptr = new int[size]; return ptr; } void ReadArray(int array[], int length) { cout << "Please enter " << length << " integer values." << endl; for (int i=0; i<length; i++) cin >> array[i]; }
void AddArrays(int x[], int y[], int z[], int size) { for (int i=0; i<size; i++) z[i] = x[i] + y[i]; }
21
void PrintRow(int a, int b, int c) { cout << a << "\t+\t" << b << "\t=\t" << c << endl; } void PrintArrays(int x[], int y[], int z[], int size) { for (int i=0; i<size; i++) PrintRow(x[i], y[i], z[i]); } void PrintSum(int sum) { cout << "Sum = " << sum << endl; } int SumArray(int array[], int size) { int sum=0; for (int i=0; i<size; i++) sum += array[i]; return sum; } void DestroyArray(int* ptr) { delete[] ptr; } void DestroyArrays(int x[], int y[], int z[]) { DestroyArray(x); DestroyArray(y); DestroyArray(z); }
22
3. Modularity
23
Modularity
The degree to which software can be understood by examining its components independently of one another
Modularity is the single attribute of software that allows a program to be intellectually manageable Module Interface: float sqrt(float value);
Modular Design Method Evaluation Criteria
24
Decomposability
Provides systematic means for breaking problem into sub-problems
Composability
Supports reuse of existing modules in new systems
Understandability
Module can be understood as a stand-alone unit
Continuity
Side-effects due to module changes minimized
Protection
Side-effects due to processing errors minimized
4. Software Architecture
25
Architecture is a comprehensive framework that describes its form and structure, its components and how they fit together. (Jerrold Grochow)
Architectural design specifies properties
Structural properties Extra-functional properties Families of related systems
Software Architecture
1.
2.
3.
Structural properties. This aspect of the architectural design representation defines the components of a system (e.g., modules, objects, filters) and the manner in which those components are packaged and interact with one another. Extra-functional properties. The architectural design description should address how the design architecture achieves requirements for performance, capacity, reliability, security, adaptability, and other system characteristics. Families of related systems. The architectural design should draw upon repeatable patterns that are commonly encountered in the design of families of similar systems. In essence, the design should have the ability to reuse architectural building blocks.
Models in Software Architecture
27
The architectural design can be represented using one or more of different models:
Structural models
Represent architecture as an organized collection of program components
Framework models
Increase the level of design abstraction by attempting to identify repeatable architectural design frameworks (patterns) that are encountered in similar types of applications
Dynamic models
Address the behavioral aspects of the program architecture, indicating how the structure or system configuration may change as a function of external events.
Process models
Focus on the design of the business or technical process that the system must accommodate.
Functional models
Can be used to represent the functional hierarchy of a system.
5. Control Hierarchy
28
Also called program structure, represents the module organization and
implies a control hierarchy, but does not represent the procedural aspects of the software (e.g. event sequences)
Control Hierarchy Terminology
29
Span of control: Number of levels of control within a software product Depth: Distance between the top and bottom modules in program control structure Fan-out or width: Number of modules directly controlled by a particular module Fan-in: Number of modules that control a particular module Visibility: Set of program components that may be called or used as data by a given component Connectivity: Set of components that are called directly or are used as data by a given component)
6. Data structure
30
Representation of the logical relationship among individual data elements (requires at least as much attention as algorithm design)
7. Software Procedure
31
Precise specification of processing (event sequences, decision points, repetitive operations, data organization/structure) Procedure is layered
8. Information Hiding
32
Information (data and procedure) contained within a module is inaccessible to modules that have no need for such information
every module in the [...] decomposition is characterized by its knowledge of a design decision which it hides from all others. Its interface or definition was chosen to reveal as little as possible about its inner workings. (Prof. David L. Parnas)
Why Information Hiding?
33
Achieve potential for change.
The
internal mechanisms of the component can be improved without impact on other components.
Information hiding hides those program components from other classes which are likely to change.
9. Patterns
34
A pattern is a named nugget(piece) of insight which conveys the essence of a proven solution to a recurring problem within a certain context amidst competing concerns. (Brad Appleton)
Design Patterns
Reusable
Patterns
10. Refactoring
35
Refactoring is the process of changing a software system in such as way that it does not alter the external behavior of the code [design] yet improves its internal structure. (Martin Fowler)
Agile Development
11. Functional Independence
36
Functional independence is achieved by developing modules with single minded function and an aversion to excessive interaction with other modules. Leads to
Easier Testing Easier Maintenance
Functional Independence is measured by
Coupling Cohesion
Effective Modular Design
37
Functional independence
Modules have high cohesion and low coupling
Cohesion
Qualitative indication of the degree to which a module focuses on just one thing
Coupling
Qualitative indication of the degree to which a module is connected to other modules and to the outside world
Example: Design of Computer
38
Example: Computer Design
39
The two computer designs are functionally equivalent
Second design is Hard to understand Hard to locate faults Difficult to extend or enhance Cannot be reused in another product
Modules must be like the first design
Maximal relationships within modules, relationships between modules
minimal
Composite/Structured Design
40
Method for breaking up a product into modules for
Maximal interaction within module, and Minimal interaction between modules
Module cohesion
Degree of interaction within a module
Module coupling
Degree of interaction between modules
Cohesion
41
Degree of interaction within a module Seven categories or levels of cohesion (non-linear scale)
1. Coincidental Cohesion
42
A module has coincidental cohesion if it performs multiple, completely unrelated actions void threeinone(float val, float& sin, char *str, float& tax) { code for computing sin of val code for reversing str Code for computing tax }
Task A
Task B
Task C
Module
1. Coincidental Cohesion (Contd)
43
Arise from rules like
Every module will consist of between 35 and 50 statements
Why Is Coincidental Cohesion So Bad?
Degrades maintainability Modules are not reusable
FIX Break into separate modules each performing one task
2. Logical Cohesion
44
A module has logical cohesion when it performs a series of related actions, one of which is selected by the calling module
float arithmetic(int op, int x, int y)
{
if (op == 1) return x+y; if (op == 2) return x-y; if (op == 3) return x*y;
if (op == 4) return x/y;
Logical Cohesion (Contd)
45
Task A
Task B
Task C
Module
Logically Similar Tasks
Why Is Logical Cohesion So Bad?
The interface is difficult to understand Code for more than one action may be intertwined Difficult to reuse
3. Temporal Cohesion
46
A module has temporal cohesion when it performs a series of actions related in time
main() { Queue q; Stack s; s.top = -1; s.size = 100; q.rear = q.front = -1; q.size = 200; q.create(); s.create(); s.push(10); q.insert(s.pop()); }
main() { Queue q(200); Stack s(100); s.push(10); q.insert(s.pop()); }
Temporal Cohesion (Contd)
47
Task A (t0)
Task B (t0+1)
Task C(t0+2)
Module
Tasks to be executed in order
Why Is Temporal Cohesion So Bad?
Actions of a module are weakly related to one another, but strongly related to actions in other modules.
Not reusable
4. Procedural Cohesion
48
A module has procedural cohesion if it performs a series of actions related by the procedure to be followed by the product
Task A (t0)
Task B (t0+1)
Task C(t0+2)
Module
Elements of a component are related only to ensure a particular order of execution
Why Is Procedural Cohesion So Bad?
Actions are still weakly connected, so module is not reusable
void conv(int x) {
const int BITS=16;
int bits[BITS], i, left, right, temp; // initialize for (i=0; i<BITS; i++) bits[i]=0; // convert i=0; do { bits[i] = x%2, x /= 2; i++; } while (x); // reverse left=0, right=BITS-1; while (left<BITS/2) { int temp bits[left] = bits[left]; = bits[right]; } void conv(int x) { const int BITS=32; int bits[BITS]; zero(bits, BITS);
void zero(int bits[], int size) { } void binary(int bits[], int size, int x) { } void reverse(int bits[], int size) { } void print(int bits[], int size) { }
binary(bits, BITS, x);
reverse(bits, BITS); print(bits, BITS);
bits[right] = temp;
left++, right--;
} // print for (i=0; i<BITS; i++) cout << bits[i];
int main() { conv(299); }
49
5. Communicational Cohesion
50
A module has communicational cohesion if it performs a series of actions related by the procedure to be followed by the product, but in addition all the actions operate on the same data Task A (t0) Task B (t0+1) Task C(t0+2)
Module
Data
Why Is Communicational Cohesion So Bad?
Still lack of reusability
6. Functional Cohesion
51
Module with functional cohesion performs exactly one action
Why is functional cohesion so good?
More reusable Corrective maintenance easier
Fault isolation
Fewer regression faults
Easier to extend product
7. Informational Cohesion
52
A module has informational cohesion if it performs a number of actions, each with its own entry point, with independent code for each action, all performed on the same data structure Essentially, this is an abstract data type (Class)
Data
Entry
Task A
Entry
Exit
Task B
Exit
Entry
Task C
Exit
Coupling
53
Coupling: Degree of dependence among components
No dependencies
Loosely coupled-some dependencies
Highly coupled-many dependencies
High coupling makes modifying parts of the system difficult, e.g., modifying a component affects all the components to which the component is connected. Ripple Effect
Coupling
54
Degree of interaction (dependence) between two modules
Five categories or levels of coupling (non-linear scale)
1. Content Coupling
55
Two modules are content coupled if one directly references contents of the other Examples
Module A modifies statement of module B
Module A refers to local data of module B in terms of some numerical displacement within B
Module A branches into local label of module B
Why Is Content Coupling So Bad?
Almost any change to B, even recompiling B with new compiler or assembler, requires change to A
2. Common Coupling
56
Two modules are common coupled if they have write access to global data
zero
int x, y, z; void zero() { x=y=0; } void add() { z=x+y; } void loop() { while(z) cout << z--; }
add
Global Variables
loop
Why Is Common Coupling So Bad?
57
Contradicts the spirit of structured programming
The resulting code is virtually unreadable
Modules can have side-effects
This affects their readability
All modules must be read to find out a single module does Difficult to reuse Module exposed to more data than necessary
float arithmetic(int op, int x, int y)
3. Control Coupling
58
{
if (op == 1) return x+y;
if (op == 2) return x-y; if (op == 3) return x*y; if (op == 4) return x/y;
Two modules are control coupled if one passes an element of control to the other
Examples:
Operation code passed to module with logical cohesion Control-switch passed as argument
Why Is Control Coupling So Bad? Modules are not independent; module b (the called module) must know internal structure and logic of module a.
Affects reusability
Associated with modules containing logical cohesion
4. Stamp Coupling
59
Two modules are stamp coupled if a data structure is passed as a parameter, but the called module operates on some but not all of the individual components of the data structure
Many languages support passing of data structures
part record satellite coordinates segment table
struct quad { int w, x, y, z; }; int sum(quad q) { return q.x + q.y; }
Why Is Stamp Coupling So Bad?
60
It is not clear, without reading the entire module, which fields of a record are accessed or changed
Example: calculate withholding (employee record)
Difficult to understand and Unlikely to be reusable
More data than necessary is passed
Uncontrolled data access can lead to computer crime
There is nothing wrong with passing a data structure as a parameter, provided all the components of the data structure are accessed and/or changed
transpose_matrix (Matrix &m);
5. Data Coupling
61
Two modules are data coupled if all parameters are homogeneous data items [simple parameters, or data structures all of whose elements are used by called module] Examples
int sumAll(int array[], int size); void multiply_matrix(Matrix &a, Matrix &b, Matrix &result); int distance(Point a, Point b);
Why Is Data Coupling So Good?
The difficulties of content, common, control, and stamp coupling are not present Maintenance is easier
Example: Data Coupling
class Point { private: int x, y; public: Point(int px, int py) { x=px; y=py; } int getx() { return x; } int gety() { return y; } void setx(int val) { x = val; } void sety(int val) { y = val; } }; int square(int x) { return x*x; } int distance(Point a, Point b) { int dx = b.getx() - a.getx(); int dy = b.gety() - a.gety(); return sqrt(square(dx) + square(dy)); } int main() { Point a(10,5), b(20,40); cout << distance(a,b); }
Design Heuristics for Effective Modularity
63
Evaluate the first iteration of the program structure to reduce coupling and improve cohesion. Attempt to minimize structures with high fan-out; strive for fan-in as structure depth increases. Keep the scope of effect of a module within the scope of control for that module. Evaluate module interfaces to reduce complexity, reduce redundancy, and improve consistency. Define modules whose function is predictable and not overly restrictive (e.g. a module that only implements a single sub-function). Strive for controlled entry modules, avoid pathological connection (e.g. branches into the middle of another module)
Program structures
64
The Software Design Process
65
Requir ements specif ication Design acti ities v Architectur al design Abstr act specif ication Interface design Component design Data structur e design Algorithm design
System architectur e
Software specif ication
Interface specif tion ica
Component specif ication Design pr oducts
Data structur e specif ication
Algorithm specif tion ica
Generic Design Task Set
66
1.
Select an architectural pattern appropriate to the software based on the analysis model Partition the analysis model into design subsystems, design interfaces, and allocate analysis functions (classes) to each subsystem Examine domain model and design appropriate data structures for data objects and their attributes
2.
3.
Generic Design Task Set (contd)
67
4.
Design user interface
Review task analysis (use cases) Specify action sequences based on user scenarios Define interface objects and control mechanisms Review interface design and revise as needed
Specify algorithms at low level of detail Refine interface of each component Define component level data structures Review components and correct all errors uncovered
5.
Conduct component level design
6.
Develop deployment model