Imagine you want to build a remote control for different TV brands. Why is it better to design the remote control to work with a general TV interface instead of a specific TV brand's implementation?
Think about how many different TV brands you want your remote to control without changing the remote itself.
Programming to an interface means the remote control depends on a general contract (interface) that all TVs follow. This allows the remote to work with any TV brand that implements the interface, making the system flexible and easy to extend without changing the remote.
You are designing a payment system that supports multiple payment methods like credit card, PayPal, and bank transfer. Which design best follows the 'program to interface, not implementation' principle?
Think about how the system can add new payment types without changing existing code.
Defining a PaymentMethod interface and programming to it allows the system to treat all payment types uniformly. New payment methods can be added by implementing the interface without changing the system code, following the open-closed principle.
You have a notification system that sends messages via email, SMS, and push notifications. To scale and add new notification types easily, which approach best applies the 'program to interface' principle?
Consider how adding a new notification type affects existing code.
Using a NotificationSender interface allows the system to treat all notification types uniformly. Adding new notification types requires only implementing the interface without modifying existing code, which supports scalability and maintainability.
What is a common tradeoff when choosing to program to an interface rather than a concrete implementation?
Think about the cost of abstraction versus benefits.
Programming to an interface adds a layer of abstraction that can cause minor performance overhead due to indirection. However, this tradeoff is worthwhile because it makes the system more flexible and easier to maintain or extend.
You are designing a modular logging system where different modules can log messages to various outputs (console, file, remote server). How should components interact to follow the 'program to interface' principle?
Consider how modules can switch logging outputs without changing their code.
By defining a Logger interface and programming modules to it, the system allows swapping or adding new logging outputs without modifying module code. This decouples modules from concrete implementations and supports modularity and extensibility.