Lädt...


🔧 SOLID Principles - Explained Using Real World Examples in Python


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

SOLID Principles

SOLID Principles (Image Credit: FreeCodeCamp)

SOLID is an acronym that stands for five design principles that help developers create more maintainable, understandable, and flexible software. Let's go through each one with a relatable example.

1. S - Single Responsibility Principle (SRP)

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

Explanation: Imagine you have a tool that combines two different tasks, like sending emails and processing payments. If both tasks are handled by a single class, changes in the email feature might break the payment feature. By keeping these responsibilities separate, you minimise the risk of changes in one part affecting another.

Example:

class EmailSender:
    def send_email(self, recipient, subject, body):
        # Code to send an email
        print(f"Sending email to {recipient} with subject '{subject}'")

class PaymentProcessor:
    def process_payment(self, amount):
        # Code to process payment
        print(f"Processing payment of amount {amount}")

# Usage
email_sender = EmailSender()
email_sender.send_email("[email protected]", "Hello!", "Welcome to our service!")

payment_processor = PaymentProcessor()
payment_processor.process_payment(100)

In this example, EmailSender is responsible only for sending emails, and PaymentProcessor is responsible only for processing payments. They each have a single responsibility, making the code easier to maintain and extend.

2. O - Open/Closed Principle (OCP)

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

Explanation: This means you should be able to add new features or behaviors to a class without changing its existing code. Imagine you have a payment processing system, and you want to add a new payment method. You should be able to add this new method without modifying existing code.

Example:

from abc import ABC, abstractmethod

class PaymentProcessor(ABC):
    @abstractmethod
    def process_payment(self, amount):
        pass

class CreditCardPayment(PaymentProcessor):
    def process_payment(self, amount):
        print(f"Processing credit card payment of {amount}")

class PayPalPayment(PaymentProcessor):
    def process_payment(self, amount):
        print(f"Processing PayPal payment of {amount}")

# Usage
payments = [CreditCardPayment(), PayPalPayment()]
for payment in payments:
    payment.process_payment(100)

In this example, PaymentProcessor is an abstract class that defines a contract for processing payments. CreditCardPayment and PayPalPayment are implementations that extend this class. If you want to add a new payment method, you can create a new class that extends PaymentProcessor without modifying existing classes.

3. L - Liskov Substitution Principle (LSP)

Definition: Subtypes must be substitutable for their base types without altering the correctness of the program.

Explanation: This means that objects of a superclass should be replaceable with objects of a subclass without affecting the functionality of the program. For example, if you have a function that works with a Vehicle class, it should also work with any subclass like Car or Bike.

Example:

class Vehicle:
    def start_engine(self):
        pass

class Car(Vehicle):
    def start_engine(self):
        print("Starting car engine...")

class Bike(Vehicle):
    def start_engine(self):
        print("Starting bike engine...")

# Usage
def start_vehicle_engine(vehicle: Vehicle):
    vehicle.start_engine()

car = Car()
bike = Bike()

start_vehicle_engine(car)  # Should work fine
start_vehicle_engine(bike) # Should work fine

In this example, Car and Bike are subclasses of Vehicle. The start_vehicle_engine function can work with any subclass of Vehicle without needing to know the specifics of the subclass, which is in line with the Liskov Substitution Principle.

4. I - Interface Segregation Principle (ISP)

Definition: A client should not be forced to implement interfaces it does not use. Instead of one fat interface, many small interfaces are preferred based on groups of methods, each one serving one submodule.

Explanation: This principle suggests that you should create specific interfaces for each type of client rather than one general-purpose interface. Imagine you have a machine that can print, scan, and fax. If you have separate machines that can only print or scan, they shouldn't be forced to implement functionalities they don't use.

Example:

from abc import ABC, abstractmethod

class Printer(ABC):
    @abstractmethod
    def print(self, document):
        pass

class Scanner(ABC):
    @abstractmethod
    def scan(self, document):
        pass

class MultiFunctionDevice(Printer, Scanner):
    def print(self, document):
        print(f"Printing: {document}")

    def scan(self, document):
        print(f"Scanning: {document}")

# Usage
mfd = MultiFunctionDevice()
mfd.print("Document 1")
mfd.scan("Document 2")

Here, Printer and Scanner are separate interfaces. MultiFunctionDevice implements both, but if there were devices that only printed or only scanned, they wouldn't need to implement methods they don't use, adhering to the Interface Segregation Principle.

5. D - Dependency Inversion Principle (DIP)

Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces). Abstractions should not depend on details. Details should depend on abstractions.

Explanation: Instead of a high-level class depending directly on low-level classes, both should depend on an interface or an abstract class. This allows for more flexibility and easier maintenance.

Example:

from abc import ABC, abstractmethod

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

class EmailNotificationService(NotificationService):
    def send(self, message):
        print(f"Sending email: {message}")

class SMSNotificationService(NotificationService):
    def send(self, message):
        print(f"Sending SMS: {message}")

class NotificationSender:
    def __init__(self, service: NotificationService):
        self.service = service

    def notify(self, message):
        self.service.send(message)

# Usage
email_service = EmailNotificationService()
sms_service = SMSNotificationService()

notifier = NotificationSender(email_service)
notifier.notify("Hello via Email")

notifier = NotificationSender(sms_service)
notifier.notify("Hello via SMS")

In this example, NotificationSender depends on the NotificationService abstraction rather than on a concrete class like EmailNotificationService or SMSNotificationService. This way, you can switch the notification service without changing the NotificationSender class.

Conclusion

  • Single Responsibility Principle (SRP): A class should do one thing and do it well.

  • Open/Closed Principle (OCP): A class should be open for extension but closed for modification.

  • Liskov Substitution Principle (LSP): Subclasses should be substitutable for their base classes.

  • Interface Segregation Principle (ISP): No client should be forced to depend on methods it does not use.

  • Dependency Inversion Principle (DIP): Depend on abstractions, not on concrete implementations.

By following these SOLID principles, you can create software that is easier to understand, maintain, and extend.

...

🔧 🛠️ Cracking the Code: Master SOLID Principles in JavaScript with Real-World Examples 🚀


📈 44.92 Punkte
🔧 Programmierung

🔧 Understanding SOLID Principles with Python Examples


📈 38.39 Punkte
🔧 Programmierung

🔧 SOLID Principles Aren't Principles


📈 35.63 Punkte
🔧 Programmierung

🔧 SOLID Principles / Open - closed principles -


📈 35.63 Punkte
🔧 Programmierung

🔧 SOLID Principles: They're Rock-Solid for Good Reason!


📈 35.19 Punkte
🔧 Programmierung

🔧 Discover the Heart of Ethical Software Development: Principles, Practices, and Real-World Examples


📈 33.34 Punkte
🔧 Programmierung

🔧 Mastering SOLID Principles: A Guide with JavaScript Examples


📈 33.27 Punkte
🔧 Programmierung

🔧 SOLID Principles in Java with Examples


📈 33.27 Punkte
🔧 Programmierung

🔧 SOLID Principles in Functional Programming (FP) with examples


📈 33.27 Punkte
🔧 Programmierung

🔧 Solid Principles in GO with examples


📈 33.27 Punkte
🔧 Programmierung

🔧 Learn SOLID Principles in C# with Examples for Better Code


📈 33.27 Punkte
🔧 Programmierung

🔧 Understanding SOLID design principles with easy coding examples


📈 33.27 Punkte
🔧 Programmierung

🔧 Examples of SOLID Principles in Test Automation


📈 33.27 Punkte
🔧 Programmierung

🔧 Mastering SOLID Principles with Go Examples


📈 33.27 Punkte
🔧 Programmierung

🔧 SOLID Principles - Breaking Bad using Python 🧪


📈 32.67 Punkte
🔧 Programmierung

🔧 Solid Principles in Python


📈 28.73 Punkte
🔧 Programmierung

🔧 SOLID principles using some fun analogies with Vehicle Example


📈 27.54 Punkte
🔧 Programmierung

🔧 Optimizing Your Code with Python's Walrus Operator: Real-World Examples and Anti-Patterns to Avoid


📈 26.44 Punkte
🔧 Programmierung

🔧 Web Scraping with python: Real world examples


📈 26.44 Punkte
🔧 Programmierung

🔧 Jerseys as Join Tables: Using Real-World Examples to Understand Relationships Between Data


📈 25.25 Punkte
🔧 Programmierung

🔧 Python Program Examples – Simple Code Examples for Beginners


📈 24.44 Punkte
🔧 Programmierung

🔧 How do programming principles equate to life's principles?


📈 24.05 Punkte
🔧 Programmierung

🔧 S.O.L.I.D. Principles: Applying Single Responsibility Principle to Real-World Code


📈 23.68 Punkte
🔧 Programmierung

🔧 Understanding SOLID Principles: A Beginner's Guide


📈 23.61 Punkte
🔧 Programmierung

🔧 Solid Principles


📈 23.61 Punkte
🔧 Programmierung

🔧 The Foundation of Good Software Engineering: Mastering SOLID Principles


📈 23.61 Punkte
🔧 Programmierung

🔧 The SOLID Design Principles


📈 23.61 Punkte
🔧 Programmierung

🔧 Understanding the SOLID Principles in Programming


📈 23.61 Punkte
🔧 Programmierung

matomo