Software architecture and design patterns
Module 1
Design Pattern:
A design pattern is a general repeatable solution to a commonly
occurring problem in software design. A design pattern isn't a
finished design that can be transformed directly into code. It is a
description or template for how to solve a problem that can be used in
many different situations.
Types of design patterns
1. Creational: These patterns are designed for class instantiation.
2. Structural: These patterns are designed with regard to a class's
structure and composition.
3. Behavioural: These patterns are designed depending on how one
class communicates with others.
Describing design patterns:
Describing design patterns refers to the process of explaining and
documenting established solutions to recurring problems in software
development. It involves outlining how a specific design pattern
works, when to use it, and how it can be implemented in a software
project. The purpose of describing design patterns is to help
developers recognize common issues and apply appropriate solutions
more efficiently.
Here's how a design pattern is typically described:
1. Pattern Name
A short, descriptive name for the pattern. For example,
Singleton, Factory Method, or Observer. The name provides a
vocabulary for developers to communicate about the pattern.
2. Intent
A brief description of the problem the pattern addresses and the
solution it provides.
Example (Singleton): "Ensure that a class has only one instance and
provide a global point of access to it."
3. Motivation
Explains why the pattern is necessary and the type of scenario in
which it can be used. This helps understand the problem the pattern
solves.
Example (Observer): "When an object's state changes, all dependent
objects need to be updated automatically, such as in event-handling
systems."
4. Structure
Shows the relationships between the components of the pattern.
This often includes class diagrams, flowcharts, or UML diagrams that
illustrate how objects interact within the pattern.
5. Participants
Lists the classes and objects involved in the pattern and their roles.
6. Collaborations
Describes how the participants of the pattern interact and how the
pattern achieves its goal through these interactions.
7. Applicability
Details when and where the pattern is most useful. This includes
specific conditions or problem types where the pattern offers a good
solution.
The Catalog of Design Patterns:
The Design Patterns are organized into a form of a catalog. These
Design Patterns collectively assist in software engineering by finding
objects, specifying objects implementations, objects interfaces,
determining objects granularity, implementing reuse mechanisms, etc.
The Intents specify what the design pattern does. Some of the patterns
with their names and intents are as follows.
Abstract Factory: It indicates what factory is to be instantiated,
provides an interface to create families of objects without any
specification of their concrete classes.
Adaptor: Id Adapt or converts an interface of a class into
another one according to the client expectation and hence,
overcomes the problem of incompatible interfaces thereby
enabling the classes to work together.
Bridge: It Separates abstraction from its implementation to
make them independent.
Builder: It separates the complex objects constructions from
their representation in order to create different representations
with the same construction process.
Chain of Responsibility: It enables the handling of command
objects by passing them to other objects by using the logic
present in the processing of objects. In other words, its
decouples sender and receiver by formatting a chain of receiving
objects to pass the request until the request is handled by an
object.
Command: It encapsulates the action and its parameters and
hence, enables to parameterize the different requests of the
clients such as long or queue requests. It also assists undoable
operations.
Composite: It represents the objects in a tree structure where
each object represents the same interface. This enables clients to
treat individual objects and their compositions uniformly.
Decorator: It adds additional functionality to a class at runtime.
This Enables flexibility to subclass for adding functionality.
Facade: It creates a simplified/unified interface of existing
interfaces in the subsystems so as to handle common tasks
easily.
Factory Method: It focuses on objects creation of specific
implementation. lets the subclass decide as to which class to be
instantiated.
Flyweight: It performs sharing of common objects properties by
a large number of objects to save space.
Interpreter: It Deals with the implementation of a specified
computer language that solves specific problems. It interprets
sentences in language by representing the grammar of language
along with an interpreter.
Iterator: It enables sequential aggregate objects elements by
hiding their underlying representations.
Mediator: It provides a unified interface to the set of interfaces
in a subsystem. It provides loose coupling which enables objects
to refer to each explicitly and also varies objects interaction
independently.
Moment: It supports the rollback mechanism by enabling the
objects, to restore to their previous state without violation of
encapsulation.
Observer: Whenever an object changes its state, it raises an
event that notifies other objects and updates them automatically.
This defines a one-to-many dependency between the objects.
Prototype: Here Prototypical instance determines the type of
objects to be created. Further new objects are created by cloning
this prototype.
proxy: It provides an illusion by applying placeholder to other
objects in order to have control over it.
Singleton: It provides restrictions on instantiating a class to a
single object and also makes it globally accessible.
State: It Permits an alteration in the object’s behaviour with
alteration in its state. Allows objects type to change at runtime.
Visitors: It describes the skeleton of a program, enables
subclasses to define some steps of the algorithm, and also to
redefine certain steps without affecting the structure of the
algorithm.
Strategy: It defines the Family of algorithms and their selection
based upon the clients.
How design patterns solve design problems:
Design patterns don't solve other design patterns directly, but
rather they solve common design challenges or problems that occur in
software development. They act as templates or best practices,
providing proven solutions to recurring problems in software design
1. Reusability
Problem: Redundant or inefficient code.
Solution: Design patterns such as Factory, Singleton, or
Strategy increase reusability by providing a standard way to
handle object creation, strategy encapsulation, and more.
2. Maintainability
Problem: Difficult to maintain or extend code.
Solution: Patterns like Observer and Chain of Responsibility
promote modular designs.
3. Scalability
Problem: Code that doesn't scale well as the system grows.
Solution: Patterns such as Builder and Adapter allow systems to
scale more gracefully by separating concerns and providing
flexibility. The Adapter Pattern can allow incompatible
interfaces to work together, making the system more extensible
without large-scale modifications.
4. Flexibility
Problem: Code that is hard to modify or extend.
Solution: The Strategy Pattern or Template Method Pattern
promotes flexibility by allowing you to change the behaviour of
a class at runtime. Strategy.
5. Performance Optimization
Problem: Inefficient or slow operations.
Solution: Patterns like Flyweight reduce the memory footprint
by sharing common data across instances, and the Proxy Pattern
can defer costly object creation until it's really needed.
6. Concurrency
Problem: Managing multiple threads or processes effectively.
Solution: Patterns like Thread Pool or Singleton help manage
resource allocation efficiently in a multithreaded environment.
How to select a design pattern
Selecting the right design pattern depends on the problem you are
trying to solve. Here are steps to help guide the selection process:
1. Understand the Problem
Analyze Requirements: Clearly define what needs to be
achieved. Different problems will be best served by different
design patterns.
Identify Recurring Issues: If a specific type of problem occurs
frequently in your project, it may be a signal to use a specific
pattern.
2. Categorize the Problem
Design patterns are generally categorized into three types:
Creational Patterns: Focus on object creation (e.g., Singleton,
Factory, and Builder).
Structural Patterns: Deal with object composition and
structure (e.g., Adapter, Composite).
Behavioural Patterns: Focus on object interaction and
responsibilities (e.g., Observer, Strategy, Command).
3. Match the Problem with a Pattern
Here are some common scenarios and their corresponding
patterns:
Object Creation Complexity: If your class initialization
process is complex, look at Factory, Builder, or Prototype
patterns.
Multiple Implementations: If you need to handle multiple
implementations or behaviours, Strategy or State patterns
might be useful.
Communication Between Objects: For managing interactions
between objects, Observer, Mediator, or Command patterns
are often effective.
Large Complex Interfaces: If you are dealing with a large and
complex interface, Facade or Adapter can simplify interaction.
4. Evaluate the Context
Scalability: Will the solution scale with future requirements?
Flexibility: How easy will it be to extend or modify the design?
Performance Considerations: Some patterns (like Singleton)
can impact performance, so it's important to understand the
trade-offs.
5. Prototype or Test the Pattern
Build a prototype to see how well the pattern integrates with
your current system. Testing it in a small scope can help ensure
it's the right fit.
6. Consider Best Practices
Maintainability: Ensure that the pattern improves the
maintainability of your code.
Readability: The design pattern should make the system more
understandable for other developers.
Summary of Common Design Patterns:
Singleton: Use when you need exactly one instance of a class.
Factory Method: Use when creating an object requires
complex logic.
Observer: Use for one-to-many relationships.
Strategy: Use when you have multiple algorithms and you want
to select one at runtime.
Each pattern solves specific problems, so understanding both the
problem and the patterns is key to selecting the right one.
How to use a design pattern:
Using design patterns involves understanding the problem you're
facing in your software design and selecting a pattern that offers a
reusable solution. Here’s how you can effectively use a design
pattern:
1. Understand the Problem
Break down your problem into components. Is it about object
creation, structural relationships, or behaviour among objects.
Identify the pattern category: Creational, Structural, or Behavioural.
2. Choose the Right Design Pattern
Once the problem is clear, map it to a pattern:
Creational patterns like Singleton or Factory help with object
creation.
Structural patterns like Adapter or Composite deal with class and
object composition.
Behavioural patterns like Observer or Strategy manage
communication and assignment of responsibility between objects.
3. Study the Pattern’s Structure
Look at the UML diagram and class structure of the chosen pattern to
understand how components interact.
Analyze the purpose of each component (e.g., classes, interfaces) in
the pattern.
4. Implement the Pattern
Follow the structure of the pattern and apply it to your code. Create
classes/interfaces that align with the pattern’s structure.
Follow the relationships between these classes, as suggested by the
pattern.
Encapsulate logic in a way that decouples dependencies (e.g.,
Strategy pattern decouples algorithms from the client).
5. Test and Refine
Make sure the pattern fits the problem and doesn’t add unnecessary
complexity. Test the interaction between components to ensure they
behave as expected.
A notation for describing object oriented systems:
A common notation for describing object-oriented systems is
Unified Modeling Language (UML). UML is a standardized visual
language that helps in specifying, visualizing, constructing, and
documenting the object-oriented system. It consists of various
diagrams that represent different aspects of the system, such as
structure, behaviour, and interactions.
Here are some of the key UML diagrams used to describe object-
oriented systems:
1. Class Diagram
Purpose: Describes the structure of the system by showing classes,
their attributes, methods, and the relationships among objects.
2. Elements:
Classes: Represented as rectangles divided into three sections: class
name, attributes, and methods.
Relationships: Include associations, inheritances (generalizations),
compositions, and dependencies between classes.
3. Object Diagram:
Purpose: Shows a snapshot of instances (objects) at a particular point
in time, representing the system's state.
Elements: Objects (instances of classes) and links (instances of
relationships).
3. Sequence Diagram:
Purpose: Models the interaction between objects in a specific
sequence, detailing how processes operate over time.
Elements:
Objects: Represented horizontally at the top.
Messages: Shown as arrows indicating interactions (method calls)
between objects.
Lifelines: Vertical dashed lines that represent the lifetime of an object
during interaction.
4. Use Case Diagram
Purpose: Describes the functionality of a system from the perspective
of users (actors) interacting with it.
Elements:
Actors: Represent external users or systems.
Use Cases: Ovals representing functional requirements or
interactions.
5. State Diagram
Purpose: Depicts the lifecycle of an object, showing the states it goes
through in response to events.
Elements:
States: Represent different conditions of an object.
Transitions: Arrows between states showing the movement of an
object from one state to another.
6. Activity Diagram
Purpose: Illustrates the dynamic aspects of the system by showing
workflow from one activity to another.
Activities: Represented as rounded rectangles showing tasks or
functions.
Transitions: Arrows showing the flow from one activity to the next.
Overview of the analysis phase:
Analysis phase defines the requirements of the system,
independent of how these requirements will be accomplished. This
phase defines the problem that the customer is trying to solve. The
deliverable result at the end of this phase is a requirement document.
The analysis phase is a crucial stage in the software
development life cycle that helps the development team understand
and define the requirements of a project. It's a time when the team
works closely with stakeholders to identify and define their needs and
expectations.
Analysis Phase
Gathering the requirements functional
Requirement gathering is the process of creating a list of requirements
that define a project's goals and scope. It's often a design for a project,
and can have a big impact on its success.
Requirements gathering is the process of identifying your
project's exact requirements from start to finish.
This process occurs during the project initiation phase but
you'll continue to manage your project requirements
throughout the entire project timeline.
Gathering the requirements
Requirements gathering steps:
Step1: understand pain behind the requirement.
Step2: Eliminate language ambiguity.
Step3: Identify corner cases.
Step4: write user stories.
Step 5: create a definition of done.
It involves understanding the clients needs and identifying their
problems.
Requirement specification:
A Requirement Specification is a detailed document or statement
that outlines the functionalities, constraints, and criteria a system or
project must meet. It serves as a guideline for developers, designers,
and stakeholders throughout the project lifecycle. There are various
types of requirement specifications such as:
1. Business Requirement Specification (BRS): Defines high-
level business goals, objectives, and expectations.
2. Software Requirement Specification (SRS): Focuses on the
technical and functional aspects of the software being
developed.
3. Functional Requirement Specification (FRS): Describes the
functions, behaviour, and features that a system must deliver.
4. Non-Functional Requirements (NFR): Outlines the system
performance, security, reliability, and usability standards.
Conceptual classes and relationships:
A conceptual model captures the important concepts and
relationships in some domain. Concepts are represented by classes,
while relationships are represented by associations. Packages
represent groups of related classes, and objects represent specific
instances of classes.
A Conceptual class is an idea, thing, or object to
understand the real world situation.
It is considered in terms of its symbol, intension, and
extension. • Symbol words or images representing a
conceptual class.
The one-to-many relationships between conceptual models
and design models, and between design models and
implementation models are illustrated in the following
Figure.
Domain models are solution-independent descriptions of a
problem domain produced in the analysis phase of a software
engineering project. The term "conceptual model" is often used as a
synonym of "domain model".
A domain model may include both descriptions of the domain’s state
structure and descriptions of its processes. They are solution-
independent, or ‘computation-independent’, in the sense that they are
not concerned with making any system design choices or with other
computational issues.
Design and implementation:
Design and implementation is the fourth phase of the project
cycle, subsequent to value chain selection, value chain analysis and
designing the competitiveness strategy. While is it useful to separate
these phases for the purposes of discussion, in practice many of the
techniques and skills used in selection, analysis and strategy
development are continually applied during implementation.
It is essential that analysis continues during the
implementation phase, in order to guide modifications to
the competitiveness strategy in response to changes in the
market, the enabling environment or the chain itself.
The competitiveness strategy that informs project design is
not just a plan for helping individual firms become more
profitable, it is a road map for moving an industry toward
higher, sustained rates of growth.
It provides a vision of competitiveness and an upgrading
plan for the industry that helps us understand what needs
to be done to upgrade the industry, who therelevant
stakeholders are and what each of them needs to do, and
how the industry will attain the vision.