agentsclimarketplace

Clean architecture

Skill iceflower/agent-skills/clean-architecture

Agent Skills 오픈 표준 기반 AI 코딩 에이전트용 스킬 컬렉션 (Java, Kotlin, Spring, NestJS, K8s, Terraform, GraphQL, gRPC, OpenTelemetry, a11y, i18n 등 60개)

Install
npx -y skills add iceflower/agent-skills --skill clean-architecture

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Clean Architecture and Hexagonal Architecture (Ports & Adapters) patterns. Covers the dependency rule, domain layer isolation, use case (application service) design, repository pattern, input/output port definitions, adapter implementation, and onion architecture layering. Use when designing layered architecture, defining port/adapter boundaries, structuring domain-centric applications, or enforcing the dependency rule between infrastructure and domain layers.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

15.8 KB, as published. Nobody here has run it

Clean Architecture / Hexagonal Architecture Rules

Note: Code examples in this document use framework-agnostic pseudocode (a mix of common OOP syntax). They are not tied to any specific language or framework.

1. Architecture Principles

Dependency Rule

  • Dependencies always point inward: outer layers depend on inner layers, never the reverse
  • The domain layer is the center and has zero external dependencies
  • Framework, database, and UI are implementation details that belong to the outermost layers
  • Changes in infrastructure must never require changes in domain logic

Separation of Concerns

LayerResponsibilityChanges When
DomainBusiness rules, entities, value objectsBusiness requirements change
ApplicationUse case orchestration, portsWorkflow or use case changes
InfrastructureDatabase, messaging, external APIsTechnology or vendor changes
PresentationHTTP, CLI, event listener adaptersInterface or protocol changes

Core Principles

  • Business rules are independent of frameworks, databases, and delivery mechanisms
  • Each layer has a well-defined boundary with explicit contracts (interfaces)
  • Inner layers define interfaces (ports) that outer layers implement (adapters)
  • The architecture makes the system testable without external dependencies

2. Layer Structure

Layer Hierarchy (Inside-Out)

┌─────────────────────────────────────────────┐
│              Presentation Layer              │  Controllers, CLI, Event Listeners
├─────────────────────────────────────────────┤
│             Infrastructure Layer             │  DB, External API, Messaging
├─────────────────────────────────────────────┤
│              Application Layer               │  Use Cases, Application Services
├─────────────────────────────────────────────┤
│                Domain Layer                  │  Entities, Value Objects, Domain Services
└─────────────────────────────────────────────┘
         ▲ Dependencies point inward ▲

Layer Responsibilities

Domain Layer (Innermost)

  • Entities with identity and lifecycle
  • Value objects (immutable, equality by value)
  • Domain services (cross-aggregate logic)
  • Domain events
  • Repository interfaces (outbound ports)
  • No framework annotations, no infrastructure imports

Application Layer

  • Use case classes / application services
  • Inbound port interfaces (what the system can do)
  • Outbound port interfaces (what the system needs)
  • Command and query objects
  • Transaction boundary management
  • Event publishing orchestration

Infrastructure Layer

  • Repository implementations (ORM adapters, query builders, raw SQL)
  • External API clients
  • Message broker producers/consumers
  • File system access
  • Cache implementations
  • Framework-specific configuration

Presentation Layer

  • REST controllers / GraphQL resolvers
  • Request/response DTOs
  • Input validation (format-level, not business-level)
  • Authentication filter integration
  • API documentation annotations

3. Ports and Adapters Pattern

See references/ports-and-adapters.md for detailed patterns including:

  • Inbound ports (use cases) and inbound adapters (controllers)
  • Outbound ports (repository interfaces) and outbound adapters (implementations)

4. Package Structure

Recommended Layout

order/
├── domain/                              # Domain layer
│   ├── model/
│   │   ├── Order                        # Aggregate root
│   │   ├── OrderLine                    # Entity within aggregate
│   │   ├── OrderId                      # Value object (ID)
│   │   ├── OrderStatus                  # Enum
│   │   └── Money                        # Value object
│   ├── event/
│   │   ├── DomainEvent                  # Event marker interface
│   │   └── OrderConfirmedEvent          # Domain event
│   ├── service/
│   │   └── OrderPricingService          # Domain service
│   └── repository/
│       └── OrderRepository              # Outbound port (interface)
│
├── application/                         # Application layer
│   ├── port/
│   │   ├── inbound/
│   │   │   ├── CreateOrderUseCase
│   │   │   └── GetOrderQuery
│   │   └── outbound/
│   │       ├── PaymentGateway
│   │       └── NotificationSender
│   ├── service/
│   │   ├── CreateOrderService           # Use case implementation
│   │   └── OrderQueryService            # Query implementation
│   └── dto/
│       ├── CreateOrderCommand           # Input command
│       └── OrderDetailResult            # Output result
│
├── infrastructure/                      # Infrastructure layer
│   ├── persistence/
│   │   ├── entity/
│   │   │   └── OrderPersistenceEntity   # ORM / persistence entity
│   │   ├── repository/
│   │   │   └── OrderRepositoryImpl      # Outbound adapter
│   │   └── mapper/
│   │       └── OrderEntityMapper        # Persistence ↔ Domain mapper
│   ├── external/
│   │   └── StripePaymentGateway         # External API adapter
│   ├── messaging/
│   │   └── KafkaNotificationSender      # Messaging adapter
│   └── config/
│       └── PersistenceConfig            # Infrastructure config
│
└── presentation/                        # Presentation layer
    ├── controller/
    │   └── OrderController              # REST inbound adapter
    ├── dto/
    │   ├── CreateOrderRequest           # API request DTO
    │   └── OrderDetailResponse          # API response DTO
    └── mapper/
        └── OrderResponseMapper          # Request/Response ↔ Command/Result

Package Dependency Rules

presentation  → application  (invokes use cases)
infrastructure → domain      (implements repository ports)
infrastructure → application (implements outbound ports)
application   → domain       (uses domain model)
domain        → (nothing)    (no outward dependencies)
  • domain package must not import from application, infrastructure, or presentation
  • application package must not import from infrastructure or presentation
  • presentation must not import from infrastructure directly
  • Cross-cutting via dependency injection only (DI framework wires adapters to ports)

5. Data Transformation Between Layers

See references/data-transformation.md for detailed patterns including mapping examples, use case implementation, and test examples.

Key Rules

  • Each layer boundary has its own data objects -- never pass persistence entities to controllers
  • Mapping logic lives at the boundary of the outer layer (adapter side)
  • Domain objects never depend on DTO or persistence entity classes
  • Use dedicated mapper classes or mapping functions for conversions

6. Dependency Inversion Principle (DIP)

Core Mechanism

The domain and application layers define interfaces (ports) that the infrastructure layer implements. A dependency injection framework wires the concrete implementations at runtime.

// Domain layer defines the interface
interface OrderRepository {
    fun findById(id: OrderId): Order?
    fun save(order: Order)
}

// Infrastructure layer implements it
// Repository implementation (infrastructure layer)
class OrderRepositoryImpl implements OrderRepository {
    private persistenceRepository: OrderPersistenceRepository

    fun findById(id: OrderId): Order? { ... }
    fun save(order: Order) { ... }
}

// Application layer depends only on the interface
// Application service
class CreateOrderService implements CreateOrderUseCase {
    private orderRepository: OrderRepository      // Port, not adapter
    private paymentGateway: PaymentGateway        // Port, not adapter

    fun execute(command: CreateOrderCommand): OrderId { ... }
}

DIP Benefits

Without DIPWith DIP
Service depends on OrderRepositoryImplService depends on OrderRepository (port)
Changing DB requires changing service codeChanging DB only requires new adapter
Testing requires real DB or mock frameworkTesting uses simple fake implementation
Domain coupled to frameworkDomain is framework-free

DIP Application Rules

  • Define interfaces in the layer that needs the capability (domain or application)
  • Implement interfaces in the outer layer that provides the capability (infrastructure)
  • Never create an interface just to have an interface -- use DIP only when the boundary is meaningful
  • Framework annotations belong on implementations, not on port interfaces

7. Use Case / Application Service Pattern

Use Case Design Rules

  • One class per use case (Single Responsibility)
  • Use cases are thin orchestrators -- business logic belongs in domain objects
  • Use cases handle transaction boundaries, not domain objects
  • Input is a command/query object, output is a result object or domain ID
  • Never return domain entities from use cases -- return result DTOs or IDs
  • Use case names describe business actions, not technical operations

Command vs Query Separation (CQS)

AspectCommandQuery
PurposeChange stateRead state
ReturnVoid or created IDResult DTO
SideWrite sideRead side
TxRead-write txRead-only tx
ExampleCreateOrderUseCaseGetOrderDetailQuery

8. Testability by Design

Testing Strategy Per Layer

LayerTest TypeDependenciesSpeed
DomainUnit testNone (pure logic)Fast
ApplicationUnit testFake ports (in-memory)Fast
InfrastructureIntegration testTest containers, HTTP mock serversSlow
PresentationAPI testHTTP test client, mock servicesMedium

Testability Rules

  • Domain layer tests require zero mocking -- if mocking is needed, the domain has external dependencies (violation)
  • Application layer tests use fake implementations of ports, not mocks
  • Infrastructure tests verify that adapters correctly translate between domain and technology
  • Presentation tests verify HTTP contract (status codes, response structure), not business logic
  • If a class is hard to test, it likely violates separation of concerns -- fix the design, not the test

9. Anti-Patterns

Domain Layer Violations

  • Framework annotations in domain: ORM annotations, DI annotations, transaction annotations on domain classes couples domain to framework
  • Infrastructure imports in domain: Domain classes importing framework or infrastructure packages
  • Anemic domain model: Domain objects with only getters/setters and all logic in services
  • Domain returning infrastructure types: Domain methods returning paginated wrappers, HTTP response objects, or persistence entities

Dependency Violations

  • Bidirectional dependencies: Application layer depending on infrastructure and infrastructure depending back on application
  • Skipping layers: Controller directly calling repository without going through use case
  • Shared mutable state: Passing persistence entities across layer boundaries (lazy loading failures, unintended mutations)

Structural Violations

  • God use case: Single application service handling dozens of unrelated operations
  • Leaky abstraction: Outbound port method signatures exposing infrastructure details (e.g., fun findByRawQuery(query: String))
  • DTO explosion: Creating separate DTOs for every minor variation instead of reusing where appropriate
  • Premature abstraction: Creating ports and adapters for internal modules that will never have multiple implementations

Common Mistakes

MistakeWhy It HurtsFix
Persistence entity as domain entityDomain coupled to persistence frameworkSeparate domain model and persistence entity
Business logic in controllerUntestable without HTTP contextMove to domain or application layer
Repository returning DTOsMixes persistence and presentationReturn domain objects, map at boundary
Transaction annotations on domain serviceDomain depends on frameworkPut transaction management on application service
Using framework events as domain eventsDomain coupled to framework event systemDomain defines events, application publishes via framework

10. Related Rules

Related SkillWhen to Reference
ddd skillDesigning entities, aggregates, value objects, domain events
code-quality skillAbstraction layers, modularity, single responsibility
testing-unit skillWriting tests for use cases and domain logic
error-handling skillException hierarchy, business vs system exceptions
spring-framework skillSpring DI wiring, @Transactional, JPA repository patterns

Additional Resources

  • Alistair Cockburn, "Hexagonal Architecture" (original article, 2005)
  • Robert C. Martin, "Clean Architecture" concepts and dependency rule
  • Vaughn Vernon, "Implementing Domain-Driven Design" (architecture patterns chapter)
  • Netflix Tech Blog, "Ready for changes with Hexagonal Architecture"
  • Herberto Graca, "DDD, Hexagonal, Onion, Clean, CQRS, How I put it all together" (blog series)
  • Tom Hombergs, "Get Your Hands Dirty on Clean Architecture"

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.