0% found this document useful (0 votes)
19 views40 pages

220240313140539-Lesson 03

Uploaded by

mightymayktv
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views40 pages

220240313140539-Lesson 03

Uploaded by

mightymayktv
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 40

LESSON 03:

Design
Principles and
Patterns
C R E AT I N G R O B U S T A N D
M A I N T A I N A B L E S O F T WA R E
Definition of Design
Principles and Patterns
Design Principles:
• The fundamental guidelines and concepts that help in
creating robust, maintainable, and scalable software.
• Examples include SOLID principles, DRY (Don't
Repeat Yourself), KISS (Keep It Simple, Stupid), and
YAGNI (You Aren't Gonna Need It).
Design Patterns:
• Reusable solutions to common problems in software
design.
• Examples include Singleton, Factory Method,
Observer, and many more.
Importance in Software Development

Enhancing Maintainability: Design Scalability and Flexibility: They provide Code Reusability: Design patterns Ease of Collaboration: A common set of
principles and patterns contribute to code a foundation for scalable and flexible facilitate the reuse of proven solutions, design principles and patterns provides a
maintainability by promoting clean, software architecture, allowing systems to reducing redundancy and promoting a shared vocabulary for developers, making
modular, and easily understandable code. evolve and adapt to changing more efficient development process. collaboration and communication more
requirements. effective.
SOLID
Principles
Single Responsibility
Principle (SRP)
Definition:
• The Single Responsibility Principle (SRP) in
software design advocates that a class should have
only one reason to change, focusing on a single
responsibility or role within the system.

Example:
• Imagine a class responsible for user authentication
that also handles sending email notifications. This
violates the SRP because the class has multiple
responsibilities – managing user authentication
and email notification logic.
Open/Closed
Principle (OCP)
• Definition: Software entities (classes,
modules, functions) should be open for
extension but closed for modification.
Example: Instead of modifying existing
code, extend it. Use interfaces and
abstract classes to allow for future
enhancements without altering existing
code.
Liskov Substitution
Principle (LSP)
• Definition: Subtypes must be
substitutable for their base types
without altering the correctness of the
program.
• Example: If a class represents a
square, its subclass representing a
rectangle should not break any
assumptions made about the square
class (e.g., equal side lengths).
Interface Segregation
Principle (ISP):

• Definition: A class should not be


forced to implement interfaces it does
not use. Keep interfaces specific to
the needs of the implementing class.
• Example: Instead of a monolithic
interface for a printer, split it into
separate interfaces like Printable and
Scannable for better ISP adherence.
Dependency Inversion
Principle (DIP):

Definition: High-level modules should not


depend on low-level modules. Both should
depend on abstractions. Abstractions should
not depend on details; details should depend
on abstractions.
Example: Using dependency injection to
invert the control of instantiating and
managing dependencies, promoting
flexibility and easier testing.
Importance of a Solid Design Foundation
• Maintainability: A solid design foundation ensures that the codebase is easy to understand, modify, and extend.
This is crucial for long-term maintainability and reducing the cost of future changes.
• Scalability: A well-designed system can scale more effectively to handle increased complexity and evolving
requirements. It provides a robust structure that accommodates growth.
• Reduced Bugs and Technical Debt: Following design principles helps catch and prevent issues early in the
development process, reducing the accumulation of technical debt and minimizing the occurrence of bugs.
• Collaboration and Communication: A consistent design foundation provides a shared understanding among
team members, facilitating effective collaboration and communication.
• Adaptability to Change: A solid design foundation allows for easier adaptation to changing requirements. By
adhering to principles like the Open/Closed Principle, the system can be extended without major modifications.
Don't Repeat Yourself
(DRY)

Definition: Avoid duplicating code by


abstracting common functionality into
reusable components.
Example: If you find the same piece of code
repeated in multiple places, consider
creating a function or method to encapsulate
that logic. This not only reduces redundancy
but also makes the code easier to maintain.
Keep It Simple, Stupid (KISS)

• Definition: Prefer simplicity over


complexity in design and
implementation.
• Example: When designing a user
interface, avoid unnecessary features
and keep the layout and interactions
straightforward. This principle
encourages a clean and understandable
design.
You Aren't Gonna Need It (YAGNI)

• Definition: Only implement functionality


when it is actually needed, not when you
foresee that it might be needed in the future.
• Example: Avoid adding features or
functionalities to your codebase based on
speculative future requirements. Only
implement what is necessary for the current
use case.
Introduction to
Design Patterns
Design Patterns refer to reusable solutions to
common problems encountered in software
design. These patterns are templates providing a
general, reusable blueprint to solve recurring
design problems in a flexible and efficient
manner.

https://www.youtube.com/watch?v=tv-
_1er1mWI&ab_channel=Fireship
Introductio Purpose:
• Abstraction of Expertise: Design patterns capture the
n to Design collective experience of skilled software developers, abstracting
Patterns away common solutions to specific problems.
• Encapsulation of Best Practices: They encapsulate best
practices for design and development, providing a proven
structure for building robust and maintainable software.
• Promotion of Reusability: Design patterns promote code
reusability, allowing developers to use established solutions
rather than reinventing the wheel for similar problems.
• Enhancement of Communication: By using design patterns,
developers can communicate more effectively, as these patterns
provide a common language and understanding among team
members.
Importance of Using Design Patterns in Software Development:

Design patterns encourage the reuse of proven solutions, reducing redundancy in


Code Reusability: code. This results in more efficient development, promotes consistency, and helps
maintain a standard approach across the codebase.

Adopting design patterns establishes a consistent and standardized approach to


Consistency and Standardization: software design. This consistency enhances collaboration among developers and
makes the codebase more comprehensible and predictable.

Design patterns offer efficient solutions to recurring design problems. Developers


Efficient Problem Solving: can leverage these patterns to address common challenges, allowing them to
focus on unique aspects of a problem and avoid starting from scratch.

Design patterns act as a common language for developers. They provide a shared
Communication Enhancement: vocabulary and understanding, facilitating effective communication and
collaboration within development teams.

The use of design patterns contributes to higher code quality. Since these patterns
Quality Assurance: encapsulate best practices, they help prevent common errors and enhance the
overall reliability and robustness of the software.
Creational Design Patterns

Singleton Pattern

Factory Method Pattern

Abstract Factory Pattern


is a design pattern that restricts the
instantiation of a class to a single
instance and provides a global
point of access to that instance. It
ensures that a class has only one
instance and provides a way to
access it from any point in the
application. This pattern is
particularly useful when exactly
Singleton Pattern one object is needed to coordinate
actions across the system.
Purpose:

01 02 03 04
Single Instance: Global Access Point: Lazy Loading: Resource Sharing:
• The primary purpose of the • It provides a global point of access • Singleton can be designed to • The Singleton Pattern is useful when
Singleton Pattern is to ensure that a to the single instance, allowing other instantiate the instance only when it a single point of control or
class has only one instance, parts of the application to easily is first requested. This is known as coordination is required, such as
preventing multiple instances from interact with it. lazy loading, which helps improve managing a resource pool,
being created. performance by delaying the configuration settings, or a logging
instantiation until it is necessary. service.
Factory Method
Pattern

is a creational design pattern that provides


an interface for creating instances of a class,
but it allows subclasses to alter the type of
objects that will be created. It defines an
interface for creating an object but lets
subclasses alter the type of objects that will
be created. This pattern promotes loose
coupling by decoupling the client code from
the specific classes it instantiates.
Purpose:

Encapsulation of Object Flexibility and Extensibility: Reduced Coupling: Code Reusability:


Creation:
The Factory Method Pattern Subclasses can override the factory By relying on interfaces and abstract The pattern promotes the reuse of
encapsulates the creation of objects, method to create objects of different classes, the Factory Method Pattern common object creation logic across
allowing the client code to interact with types, providing flexibility and allowing reduces the dependency between the different subclasses, avoiding code
a common interface without being the system to be easily extended with client code and the concrete classes, duplication.
concerned with the specific class new classes. promoting a more modular and
instantiation details. maintainable design.
Abstract Factory
Pattern
is a creational design pattern that provides an
interface for creating families of related or
dependent objects without specifying their
concrete classes. It involves creating abstract
classes (interfaces) for each type of object to be
created and then providing concrete
implementations for these interfaces. The
pattern allows a client to interact with a family
of related objects without being concerned
about their specific classes.
Purpose:

Encapsulation of • The Abstract Factory Pattern encapsulates the creation of multiple


related objects, ensuring that the created objects are compatible and
Object Creation: designed to work together.

Flexibility and • It allows easy extension of a family of related objects. New variations of
the family can be introduced by providing new concrete
Extensibility: implementations of the abstract factory interfaces.

Consistent • Ensures that the created objects conform to a consistent interface,


promoting interoperability and reducing dependencies between client
Interfaces: code and concrete classes.

Variability Across • The pattern supports the creation of families of related objects that can
vary independently, providing flexibility in adapting to different
Product Families: requirements or configurations.
Adapter Pattern

Decorator Pattern
Structural
Design Patterns Composite Pattern
Adapter Pattern

is a structural design pattern that allows


incompatible interfaces to work
together. It acts as a bridge between two
incompatible interfaces, enabling them
to collaborate. This pattern involves a
single class called the Adapter, which is
responsible for joining functionalities of
independent or incompatible interfaces.
Purpose:

01 02 03 04
Interoperability: Reusability: Client-Server Integration: Legacy System Integration:
• The Adapter Pattern is used to allow • It promotes the reuse of existing • When a client expects a specific • It is useful when integrating new
the collaboration of classes with classes by providing a wrapper that interface, but the server provides a components with existing systems,
incompatible interfaces, enabling adapts their interfaces, rather than different one, the Adapter Pattern especially when the new components
them to work together seamlessly. modifying the existing code. allows these components to work have interfaces that differ from the
together without requiring changes existing ones.
in the client code.
Decorator Pattern

is a structural design pattern that allows


behavior to be added to an individual object,
either statically or dynamically, without
affecting the behavior of other objects from the
same class. It is achieved by creating a set of
decorator classes that are used to wrap concrete
components. This pattern is used to extend the
functionalities of classes in a flexible and
reusable way.
Purpose:

Dynamic Behavior Single Responsibility


Open-Closed Principle: Component Reusability:
Extension: Principle:

The Decorator Pattern allows


Conforms to the Open-Closed Promotes the Single
behavior to be added to Components can be reused in
Principle by allowing the Responsibility Principle by
objects dynamically at various combinations,
introduction of new dividing the responsibilities of
runtime, providing a flexible allowing for a more modular
decorators without modifying classes into smaller, focused
alternative to subclassing for and adaptable design.
existing code. decorators.
extending functionality.
Composite Pattern

is a structural design pattern that lets you


compose objects into tree structures to
represent part-whole hierarchies. It allows
clients to treat individual objects and
compositions of objects uniformly. In
simpler terms, the pattern enables the
creation of complex structures by treating
individual objects and compositions of
objects uniformly.
Purpose

Hierarchy Representation: Uniformity in Client Code: Recursion: Simplifying Client Code:


The Composite Pattern is used to It provides a way for clients to work The pattern supports the creation of Clients can interact with complex
represent part-whole hierarchies where with individual objects and recursive structures, allowing the structures in a simplified manner, as
clients can treat individual objects and compositions of objects without construction of complex objects through they do not need to know the specific
compositions of objects uniformly. distinguishing between them, resulting combinations of simpler objects. classes of the objects they are working
in more consistent client code. with.
Behavioral Design Patterns

1. Observer Pattern

2. Strategy Pattern

3. Command Pattern
Observer Pattern is a behavioral design pattern where an object,
known as the subject, maintains a list of its
dependents, called observers, that are notified of
any changes in the subject's state. This pattern
establishes a one-to-many dependency between
objects, allowing multiple observers to be
notified and updated automatically when the
subject's state changes.
Purpose

Loose Coupling: Decentralized Event Handling: Distributed Systems:


Communication:
The Observer Pattern promotes loose It provides a way for objects to Commonly used in event handling Useful in distributed systems where
coupling between the subject and its communicate without being directly systems where multiple components components need to be updated based
observers, allowing changes in one to aware of each other, allowing for more need to react to changes in a subject's on changes in other components without
not affect the other significantly. flexible and modular designs. state. direct dependencies.
Strategy Pattern

is a behavioral design pattern that defines a


family of algorithms, encapsulates each
algorithm, and makes them interchangeable.
It allows the client to choose the appropriate
algorithm at runtime without altering the
client's code. The Strategy Pattern enables a
class to have multiple algorithms and lets the
client select the one it needs.
Purpose

Algorithm Run-Time Algorithm Open-Closed


Code Reusability:
Encapsulation: Selection: Principle:
• The Strategy Pattern • It allows the client to • The pattern follows • Promotes code reuse
encapsulates choose an algorithm the Open-Closed by encapsulating
algorithms in dynamically at Principle, allowing algorithms in
separate classes, runtime, providing for the addition of separate strategy
making it easy to flexibility and new algorithms classes, making
add, modify, or adaptability. without modifying them easily
interchange them existing code. shareable across
without affecting the different contexts.
client.
Command Pattern

is a behavioral design pattern that


encapsulates a request as an object,
thereby allowing parameterization of
clients with queues, requests, and
operations. It enables the separation of
responsibilities between the sender and
the receiver of a request, allowing
requests to be queued, logged, or
undone.
Purpose
• The Command Pattern encapsulates requests as objects, allowing them to be parameterized with
Encapsulation of Requests: additional information, queued, or logged for later execution.

• It decouples the sender of a request from its receiver, allowing for more flexible and modular
Decoupling: designs where commands can be executed by different receivers without the sender's knowledge.

• Enables the implementation of undo functionality by storing command history and supporting
Undo Operations: operations to undo or redo previous actions.

• Supports the implementation of transactional behavior, where multiple commands can be


Transaction Support: grouped together and executed as a single atomic operation.
Best Practices for Design Principles and Design
Patterns:
Understand Follow Design Keep Code

Understand the Follow SOLID Design for Change: Keep Code Modular: Code to Interfaces:
Problem Domain: Principles: • Anticipate changes in • Modular code is easier to • Use interfaces or abstract
• Before applying design • Adhere to the SOLID requirements and design maintain and understand. classes to program against
principles or patterns, principles (Single systems that can easily Design patterns like the abstractions, promoting
thoroughly understand the Responsibility, adapt. Embrace principles Command Pattern and the flexibility and enabling the
problem domain. This Open/Closed, Liskov and patterns that support Composite Pattern easy replacement of
understanding helps in Substitution, Interface flexibility, such as the contribute to modular and implementations. This
selecting appropriate Segregation, Dependency Open/Closed Principle and extensible code. aligns with the
patterns and designing Inversion) for creating the Strategy Pattern. Dependency Inversion
solutions that align with maintainable, scalable, and Principle.
the actual requirements. flexible software designs.
Best Practices for Design Principles and Design
Patterns:
Favor Avoid Document Use Code

Favor Composition Avoid Document Design Use Design Patterns Regular Code
over Inheritance: Overengineering: Decisions: Wisely: Reviews:
• Prefer composition over • Apply design principles • Clearly document • Select design patterns • Conduct regular code
inheritance to achieve and patterns design decisions, based on the problem at reviews to ensure that
flexibility and avoid the judiciously. Avoid especially when using hand. Don't force design principles and
pitfalls of deep class overengineering design patterns. This patterns into the design patterns are consistently
hierarchies. The solutions that are more helps team members if they don't add value. applied across the
Composite Pattern is an complex than necessary understand the rationale Consider the trade-offs codebase. This
example of favoring for the current problem. behind design choices and implications of promotes knowledge
composition. and facilitates using a particular sharing and maintains
collaboration. pattern. code quality.
Best Practices for Design Principles and Design
Patterns:
Testability Keep Consistency Consider Continuous

Testability: Keep Code DRY Consistency in Consider Continuous


• Design systems with (Don't Repeat Naming and Coding Performance Learning:
testability in mind. Yourself): Style: Implications: • Stay updated on design
Patterns like Dependency • Apply the DRY principle • Maintain consistency in • While designing, consider principles, patterns, and
Injection (DI) can enhance best practices. Continuous
testability by allowing the to eliminate redundancy in naming conventions and the performance
code. Repeated patterns or coding style. This implications of design learning allows you to
substitution of apply new and improved
dependencies during functionalities can be improves code readability decisions. Some patterns
encapsulated using design and makes it easier for may introduce overhead, techniques to your designs.
testing.
patterns like the Template developers to understand so evaluate the trade-offs
Method Pattern. and contribute to the based on the application's
codebase. requirements.

You might also like