Token导航 LogoToken导航TokenDH.com
研究检索external-servicegithub未标认证来源可访问许可证需确认审计通过

clean-architecture干净的架构

Agent Skill

clean-architecture 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

17,430

周安装

712

GitHub Stars

229

下载量

5,639
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:clean-architecture(干净的架构)
来源仓库:https://github.com/giuseppe-trisciuoglio/developer-kit
仓库路径:skills/clean-architecture
安装命令:
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill clean-architecture
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill clean-architecture

简介

用于查找、检索和筛选相关信息。

  • 适合在关键词或任务场景下快速定位候选结果。
  • 可结合来源仓库和原始 README 核验具体用法。
  • 安装命令:npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill clean-architecture。
  • 建议确认权限范围和维护状态后再使用。

SKILL.md

Clean Architecture, Hexagonal Architecture & DDD for Spring Boot

Overview

This skill provides comprehensive guidance for implementing Clean Architecture, Hexagonal Architecture (Ports & Adapters), and Domain-Driven Design tactical patterns in Java 21+ Spring Boot 3.5+ applications. It ensures clear separation of concerns, framework-independent domain logic, and highly testable codebases through proper layering and dependency management.

When to Use

  • Architecting new Spring Boot applications with clear separation of concerns
  • Refactoring tightly coupled code into testable, layered architectures
  • Implementing domain logic independent of frameworks and infrastructure
  • Designing ports and adapters for swappable implementations
  • Applying Domain-Driven Design tactical patterns (entities, value objects, aggregates)
  • Creating testable business logic without Spring context dependencies

Instructions

1. Understand the Core Concepts

Clean Architecture Layers (Dependency Rule)

Dependencies flow inward. Inner layers know nothing about outer layers.

LayerResponsibilitySpring Boot Equivalent
DomainEntities, value objects, domain events, repository interfacesdomain/ - no Spring annotations
ApplicationUse cases, application services, DTOs, portsapplication/ - @Service, @Transactional
InfrastructureFrameworks, database, external APIsinfrastructure/ - @Repository, @Entity
AdapterControllers, presenters, external gatewaysadapter/ - @RestController

Hexagonal Architecture (Ports & Adapters)

  • Domain Core: Pure Java business logic, no framework dependencies
  • Ports: Interfaces defining contracts (driven and driving)
  • Adapters: Concrete implementations (JPA, REST, messaging)

Domain-Driven Design Tactical Patterns

  • Entities: Objects with identity and lifecycle (e.g., Order, Customer)
  • Value Objects: Immutable, defined by attributes (e.g., Money, Email)
  • Aggregates: Consistency boundary with root entity
  • Domain Events: Capture significant business occurrences
  • Repositories: Persistence abstraction, implemented in infrastructure

2. Organize Package Structure

Follow this feature-based package organization:

com.example.order/
├── domain/
│   ├── model/              # Entities, value objects
│   ├── event/              # Domain events
│   ├── repository/         # Repository interfaces (ports)
│   └── exception/          # Domain exceptions
├── application/
│   ├── port/in/            # Driving ports (use case interfaces)
│   ├── port/out/           # Driven ports (external service interfaces)
│   ├── service/            # Application services
│   └── dto/                # Request/response DTOs
├── infrastructure/
│   ├── persistence/        # JPA entities, repository adapters
│   └── external/           # External service adapters
└── adapter/
    └── rest/               # REST controllers

3. Implement the Domain Layer (Framework-Free)

The domain layer must have zero dependencies on Spring or any framework.

  • Use Java records for immutable value objects with built-in validation
  • Place business logic in entities, not services (Rich Domain Model)
  • Define repository interfaces (ports) in the domain layer
  • Use strongly-typed IDs to prevent ID confusion
  • Implement domain events for decoupling side effects
  • Use factory methods for entity creation to enforce invariants

4. Implement the Application Layer

  • Create use case interfaces (driving ports) in application/port/in/
  • Create external service interfaces (driven ports) in application/port/out/
  • Implement application services with @Service and @Transactional
  • Use DTOs for request/response, separate from domain models
  • Publish domain events after successful operations

5. Implement the Infrastructure Layer (Adapters)

  • Create JPA entities in infrastructure/persistence/
  • Implement repository adapters that map between domain and JPA entities
  • Use MapStruct or manual mappers for domain-JPA conversion
  • Configure conditional beans for swappable implementations
  • Keep infrastructure concerns isolated from domain logic

6. Implement the Adapter Layer (REST)

  • Create REST controllers in adapter/rest/
  • Inject use case interfaces, not implementations
  • Use Bean Validation on DTOs
  • Return proper HTTP status codes and responses
  • Handle exceptions with global exception handlers

7. Apply Best Practices

  1. Dependency Rule: Domain has zero dependencies on Spring or other frameworks
  2. Immutable Value Objects: Use Java records for value objects with built-in validation
  3. Rich Domain Models: Place business logic in entities, not services
  4. Repository Pattern: Domain defines interface, infrastructure implements
  5. Domain Events: Decouple side effects from primary operations
  6. Constructor Injection: Mandatory dependencies via final fields
  7. DTO Mapping: Separate domain models from API contracts
  8. Transaction Boundaries: Place @Transactional in application services
  9. Factory Methods: Use Entity.create() for invariant enforcement during construction
  10. Separate JPA Entities: Keep domain entities separate from JPA entities with mappers

8. Validate Architecture Compliance

After implementing each layer, verify the dependency rules are respected:

  • Domain Layer Check: Run grep -r "@Service\|@Component\|@Autowired" domain/ to ensure zero Spring imports
  • ArchUnit Test: Add dependency tests to verify no infrastructure imports in domain layer: noClasses().that().resideInPackage("..domain..").should().accessClassesThat().resideInAnyPackage("..spring..", "..infrastructure..");
  • Entity Exposure Check: Verify JPA entities are never returned from domain services
  • Transaction Check: Confirm @Transactional only on application layer services, never on domain

9. Write Tests

  • Domain Tests: Pure unit tests without Spring context, fast execution
  • Application Tests: Unit tests with mocked ports using Mockito
  • Infrastructure Tests: Integration tests with @DataJpaTest and Testcontainers
  • Adapter Tests: Controller tests with @WebMvcTest

Examples

Example 1: Domain Layer - Entity with Domain Events

// domain/model/Order.java
public class Order {
    private final OrderId id;
    private final List<OrderItem> items;
    private Money total;
    private OrderStatus status;
    private final List<DomainEvent> domainEvents = new ArrayList<>();

    private Order(OrderId id, List<OrderItem> items) {
        this.id = id;
        this.items = new ArrayList<>(items);
        this.status = OrderStatus.PENDING;
        calculateTotal();
    }

    public static Order create(List<OrderItem> items) {
        validateItems(items);
        Order order = new Order(OrderId.generate(), items);
        order.domainEvents.add(new OrderCreatedEvent(order.id, order.total));
        return order;
    }

    public void confirm() {
        if (status != OrderStatus.PENDING) {
            throw new DomainException("Only pending orders can be confirmed");
        }
        this.status = OrderStatus.CONFIRMED;
    }

    public List<DomainEvent> getDomainEvents() {
        return List.copyOf(domainEvents);
    }

    public void clearDomainEvents() {
        domainEvents.clear();
    }
}

Example 2: Domain Layer - Value Object with Validation

// domain/model/Money.java (Value Object)
public record Money(BigDecimal amount, Currency currency) {
    public Money {
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new DomainException("Amount cannot be negative");
        }
    }

    public static Money zero() {
        return new Money(BigDecimal.ZERO, Currency.getInstance("EUR"));
    }

    public Money add(Money other) {
        if (!this.currency.equals(other.currency)) {
            throw new DomainException("Currency mismatch");
        }
        return new Money(this.amount.add(other.amount), this.currency);
    }
}

Example 3: Domain Layer - Repository Port

// domain/repository/OrderRepository.java (Port)
public interface OrderRepository {
    Order save(Order order);
    Optional<Order> findById(OrderId id);
}

Example 4: Application Layer - Use Case and Service

// application/port/in/CreateOrderUseCase.java
public interface CreateOrderUseCase {
    OrderResponse createOrder(CreateOrderRequest request);
}

// application/dto/CreateOrderRequest.java
public record CreateOrderRequest(
    @NotNull UUID customerId,
    @NotEmpty List<OrderItemRequest> items
) {}

// application/service/OrderService.java
@Service
@RequiredArgsConstructor
@Transactional
public class OrderService implements CreateOrderUseCase {
    private final OrderRepository orderRepository;
    private final PaymentGateway paymentGateway;
    private final DomainEventPublisher eventPublisher;

    @Override
    public OrderResponse createOrder(CreateOrderRequest request) {
        List<OrderItem> items = mapItems(request.items());
        Order order = Order.create(items);

        PaymentResult payment = paymentGateway.charge(order.getTotal());
        if (!payment.successful()) {
            throw new PaymentFailedException("Payment failed");
        }

        order.confirm();
        Order saved = orderRepository.save(order);
        publishEvents(order);

        return OrderMapper.toResponse(saved);
    }

    private void publishEvents(Order order) {
        order.getDomainEvents().forEach(eventPublisher::publish);
        order.clearDomainEvents();
    }
}

Example 5: Infrastructure Layer - JPA Entity and Adapter

// infrastructure/persistence/OrderJpaEntity.java
@Entity
@Table(name = "orders")
public class OrderJpaEntity {
    @Id
    private UUID id;
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    private BigDecimal totalAmount;
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItemJpaEntity> items;
}

// infrastructure/persistence/OrderRepositoryAdapter.java
@Component
@RequiredArgsConstructor
public class OrderRepositoryAdapter implements OrderRepository {
    private final OrderJpaRepository jpaRepository;
    private final OrderJpaMapper mapper;

    @Override
    public Order save(Order order) {
        OrderJpaEntity entity = mapper.toEntity(order);
        return mapper.toDomain(jpaRepository.save(entity));
    }

    @Override
    public Optional<Order> findById(OrderId id) {
        return jpaRepository.findById(id.value()).map(mapper::toDomain);
    }
}

Example 6: Adapter Layer - REST Controller

// adapter/rest/OrderController.java
@RestController
@RequestMapping("/api/orders")
@RequiredArgsConstructor
public class OrderController {
    private final CreateOrderUseCase createOrderUseCase;

    @PostMapping
    public ResponseEntity<OrderResponse> createOrder(
            @Valid @RequestBody CreateOrderRequest request) {
        OrderResponse response = createOrderUseCase.createOrder(request);
        URI location = ServletUriComponentsBuilder
            .fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(response.id())
            .toUri();
        return ResponseEntity.created(location).body(response);
    }
}

Example 7: Domain Tests (No Spring Context)

class OrderTest {
    @Test
    void shouldCreateOrderWithValidItems() {
        List<OrderItem> items = List.of(
            new OrderItem(new ProductId(UUID.randomUUID()), 2, new Money("10.00", EUR))
        );

        Order order = Order.create(items);

        assertThat(order.getStatus()).isEqualTo(OrderStatus.PENDING);
        assertThat(order.getDomainEvents()).hasSize(1);
    }
}

Example 8: Application Tests (Unit with Mocks)

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
    @Mock OrderRepository orderRepository;
    @Mock PaymentGateway paymentGateway;
    @Mock DomainEventPublisher eventPublisher;

    @InjectMocks OrderService orderService;

    @Test
    void shouldCreateAndConfirmOrder() {
        when(paymentGateway.charge(any())).thenReturn(new PaymentResult(true, "tx-123"));
        when(orderRepository.save(any())).thenAnswer(i -> i.getArgument(0));

        OrderResponse response = orderService.createOrder(createRequest());

        assertThat(response.status()).isEqualTo(OrderStatus.CONFIRMED);
        verify(eventPublisher).publish(any(OrderCreatedEvent.class));
    }
}

Best Practices

  • Domain purity: Keep the domain layer free of Spring annotations and framework imports — zero dependencies on outer layers
  • Feature-based packages: Organize by business capability (order/, customer/) rather than technical role, with each feature containing all four layers
  • Immutable value objects: Use Java records for value objects with built-in validation in compactors — immutable by design
  • Rich domain models: Place business logic in entities and aggregates, not in application services — services orchestrate, entities encapsulate
  • Always map: Separate JPA entities from domain models using MapStruct or manual mappers; never expose JPA entities outside infrastructure
  • Domain events for decoupling: Use DomainEventPublisher to decouple cross-aggregate side effects instead of direct service calls
  • Transaction boundaries in application layer: Place @Transactional only on application services, never on domain classes
  • Factory methods for invariants: Use Entity.create(...) static methods to enforce invariants at construction time
  • Enforce with ArchUnit: Add ArchUnit tests in the test suite to verify no Spring or infrastructure imports reach the domain layer
  • Strongly-typed IDs: Use record OrderId(UUID value) instead of raw UUID to prevent ID confusion across aggregates

Constraints and Warnings

Critical Constraints

  • Domain Layer Purity: Never add Spring annotations (@Entity, @Autowired, @Component) to domain classes
  • Dependency Direction: Dependencies must only point inward (domain <- application <- infrastructure/adapter)
  • Framework Isolation: All framework-specific code must stay in infrastructure and adapter layers

Common Pitfalls to Avoid

  • Anemic Domain Model: Entities with only getters/setters, logic in services - place business logic in entities
  • Framework Leakage: @Entity, @Autowired in domain layer - keep domain framework-free
  • Lazy Loading Issues: Exposing JPA entities through domain model - use mappers to convert
  • Circular Dependencies: Between domain aggregates - use IDs instead of direct references
  • Missing Domain Events: Direct service calls instead of events for cross-aggregate communication
  • Repository Misplacement: Defining repository interfaces in infrastructure - they belong in domain
  • DTO Bypass: Exposing domain entities directly in API - always use DTOs for external contracts

Performance Considerations

  • Separate JPA entities from domain models to avoid lazy loading issues
  • Use read-only transactions for query operations
  • Consider CQRS for complex read/write scenarios

References

  • references/java-clean-architecture.md - Java-specific patterns (records, sealed classes, strongly-typed IDs)
  • references/spring-boot-implementation.md - Spring Boot integration (DI patterns, JPA mapping, transaction management)

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.97%
按下载量换算2,085

Claude

29.73%
按下载量换算1,676

Cursor

18.34%
按下载量换算1,034

Gemini CLI

9.06%
按下载量换算511

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

external-service

该 Skill 可能调用第三方服务、云服务或外部模型 API,使用前需要确认账号、额度、数据发送范围和服务条款。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills