🧱 Interface Design
Interface design is the discipline of defining clear, minimal, and stable contracts that classes, modules, or services expose to each other. A well‑designed interface tells consumers what they can do, not how it is done. It is one of the most important foundations of maintainable, testable, and evolvable software.
Interface design — definition
Section titled “Interface design — definition”Interface design is the process of defining public contracts that specify the operations a component provides, the inputs it accepts, the outputs it returns, and the rules governing its behavior. A good interface hides implementation details, reduces coupling, and makes collaboration predictable.
It answers:
- What capabilities does this component expose?
- What is the minimal set of operations consumers need?
- How do we ensure stability even when internals change?
Why interface design matters
Section titled “Why interface design matters”Good interface design:
- Reduces coupling between components
- Makes code easier to test (mocking, dependency injection)
- Enables independent evolution of modules
- Improves readability and discoverability
- Prevents accidental misuse
- Supports clean architecture and SOLID principles
Poor interface design leads to brittle, tangled systems.
Core principles of interface design
Section titled “Core principles of interface design”- Abstraction — expose what to do, not how
- Encapsulation — hide internal details
- Cohesion — interfaces should group related operations
- Low coupling — avoid unnecessary dependencies
- Interface Segregation — prefer small, focused interfaces
- Clear contracts — define expectations, constraints, and invariants
- Stability — interfaces should change rarely
- Predictability — consistent naming and behavior
These principles ensure interfaces remain clean and evolvable.
What makes a good interface
Section titled “What makes a good interface”1. Minimal
Section titled “1. Minimal”Expose only what consumers need.
Avoid “fat interfaces” with unrelated methods.
2. Focused
Section titled “2. Focused”Each interface should represent a single capability or role.
3. Stable
Section titled “3. Stable”Internal changes should not break consumers.
4. Consistent
Section titled “4. Consistent”Naming, behavior, and error handling should follow predictable rules.
5. Composable
Section titled “5. Composable”Interfaces should work well together without forcing tight coupling.
6. Testable
Section titled “6. Testable”Interfaces should be easy to mock or stub.
Interface design workflow (practical)
Section titled “Interface design workflow (practical)”- Identify the responsibility the interface represents
- Define the minimal set of operations needed
- Specify inputs, outputs, and constraints
- Ensure separation of concerns
- Review for cohesion and coupling
- Validate with real usage scenarios
- Refactor if needed
Common interface design mistakes
Section titled “Common interface design mistakes”- Interfaces that expose implementation details
- Interfaces with too many unrelated methods
- Interfaces that force consumers to depend on things they don’t use
- Interfaces that change frequently
- Interfaces that leak domain or infrastructure concerns
- Interfaces that return overly generic types (e.g.,
object)
Example
Section titled “Example”If you apply interface design to a Daily Scrum application:
ISummaryGenerator
Section titled “ISummaryGenerator”- Responsibility: generate daily summaries
- Methods:
Generate(DailySession session) - Notes: allows multiple summary algorithms (Strategy pattern)
IPdfExporter
Section titled “IPdfExporter”- Responsibility: export summaries to PDF
- Methods:
Export(Summary summary) - Notes: hides PDF library details
INotificationService
Section titled “INotificationService”- Responsibility: send notifications
- Methods:
SendReminder(Member member) - Notes: allows email, SMS, or push implementations
Each interface is small, focused, and stable.
Takeaway
Section titled “Takeaway”Interface design defines clear, minimal, stable contracts between components. Good interface design reduces coupling, improves testability, and supports clean architecture. It is essential for building systems that are easy to evolve without breaking existing functionality.