Concept · SOLID principles
Interface segregation principle
Clients shouldn't depend on methods they don't use: prefer small, client-specific interfaces over one large general-purpose one.
The interface segregation principle (ISP), the I in SOLID, says that no client should be forced to depend on methods it doesn't use. Many small, focused interfaces beat one large one.
Why fat interfaces hurt
interface UserRepository {
findById(id: string): Promise<User | null>
findByEmail(email: string): Promise<User | null>
save(user: User): Promise<void>
delete(id: string): Promise<void>
exportAllToCsv(): Promise<string>
rebuildSearchIndex(): Promise<void>
}A login function that only calls findByEmail now:
- recompiles or retests whenever export or indexing changes;
- needs a test double that stubs six methods, five of them irrelevant;
- hides its real dependency — reading its signature, you can't tell it only reads users by email.
Give it what it needs:
interface FindUserByEmail {
findByEmail(email: string): Promise<User | null>
}The full repository still implements this — structural typing in TypeScript and implicit interfaces in Go mean no extra declarations are needed.
The Go way
Go makes ISP the default style. Interfaces are satisfied implicitly, so the consumer declares the small interface it needs, next to the code that uses it, and any type with those methods fits. The standard library models it: io.Reader, io.Writer and io.Closer have one method each, composed into io.ReadWriteCloser only where all three are needed. The Go proverb: the bigger the interface, the weaker the abstraction.
A useful habit: accept the smallest interface that does the job, and return concrete types. A function that needs to read bytes should take an io.Reader, not an *os.File.
How small is too small
Splitting every interface into single methods can scatter related operations. Group methods that are always used together by the same kind of client. ISP is about matching interfaces to clients, not about minimising method counts. It works hand in hand with dependency inversion and makes test doubles trivial to write. See the SOLID lesson.