Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# have only one reason to change. This example bundles reading,
# writing and processing into one class, so it breaks SRP.


class MyCustomFileFormat(object):
""" This class violates the Single Responsibility Principle because:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# The Single Responsibility Principle (SRP) states that a class should
# do only one thing. Here the reading, writing and processing logic
# are split into separate classes.

#
# By splitting the class into three classes, we can now reuse the classes in
# other parts of the program. A change in one class will not affect the other
# classes. This makes the code more maintainable and easier to understand.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Open/Closed Principle - Bad Example
# ------------------------------------------------------------------------------
# The Open/Closed Principle (OCP) states that code should be open for
# extension but closed for modification. Adding a new format here
# requires changing the FileProcessor class, so OCP is violated.
# extension but closed for modification.
#
# Adding a new format here in the example below requires changing the
# FileProcessor class, so the open/closed principle is violated.

class FileProcessor(object):

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Open/Closed Principle - Good Example
# ------------------------------------------------------------------------------
# The Open/Closed Principle (OCP) says that classes should be
# extendable without needing to modify their source. FileProcessor
# composes formatter objects so new behaviour can be added safely.
# extendable without needing to modify their source.
#
# By using composition, we can extend the functionality of the FileProcessor
# class without changing its code. This allows us to add new file formats
# without modifying the existing class, adhering to the OCP.

class LowercaseFormat(object):

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Liskov Substitution Principle - Bad Example
# ------------------------------------------------------------------------------
# The Liskov Substitution Principle (LSP) requires that subclasses
# can stand in for their base class. Here the work method checks
# for `Baby` explicitly, so `Baby` cannot substitute `Human`.
# can stand in for their base class without altering the correctness of the
# program.
#
# Here without the LSP, we have a situation where a subclass (Baby) cannot be
# used in place of its superclass (Human). As a code smell, there is a
# conditional check in the `work` method of the `Human` class that
# checks the type of the object.

class Human(object):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
# ------------------------------------------------------------------------------
# The Liskov Substitution Principle (LSP) means that objects of a
# superclass should be replaceable with objects of its subclasses
# without breaking the program. Each subclass here simply extends
# Human without special checks.
# without breaking the program.
#
# In this example, we have a base class `Human` and two subclasses `Adult` and
# `Baby`. Both subclasses implement all the methods of the `Human` class,
# allowing them to be substituted for `Human` without violating the LSP.

class Human(object):

Expand Down Expand Up @@ -36,7 +39,3 @@ class Baby(Human):

def suckle(self):
print("{} suckling".format(self.name))




Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# Interface Segregation Principle - Bad Example
# ------------------------------------------------------------------------------
# The Interface Segregation Principle (ISP) advises that clients
# should not be forced to depend on methods they do not use. The
# Device class defines unrelated operations that specific devices
# need to ignore.
# should not be forced to depend on methods they do not use.
#
# In this example, we have a base class `Device` that defines methods
# for powering on, powering off, adjusting volume, and brightness. However,
# the `HeadSet` and `Monitor` classes only use a subset of these methods,
# leading to a violation of the ISP.

class Device(object):

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Interface Segregation Principle - Good Example
# ------------------------------------------------------------------------------
# The Interface Segregation Principle (ISP) breaks large interfaces
# into focused ones. Mixins here provide only the operations each
# device actually needs.
# into focused ones.
#
# This example defines a base Device class and several mixins for specific
# functionalities. Each device class inherits from Device and the relevant
# mixins, allowing for a clean separation of concerns and avoiding the need
# for devices to implement methods they do not use.

class Device(object):
# Defines only the common methods for all devices
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Dependency Inversion Principle - Bad Example
# ------------------------------------------------------------------------------
# The Dependency Inversion Principle (DIP) dictates that high level
# modules should not depend on low level ones directly. Calculator
# instantiates Math itself and so is tightly coupled to it.

# modules should not depend on low level ones directly.
#
# This example violates DIP by hard-coding a dependency on a specific
# math implementation instead of using an abstraction.

class Math(object):

Expand All @@ -20,7 +21,7 @@ class Calculator(object):

def __init__(self):

# Code smell: Dependency relationship is hard-coded (dependency)
# CODE SMELL: Math object is hard-coded (dependency)
# and not abstracted (injection)

self.math = Math()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Dependency Inversion Principle - Good Example
# ------------------------------------------------------------------------------
# The Dependency Inversion Principle (DIP) encourages depending on
# abstractions rather than concrete classes. Calculator receives an
# IMath implementation, decoupling it from a specific Math class.
# abstractions rather than concrete classes.
#
# This example demonstrates a simple math class that adheres to DIP. It defines
# an interface (IMath) that specifies the contract for math operations,
# allowing different implementations to be used without changing the
# dependent code (Calculator).


class IMath(object):
""" Simplified interface for junior math class """
Expand Down
Empty file added examples/C18_sqlite/__init__.py
Empty file.
7 changes: 5 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ nav:
# - Dunder Methods: A15_dunder_methods.md
# - Lambda Functions: A16_lambda_functions.md
# - Generators: A17_generators.md
# - Metaclasses: A18_meta_classes.md
# - Coroutines: A18_coroutines.md
# - Comprehensions: A19_comprehensions.md
# - Data Handling: A23_data_handling.md
# - Type Hints: A20_type_hints.md
# - Metaclasses: A21_meta_classes.md

- Design:
- OOP Basics: B01_oop_pillars.md
Expand All @@ -43,5 +43,8 @@ nav:

- Libraries:
- Logging: C01_logging.md
- Threading: C02_threading.md
- Miltiprocessing: C03_multiprocessing.md
- concurrent: C04_concurrent.md
- Serialization: C12_serialization.md
- Data Structures: C13_data_structures.md