Complete the code to apply the Single Responsibility Principle by separating concerns.
class UserManager: def __init__(self, user_repository): self.user_repository = user_repository def [1](self, user): self.user_repository.save(user)
The method name save_user clearly indicates the responsibility of saving a user, aligning with the Single Responsibility Principle.
Complete the code to follow the Open/Closed Principle by allowing extension without modification.
class NotificationSender: def send(self, message): [1]
Raising NotImplementedError enforces that subclasses must implement the send method, allowing extension without modifying the base class.
Fix the error in the code to comply with the Liskov Substitution Principle.
class Bird: def fly(self): print('Flying') class Penguin(Bird): def [1](self): print('Swimming')
Penguins cannot fly, so overriding fly to raise an exception violates Liskov Substitution Principle. Instead, define a new method swim for Penguin.
Fill both blanks to apply the Interface Segregation Principle by splitting interfaces.
class PrinterInterface: def print_document(self): pass class ScannerInterface: def [1](self): pass class MultiFunctionDevice(PrinterInterface, ScannerInterface): def print_document(self): print('Printing') def [2](self): print('Scanning')
Splitting interfaces into PrinterInterface and ScannerInterface allows clients to depend only on methods they use. Both blanks use scan_document to define scanning behavior.
Fill all three blanks to apply the Dependency Inversion Principle by depending on abstractions.
class DatabaseInterface: def [1](self, data): pass class MySQLDatabase(DatabaseInterface): def [2](self, data): print(f"Saving {data} to MySQL") class DataManager: def __init__(self, db: DatabaseInterface): self.db = db def save(self, data): self.db.[3](data)
By defining and using the save method in the abstraction and implementation, DataManager depends on the interface, not the concrete class, following the Dependency Inversion Principle.