Software Architecture - Ch5 - Part 2
Software Architecture - Ch5 - Part 2
Software Design
and Architecture
That Promote
Quality
The SOLID Principles
• The SOLID principles are object-oriented design and programming
guidelines that improve software maintainability and extendibility.
These principles make it easier for developers to manage software
complexity, particularly as systems evolve.
• By adhering to the SOLID principles, developers can create more
maintainable, understandable, and flexible systems, reducing the cost
and effort associated with extending and modifying software. These
principles encourage a more thoughtful approach to design and
implementation, promoting best practices that lead to higher-quality
software.
Cont.
• S - Single Responsibility Principle (SRP)
• Definition: A class should have one and only one reason to change.
This means that a class should have only one job or responsibility.
• Benefits: SRP simplifies classes, making them easier to
understand, test, and maintain. When a class is focused on a single
responsibility, changes to that responsibility are localised to one
class, reducing the risk of introducing bugs.
• Implementation: Identify the responsibilities of your classes. If a
class has more than one responsibility, consider breaking it down
into multiple classes, each handling a single concern.
Cont.
• O - Open/Closed Principle (OCP)
• Definition: Software entities (classes, modules, functions, etc.)
should be open for extension but closed for modification. This
means you should be able to add new functionality to an entity
without modifying its code.
• Benefits: OCP encourages a more modular and cohesive design,
reduces the risk of breaking existing functionality when adding new
features, and enhances maintainability.
• Implementation: Use abstraction and polymorphism to extend
behaviours without altering existing code. For example, you can
define interfaces or abstract classes that can be implemented or
extended by new classes.
Cont.
• L - Liskov Substitution Principle (LSP)
• Definition: Objects of a superclass should be replaceable with
objects of its subclasses without affecting the program's
correctness. In other words, subclasses should be substitutable for
their base classes.
• Benefits: LSP ensures that a class and its derived classes are used
correctly, preventing unexpected behaviour and bugs. It promotes
the code's robustness and reliability.
• Implementation: When designing your classes and inheritance
hierarchies, ensure that subclasses can effectively replace their
base classes without altering how they are expected to function.
Cont.
• I - Interface Segregation Principle (ISP)
• Definition: Clients should not be forced to depend on interfaces
they do not use. This principle aims to reduce the impact of changes
and improve system organisation.
• Benefits: ISP leads to a more modular design, reducing the risks of
changes in unrelated interfaces affecting other parts of the system.
It enhances class cohesion and maintainability.
• Implementation: Break down large interfaces into smaller, more
specific ones so that implementing classes only needs to be
concerned with the methods that are relevant to them.
Cont.
• D - Dependency Inversion Principle (DIP)
• Definition: High-level modules should not depend on low-level
modules. Both should depend on abstractions. Additionally,
abstractions should not depend on details. Details should depend on
abstractions.
• Benefits: DIP reduces the coupling between software modules,
making refactoring and swap-out implementations easier without
affecting higher-level components. This principle fosters a more
decoupled and flexible system architecture.
• Implementation: Use interfaces or abstract classes to define
abstract layers on which high-level and low-level modules can
depend. Ensure that the details of implementing something are kept
separate from the abstract interfaces.
Don't Repeat Yourself (DRY) Principle
• The DRY principle is a fundamental concept in software
development that emphasises the avoidance of code duplication. It
states that every piece of knowledge or logic should only be
represented in a system once. The underlying idea is to reduce
redundancy in software systems to improve maintainability,
scalability, and reliability.
• Adhering to the DRY principle is a critical practice in writing quality
software. Developers can create more maintainable, scalable, and
robust applications by ensuring that each piece of knowledge or
logic is represented only once in the system. While it is important
to avoid unnecessary duplication, developers should also be
cautious of over-engineering solutions in pursuing DRY, as the
ultimate goal is to enhance the code's clarity and maintainability.
Benefits of DRY
• Improved Maintainability: When code is not
duplicated, there is a single source of truth. If a change
is needed, developers only need to update the code in
one place, reducing the risk of inconsistent behaviour or
bugs in different system parts.
• Enhanced Readability: DRY code tends to be more
organised and easier to read. Developers can
understand the system's behaviour more quickly when
they do not encounter the same logic scattered across
multiple locations.
Cont.
• Reduced Debugging Time: When bugs occur, there is
only one place to fix them, simplifying the debugging
process. This efficiency can significantly reduce
development time and costs.
• Easier Refactoring and Scaling: A codebase that
adheres to the DRY principle is generally easier to
refactor and scale. Since changes are centralised,
modifying or expanding the system's functionality is
simpler.
Implementation of DRY
• Identifying Common Patterns: Developers should be
vigilant in identifying repeated code patterns. When
such patterns are found, they should consider
abstracting the common logic into a single component
or utility.
• Use of Functions and Methods: When the same code
block is used in multiple places, it should be extracted
into a function or method. This approach encapsulates
the repeated logic, allowing it to be reused without
duplication.
Cont.
• Leveraging Inheritance and Composition: In object-oriented
programming, inheritance and composition can share common
behaviour among different classes, reducing the need to
duplicate code.
• Employing Templates and Generic Programming: Templates
in languages like C++ or generics in Java and C# allow for the
creation of data structures and algorithms that work with any
type, reducing code duplication.
• Configurations and Externalisation: Instead of hardcoding
repeated values or settings, externalise them into configuration
files. This practice not only adheres to DRY but also enhances the
configurability of the system.
DRY vs. WET
• The opposite of DRY is WET, which stands for "Write
Everything Twice" or "We Enjoy Typing." WET code leads
to duplication, and DRY aims to prevent the issues
above. While DRY emphasises not duplicating logic, it's
crucial to balance it with readability and not over-
abstracting, which can lead to its own set of problems,
such as making the code harder to understand or
modify.