CtrlK
BlogDocsLog inGet started
Tessl Logo

pantheon-ai/design-principles

Strategic architecture, tactical design, and testable code principles (SOLID, Clean Architecture, Design Patterns, Testable Design)

97

Quality

97%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

dep-interface-ownership.mddesign-patterns/references/

title:
Interfaces Belong to Clients Not Implementers
impact:
CRITICAL
impactDescription:
enables true dependency inversion
tags:
dep, interfaces, dependency-inversion, ownership

Interfaces Belong to Clients Not Implementers

Interfaces should be defined in the layer that uses them, not the layer that implements them. The client owns the abstraction; the implementation adapts to it.

Incorrect (interface defined next to implementation):

// infrastructure/persistence/UserRepository.java
public interface UserRepository {
    User findById(String id);
    void save(User user);
}

// infrastructure/persistence/PostgresUserRepository.java
public class PostgresUserRepository implements UserRepository {
    // Implementation
}

// application/usecases/CreateUserUseCase.java
import infrastructure.persistence.UserRepository;  // Use case imports from infrastructure!

public class CreateUserUseCase {
    private final UserRepository repository;
}

Correct (interface defined where it's used):

// application/ports/output/UserRepository.java
public interface UserRepository {
    User findById(String id);
    void save(User user);
}

// application/usecases/CreateUserUseCase.java
import application.ports.output.UserRepository;  // Same layer import

public class CreateUserUseCase {
    private final UserRepository repository;  // No infrastructure dependency
}

// infrastructure/persistence/PostgresUserRepository.java
import application.ports.output.UserRepository;  // Infrastructure depends on application

public class PostgresUserRepository implements UserRepository {
    // Implementation adapts to the port
}

Note: This is the essence of the Dependency Inversion Principle. The high-level module defines what it needs; low-level modules conform to that contract.

Reference: Clean Architecture - Chapter 11: DIP

tile.json