You are on page 1of 59

SOFE 2720

Principles of Software and Requirements


Engineering

Component-level Design

Notes adapted from - Software Engineering: A


Practitioner’s Approach, 9/e
Chapter 11
by Roger S. Pressman and Bruce R. Maxim
What is the component level?
• A complete set of software components is
defined during architectural design.
• The internal data structures and processing
details of each component are not represented
at the level of abstraction.
• Component-level design defines the data
structure, algorithm, interface, characteristics,
and communication to each software
component.

2
What is the component level?
What is a component?
• The Object Management Group (OMG) Unified
Modeling Language Specification defines a component
as
– “… a modular, deployable, and replaceable part of a system that
encapsulates implementation and exposes a set of interfaces.””
• Object-oriented view: a component contains a set of
collaborating classes.
• Traditional view: a component contains processing logic,
internal data structures that are required to implement the
processing logic, and an interface that enables the
component to be invoked and data to be passed to it.
• Process-related view: building systems out of reusable
software components or design patterns selected from a
catalogue (component-based software engineering).

4
What is a component? Cont’d
Component Diagram at a Glance

A component diagram breaks down the actual system under


development into various high levels of functionality.
Each component is responsible for one clear aim within the
entire system and only interacts with other essential elements
on a need-to-know basis.
Class-based Component-Level Design
• Each class within a component
has been fully elaborated to
include all attributes and
operations that are relevant to
its implementation.
• As part of the design
elaboration, all interfaces that
enable the classes to
communicate and collaborate
with other design classes must
also be defined.

7
Class-based Component-Level Design
• To accomplish this you begin
with the analysis model and
elaborate analysis classes (for
components that relate to
the problem domain) and
• infrastructure classes (for
components that provide
support services for the
problem domain).

8
Class-based Component-Level Design
• During requirements engineering, an
analysis class called PrintJob was
derived.
• During architectural design, PrintJob
is defined as a component within the
software architecture and is
represented using the shorthand
UML notation for a component.
• Two interfaces are defined for
PrintJob (inititiateJob and
computeJob)
– Any provided interfaces are shown as
lollipops while those required are
shown as cups.
– The interfaces provide one or more
operations.

6
Traditional Component Design
• Another approach for components design follows
a more traditional style focused on the operation
of the software product and any surrounding
components required to complete the product
such as, database access, security, management,
etc.
• These are typically defined in a hierarchical
manner by first defining components that are
focused on control with problem domain
components near the bottom of the hierarchy.

1
0
Traditional Component Roles
• Traditional components will take on one of 3
roles:
1. A control component that coordinates the invocation
of all other problem domain components,
2. A problem domain component that implements a
complete or partial function that is required by the
customer, or
3. An infrastructure component that is responsible for
functions that support the processing required in the
problem domain.

1
1
Traditional Component-Level Design
PrintJob Example 1

• In the PrintJob example


the top component is
the main “control”
component.
• Shaded boxes represent
components that
support the same
operations as those
defined in the Class
model.
• Other modules control
processing so are
considered “control”
modules”

12
Traditional Component-Level Design
PrintJob Example
• As the modules are
elaborated the
interface is defined
explicitly, the
function is defined,
and any internal
data structures.
• Typically behavior
of the module is
represented using a
State diagram.

13
ComputePageCost Module
• Offers 2 interfaces:
– getJobData – passes all
relevant Job data to the
component
–accessCostsDB – access all
print jobs’ costs.
• The component is
designed as a Class with
support operators (that
also include those
exposed via the Interface.

11
Some Component Design Principles

12
The OCP Basic Component Design Principle

• These principles also apply for OO design


• Open-Closed Principle (OCP). “A module
[component] should be open for extension but
closed for modification.
– You should specify the component in a way that allows
it to be extended (within the functional domain that it
addresses) without the need to make internal (code or
logic-level) modifications to the component itself.
– This is done by creating abstractions that serve as a
buffer between the functionality that is likely to be
extended and the design class itself.

13
Violation of OCP
• We have a Square and Rectangle class and a
ShapePrinter class that prints the shapes:
public class ShapePrinter {
public void drawShape(Object shape) {
if (shape instanceof Rectangle) {
// Draw Rectangle...
} else if (shape instanceof Square) {
// Draw Square...
}
}
}

• Existing code in ShapePrinter class has to be


changed to manage another shape.
Violation of OCP - Solution
• Create a new Abstract class called Shape with an
abstract operator draw() and override it for each
“new” shape. public abstract class Shape {
abstract void draw();
}

public class Rectangle extends Shape {


Note: You can also do
private int width;
this using Interfaces private int height;
public void draw() {
// Draw the Rectangle...
}
}

public class ShapePrinter {


public void drawShape(Shape shape) {
shape.draw();
}
}
The OCP Basic Component Design
Principle – SafeHome Example
–For example for the SafeHome security system, it
takes advantage of a Detector Class. The Detectors
can come in many different formats and interfaces.
–It is good deign to define a Detector Interface and
impose on all detectors particular operations.

19
The LSP Component Design Principle
• Liskov Substitution Principle (LSP). “Subclasses
should be substitutable for their base classes.
– Suggests that a component that uses a base class
should continue to function properly if a class derived
from the base class is passed to the component instead.
– Any precondition that must be true before the
component uses a base class and post-conditions that
should be true after the component uses a base class
should also be true for the use of derived sub-classes.

20
Violation of the LSP - Example
• Example:
–Creation of Square class that extends a Rectangle
class (the assumption is that a Square is a sub-class
of a Rectangle).
–This is not a good idea as there could be operators
defined in the Rectangle class that do not apply to
the Square class.

21
Violation of LSP
public class Rectangle { public class Square extends Rectangle {
private int width; @Override
private int height; public void setWidth(int width) {
public void setWidth(int width) { super.setWidth(width);
this.width = width; super.setHeight(width);
} )
public void setHeight(int height) {
this.height = height; @Override
} public void setHeight(int height) {
public int getArea() { super.setWidth(height);
return width * height; super.setHeight(height);
} }
} }

• We can break the assumptions of a rectangle


by executing the following code…
Violation of LSP - Solution
public class LiskovSubstitutionTest {

public static void main(String args[]) {


Rectangle rectangle = new Square(); // Square
rectangle.setWidth(2);
rectangle.setHeight(5);

if (rectangle.getArea() == 10) {
System.out.println(rectangle.getArea());
}
}
}

• That is valid for a Rectangle but not a Square.


• Solution:
– Define a Square as a separate Shape (Shape is an Interface
that defines a getArea abstract operator.
– In effect get rid of setter operators
The DIP Component Design Principle
• Dependency Inversion Principle (DIP).
“Depend on abstractions. Do not depend on
concrete components.”
–The more a component depends on other concrete
components (rather than on abstractions such as
an interface), the more difficult it will be to extend.
–If you dispense with design and hack out code, just
remember that code is the ultimate “concrete
implementation.” You’re violating DIP.

21
Dependency Inversion Principle Cont’d
Violation of DIP Example 1:
• We have a DeliveryDriver class that represents a driver
that works for a delivery company and a
DeliveryCompany that handles shipments
• DeliveryCompany creates instance of DeliveryDriver, a
lower level concept, and hence is now dependent on
that lower level concept.
public class DeliveryDriver {
public void deliverProduct(Product product){
// deliver product...
}
}

public class DeliveryCompany {


public void sendProduct(Product product) {
DeliveryDriver deliveryDriver = new DeliveryDriver();
deliveryDriver.deliverProduct(product);
}
}
Violation of DIP - Solution
• Create the DeliveryService interface and implement it in the DeliveryDriver
• Refactor DeliverCompany so that it depends on the DeliverService interface

public interface DeliveryService {


void deliverProduct(Product product);
}

public class DeliveryDriver implements DeliveryService {


public void deliverProduct(Product product) {
// deliver product...
}
}

public class DeliveryCompany {


private DeliveryService deliveryService;
public DeliveryCompany(DeliveryService deliveryService)
{
this.deliveryService = deliveryService;
}
public void sendProduct(Product product) {
this.deliveryService.deliverProduct(product);
}
}
Violation of DIP-Example 2:
Violation of DIP - Solution
The ISP Component Design Principle
• Interface Segregation Principle (ISP). “Many
client-specific interfaces are better than one
general purpose interface.”
–There are many instances in which multiple client
components use the operations provided by a
server class.
• ISP suggests that you should create a specialized interface
to serve each major category of clients.

24
Violation of ISP
• There is a Car Interface and Mustang class that implements
that Interface.
• We want to add a new car, DeLorean, that can travel in time
so new operators are defined in the Interface.
– Problem is that Mustang must also implement these operators.

public interface Car {


void startEngine();
void accelerate(); public interface Car {
} void startEngine();
void accelerate();
public class Mustang implements Car { void backToThePast();
@Override void backToTheFuture();
public void startEngine() { }
// start engine...
}
@Override
public void accelerate() {
// accelerate...
}
}
Violation of ISP - Solution
• Add a TimeMachine interface and have
DeLorean implement both Interfaces.
public class DeloRean implements
public interface TimeMachine { Car, TimeMachine {
void backToThePast(); @Override
void backToTheFuture(); public void startEngine() {
} // start engine...
}
public class Mustang implements Car { @Override
@Override public void accelerate() {
public void startEngine() { // accelerate...
// start engine... }
} @Override
@Override public void backToThePast() {
public void accelerate() { // back to de past...
// accelerate... }
} @Override
} public void backToTheFuture()
// back to de future...
}
}
The SOLID Principles
• These particular principles were introduced in the
early 2000s as the SOLID principles
• They are primarily applied to Object-Oriented
Software or Component design where Interfaces
are more readily available.
• When these principles are applied we achieve low
coupling and high cohesion since the software is
...
–Easy to maintain
–Easy to extend and
–Robust.
The “Other” Component Design Principles

• Release Reuse Equivalency Principle (REP). “The


granule of reuse is the granule of release.”
– The developer commits to establish a release control system
that supports and maintains older versions of the entity
while the users slowly upgrade to the most current version.
• Common Closure Principle (CCP). “Classes that change
together belong together.”
– When classes are packaged as part of a design, they should
address the same functional or behavioral area.
• Common Reuse Principle (CRP). “Classes that aren’t
reused together should not be grouped together.”

29
Pragmatic Component Level Design
Guidelines

30
Pragmatic Component-Level Design
Guidelines
• Components - Naming conventions should be
established for components that are specified as part of
the architectural model and then refined and
elaborated as part of the component-level model.
• Interfaces - provide important information about
communication and collaboration (as well as helping us
to achieve the OPC).
• Dependencies and Inheritance – For readability, it is a
good idea to model dependencies from left to right and
inheritance from bottom (derived classes) to top (base
classes).

36
Conducting Component-Level Design
• The following steps are typical when dealing with an OO
system.
• Step 1. Identify all design classes that correspond to the
problem domain.
• Step 2. Identify all design classes that correspond to the
infrastructure domain.
– These classes are not described in the requirements model and
are often missing from the architecture model, but they must be
described at this point (GUI, OS, data, etc.)
• Step 3. Elaborate all design classes that are not acquired as
reusable components.
– Step 3a. Specify message details when classes or component
collaborate. This can be captured in a UML Collaboration diagram
(Another UML diagram).

37
Collaboration Diagram with Message Detail

• Three objects collaborate


together to prepare a
print job for production.
• Messages are passed
between the objects
–The syntax is:
–[guard condition] sequence
expression (return value) :=
message name (argument
list)

38
Define Interfaces
• Step 3b. Identify appropriate
interfaces for each component.
– Components define Interface abstract
Classes for the operators for each
Interface (see InitiateJob)
• One could argue that the InitiateJob
interface does not exhibit sufficient
cohesion and should be broken up.
– One way is to define another component
called ProductionJob that offers the 2
interfaces buildJob and submitJob that
define the buildWorkOrder() and
checkPriority() operations.

39
Define Interfaces
• Step 3b. Identify appropriate interfaces for
each component.
–Refined design.

40
Component-Level Design
–Step 3c. Elaborate attributes and define data types
and data structures required to implement them.
• The UML structure for this is:
–name : type-expression = initial-value {property
string}
–For example:
• paperType-weight: string = “A” { contains 1 of 4 values - A,
B, C, or D}

41
Describe Processing Flow – Activity
Diagram
–Step 3d. Describe processing
flow within each operation in
detail.
• Activity diagram for
computePaperCost() operation.

42
Component-Level Design
• Step 4. Describe persistent data sources
(databases and files) and identify the classes
required to manage them.
–There are other models used for this such as data
relationship models that are not covered in this
course.

43
Behavioral Representations – State
Diagram
• Step 5. Develop and
elaborate behavioral
representations for a
class or component.
–State diagram for the
PrintJob class.
• Transitions take the
format of:
–Event-name (parameter-
list) [guard-condition] /
action expression

44
Component-Level Design
• Step 6. Elaborate
deployment diagrams to
provide additional
implementation detail.
– UML supports
deployment diagrams
that were briefly shown
in Learning Module 4 –
Design Concepts.
• This diagram shows how
components are
deployed on actual
hardware or servers.

45
Component-Level Design
• Step 7. Refactor every component-level design
representation and always consider
alternatives.
–Design is an iterative process.
–The first component-level model you create will not
be as complete, consistent, or accurate as the nth
iteration you apply to the model.
–It is essential to refactor as design work is
conducted.

46
Defining WebApps leveraging Component
Design

44
Component-Level Design for WebApps
• WebApp component is:
–a well-defined cohesive function that manipulates
content or provides computational or data
processing for an end-user, or.
–a cohesive package of content and functionality
that provides end-user with some required
capability.
• Component-level design for WebApps often
incorporates elements of content design and
functional design.

48
WebApp Content Design
• Focuses on content objects and the manner in which they
may be packaged for presentation to a WebApp end-user
• Consider a Web-based video surveillance capability within
SafeHomeAssured.com potential content components can
be defined for the video surveillance capability:
– the content objects that represent the space layout (the floor
plan) with additional icons representing the location of sensors
and video cameras;
– the collection of thumbnail video captures (each an separate data
object), and
– the streaming video window for a specific camera.
• Each of these components can be separately named and
manipulated as a package.

49
WebApp Functional Design
• Modern Web applications deliver increasingly
sophisticated processing functions that:
1. perform localized processing to generate content and
navigation capability in a dynamic fashion;
2. provide computation or data processing capability that is
appropriate for the WebApp’s business domain;
3. provide sophisticated database query and access, or.
4. establish data interfaces with external corporate systems.
• To achieve these (and many other) capabilities,
you will design and construct WebApp functional
components that are identical in form to software
components for conventional software.

50
Traditional Component Design

48
Traditional Component-Level Design
• Traditional components do not encapsulate data
the same way that OO components do.
–They focus on functions and data structures of the
software.
• Design of processing logic is governed by the basic
principles of algorithm design and structured
programming.
• Design of data structures is defined by the data
model developed for the system.
• Design of interfaces is governed by the
collaborations that a component must effect.

52
Component-Based Software Engineering
(CBSE)
• The software team asks:
–Are commercial off-the-shelf (COTS) components
available to implement the requirement?
–Are internally-developed reusable components
available to implement the requirement?
–Are the interfaces for available components compatible
within the architecture of the system to be built?

53
CBSE Benefits
• Reduced lead time. It is faster to build complete
applications from a pool of existing components.
• Greater return on investment (ROI). Sometimes savings can
be realized by purchasing components rather than
redeveloping the same functionality in-house.
• Leveraged costs of developing components. Reusing
components in multiple applications allows the costs to be
spread over multiple projects.
• Enhanced quality. Components are reused and tested in
many different applications.
• Maintenance of component-based applications. With
careful engineering, it can be relatively easy to replace
obsolete components with new or enhanced components.

54
CBSE Risks
• Component selection risks. It is difficult to predict component
behavior for black-box components, or there may be poor mapping
of user requirements to the component architectural design.
• Component integration risks. There is a lack of interoperability
standards between components; this often requires the creation of
“wrapper code” to interface components.
• Quality risks. Unknown design assumptions made for the
components makes testing more difficult, and this can affect system
safety, performance, and reliability.
• Security risks. A system can be used in unintended ways, and system
vulnerabilities can be caused by integrating components in untested
combinations.
• System evolution risks. Updated components may be incompatible
with user requirements or contain additional undocumented
features.

55
Component Refactoring
• Most developers would agree that refactoring components
to improve quality is a good practice.
• It is hard to convince management to expend resources
fixing components that are working correctly rather than
adding new functionality to them,
• Changing software and failing to document the changes can
lead to increasing technical debt.
• Reducing this technical debt often involves architectural
refactoring, which is generally perceived by developers as
both costly and risky.
• Developers can make of tools to examine change histories
to identify the most cost effective refactoring opportunities,

56
Important Notes about UML Component
and Object Diagrams

54
UML Component and Object Diagrams
• In the latest UML component diagrams show both provided
(lollipops) and required (cups) interfaces as shown below:

• In the UML there is no combined Component and Object


diagram as what the author is using.
– i.e. it is not possible to create diagrams like those in the textbook
using Visual Paradigm.
• What is possible?
– The internals of a Component can be viewed (white-box view)
where objects can be defined of the component.

58
White-box view of a Component in Visual
Paradigm
• This diagram shows the objects and their
interfaces for Component A.

59

You might also like