DEV Community

Cover image for Software Design Principles: Building Robust Applications in Python 🧑‍🏫

Software Design Principles: Building Robust Applications in Python 🧑‍🏫

Software design principles are fundamental guidelines that help developers create code that is reliable, maintainable, and scalable. By following these principles, teams can reduce technical debt, ensure better collaboration, and deliver high-quality software.

Why Do Design Principles Matter?

Poorly designed software often leads to hard-to-maintain code, bugs, and frustration among developers. Design principles provide a foundation for writing code that is easy to understand, modify, and extend.

Let’s explore some essential software design principles, and see how they can be applied in a real Python project.


Key Principles

1. Single Responsibility Principle (SRP)

Definition:

A class should have only one reason to change, meaning it should have only one job or responsibility.

Why?

If a class does too much, changes in one part can unintentionally affect another, leading to bugs and confusion.


2. Open/Closed Principle (OCP)

Definition:

Software entities (classes, modules, functions) should be open for extension but closed for modification.

Why?

You should be able to add new features by adding new code, not by changing existing, stable code.


3. Liskov Substitution Principle (LSP)

Definition:

Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program.

Why?

This ensures that inheritance is used properly and that subclasses enhance, not break, the behavior of the base class.


4. Interface Segregation Principle (ISP)

Definition:

Clients should not be forced to depend on interfaces they do not use.

Why?

It’s better to have several small, specific interfaces than one big, general-purpose interface.


5. Dependency Inversion Principle (DIP)

Definition:

High-level modules should not depend on low-level modules. Both should depend on abstractions.

Why?

This reduces coupling between different parts of your application.


Example: Applying SRP and OCP in Python

Let’s build a simple notification system that sends messages via email or SMS. We'll apply the Single Responsibility Principle (SRP) and Open/Closed Principle (OCP).

Initial (Bad) Design

class Notifier:
    def send(self, message, type):
        if type == "email":
            # email sending logic
            print(f"Sending EMAIL: {message}")
        elif type == "sms":
            # sms sending logic
            print(f"Sending SMS: {message}")
Enter fullscreen mode Exit fullscreen mode

Problems:

  • The Notifier class has multiple responsibilities.
  • Every time a new notification type is added, we have to modify the class (OCP violation).

Refactored (Good) Design

Let’s use SRP by separating each notification type, and OCP by allowing new types via extension.

from abc import ABC, abstractmethod

class NotificationSender(ABC):
    @abstractmethod
    def send(self, message):
        pass

class EmailSender(NotificationSender):
    def send(self, message):
        print(f"Sending EMAIL: {message}")
        # Actual email logic here

class SMSSender(NotificationSender):
    def send(self, message):
        print(f"Sending SMS: {message}")
        # Actual SMS logic here

def notify(sender: NotificationSender, message: str):
    sender.send(message)

# Usage example
email_sender = EmailSender()
sms_sender = SMSSender()

notify(email_sender, "Hello via Email!")
notify(sms_sender, "Hello via SMS!")
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Each sender class has a single responsibility (SRP).
  • New senders (e.g., PushSender) can be added without modifying existing code (OCP).

You can find the complete code and exercises in the companion repository:

SebastianFuentesAvalos/article1_software-design-principles-python


Conclusion

Applying software design principles like SRP and OCP leads to cleaner, more maintainable, and scalable code. In Python, using abstract base classes and separation of concerns makes it easy to follow these guidelines.

If you want to see more principles in action, you can extend this example—try adding a PushSender for push notifications!


References:


Written by Sebastián Fuentes Avalos

Top comments (4)

Collapse
 
sebastianfuentesavalos profile image
Sebastian Nicolas Fuentes Avalos • Edited

Made with soul and blood 🩸

Collapse
 
victor_williamscruzmama profile image
VICTOR WILLIAMS CRUZ MAMANI

Oh yeah , My nigga friend 🗣️😸

Collapse
 
luzkalidgm profile image
Gabriela Luzkalid Gutierrez Mamani

good article

Collapse
 
victor_williamscruzmama profile image
VICTOR WILLIAMS CRUZ MAMANI

Really so good.