# Adopt interface-based design pattern * Status: Accepted * Deciders: Gabriel Radureau, AI Agent * Date: 2026-04-02 ## Context and Problem Statement We needed to choose a design pattern for dance-lessons-coach that provides: - Good testability and mocking capabilities - Flexibility for future changes - Clear separation of concerns - Dependency injection support - Maintainability and readability ## Decision Drivers * Need for easy testing and mocking * Desire for flexible, maintainable architecture * Requirement for clear component boundaries * Need for dependency injection * Long-term evolution of the codebase ## Considered Options * Interface-based design - Define interfaces first, implement later * Direct implementation - Implement concrete types directly * Functional approach - Use functions and composition * DDD-style aggregates - Domain-driven design patterns ## Decision Outcome Chosen option: "Interface-based design" because it provides excellent testability, clear contracts, flexibility for future changes, and good support for dependency injection while maintaining good readability. ## Pros and Cons of the Options ### Interface-based design * Good, because excellent for testing and mocking * Good, because clear component contracts * Good, because flexible for future changes * Good, because supports dependency injection well * Good, because encourages good separation of concerns * Bad, because slightly more boilerplate * Bad, because can be over-engineered if taken too far ### Direct implementation * Good, because simpler and more direct * Good, because less boilerplate * Bad, because harder to test and mock * Bad, because less flexible for changes * Bad, because tighter coupling ### Functional approach * Good, because can be very clean and simple * Good, because good for pure functions * Bad, because less familiar in Go ecosystem * Bad, because harder to manage state ### DDD-style aggregates * Good, because good for complex domains * Good, because clear boundaries * Bad, because overkill for simple services * Bad, because more complex to implement ## Links * [Go Interfaces](https://go.dev/tour/methods/9) * [Effective Go - Interfaces](https://go.dev/doc/effective_go#interfaces) * [Dependency Injection in Go](https://go.dev/blog/wire) ## Implementation Examples ```go // Good: Interface defined first type Greeter interface { Greet(ctx context.Context, name string) string } type Service struct{} func (s *Service) Greet(ctx context.Context, name string) string { // implementation } // Bad: Direct implementation without interface type Service struct{} func (s *Service) Greet(name string) string { // implementation } ```