DEV Community

Software Design Principles with Python Example

Software Design Principles

Software design is a fundamental process in developing scalable, maintainable, and efficient applications. To achieve this, various principles have been established to help developers create high-quality software. Below, we will explore some of the most important principles along with a practical example in Python.

Fundamental Principles

1.Single Responsibility Principle (SRP)

Each class or module should have a single reason to change. This means a class should focus on one functionality.

2. Open/Closed Principle (OCP)

Software should be open for extension but closed for modification. New functionalities should be added without changing existing code.

3. Liskov Substitution Principle (LSP)

Subclass objects should be replaceable with superclass objects without altering program functionality.

4. Interface Segregation Principle (ISP)

No client should be forced to depend on interfaces it does not use. Large interfaces should be divided into smaller, more specific ones.

5. Dependency Inversion Principle (DIP)

High-level modules should not depend on low-level modules but on abstractions. This enhances software maintainability and scalability.

Example in Python

Let's imagine a notification system that follows the Dependency Inversion Principle (DIP). Instead of having a service depend directly on a specific implementation (such as email or SMS notifications), we use an abstraction to make the system flexible and easy to extend.

from abc import ABC, abstractmethod

# Interface for different types of notifications
class Notifier(ABC):
    @abstractmethod
    def send(self, message: str):
        pass

# Notifier implementation for email
class EmailNotifier(Notifier):
    def send(self, message: str):
        print(f"Sending email: {message}")

# Notifier implementation for SMS
class SMSNotifier(Notifier):
    def send(self, message: str):
        print(f"Sending SMS: {message}")

# Class using abstraction, avoiding direct dependency on a specific implementation
class NotificationService:
    def __init__(self, notifier: Notifier):
        self.notifier = notifier

    def notify_user(self, message: str):
        self.notifier.send(message)

# Using the system
email_notifier = EmailNotifier()
service = NotificationService(email_notifier)
service.notify_user("Your order has been shipped.")

sms_notifier = SMSNotifier()
service_sms = NotificationService(sms_notifier)
service_sms.notify_user("Your verification code is 1234.")
Enter fullscreen mode Exit fullscreen mode

Explanation of the Example

  • We define an interface (Notifier) with an abstract send() method, allowing new notification methods to be added without modifying existing code.

  • EmailNotifier and SMSNotifier implement the interface and define the send() method.

  • NotificationService depends on the Notifier abstraction rather than a specific implementation, adhering to the Dependency Inversion Principle (DIP).

Conclusion

Applying software design principles improves code structure and quality, making it more flexible and maintainable. In this example, we demonstrated how DIP helps decouple components and facilitate system extension without modifying existing code.

Link de github del ejemplo

https://github.com/juanjosee15/principios-diseno-software.git

Top comments (2)

Collapse
 
alexis_jean profile image
Alexis Jeanpierre MARTINEZ VARGAS

Great article! You provided a clear and concise explanation of key software design principles, and the Python example perfectly illustrates the Dependency Inversion Principle (DIP). I appreciate how you highlighted the importance of abstractions in making the system more flexible and maintainable. One observation: while the example focuses on DIP, it also subtly aligns with the Open/Closed Principle (OCP) by allowing new notifiers to be added without modifying existing code. This reinforces how design principles often complement each other in real-world applications. Well done!

Collapse
 
jhonticonachambi profile image
Jhon Thomas Ticona Chambi

I found this article pretty clear about software design principles, especially DIP. The Python example is well-structured and shows how to use abstractions to make the system more flexible and maintainable. I liked that it avoids direct dependencies on specific implementations, making it easier to add new notification types. As an improvement, it would be interesting to see how it works with dependency injection. Overall, it's a great resource for understanding SOLID with a practical example.