architecture-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Architecture Patterns

架构模式

Master proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to build maintainable, testable, and scalable systems.
掌握经过验证的后端架构模式,包括Clean Architecture、Hexagonal Architecture和Domain-Driven Design,以构建可维护、可测试且可扩展的系统。

When to Use This Skill

何时使用此技能

  • Designing new backend systems from scratch
  • Refactoring monolithic applications for better maintainability
  • Establishing architecture standards for your team
  • Migrating from tightly coupled to loosely coupled architectures
  • Implementing domain-driven design principles
  • Creating testable and mockable codebases
  • Planning microservices decomposition
  • 从零开始设计新的后端系统
  • 重构单体应用以提升可维护性
  • 为团队建立架构标准
  • 从紧耦合架构迁移到松耦合架构
  • 实施领域驱动设计原则
  • 创建可测试、可模拟的代码库
  • 规划微服务拆分

Core Concepts

核心概念

1. Clean Architecture (Uncle Bob)

1. Clean Architecture(鲍勃大叔提出)

Layers (dependency flows inward):
  • Entities: Core business models
  • Use Cases: Application business rules
  • Interface Adapters: Controllers, presenters, gateways
  • Frameworks & Drivers: UI, database, external services
Key Principles:
  • Dependencies point inward
  • Inner layers know nothing about outer layers
  • Business logic independent of frameworks
  • Testable without UI, database, or external services
层级(依赖向内流动):
  • Entities:核心业务模型
  • Use Cases:应用业务规则
  • Interface Adapters:控制器、呈现器、网关
  • Frameworks & Drivers:UI、数据库、外部服务
核心原则:
  • 依赖指向内部
  • 内层对外层一无所知
  • 业务逻辑独立于框架
  • 无需UI、数据库或外部服务即可测试

2. Hexagonal Architecture (Ports and Adapters)

2. Hexagonal Architecture(端口与适配器)

Components:
  • Domain Core: Business logic
  • Ports: Interfaces defining interactions
  • Adapters: Implementations of ports (database, REST, message queue)
Benefits:
  • Swap implementations easily (mock for testing)
  • Technology-agnostic core
  • Clear separation of concerns
组件:
  • Domain Core:业务逻辑
  • Ports:定义交互的接口
  • Adapters:端口的实现(数据库、REST、消息队列)
优势:
  • 轻松替换实现(测试时使用模拟对象)
  • 核心逻辑与技术无关
  • 关注点清晰分离

3. Domain-Driven Design (DDD)

3. Domain-Driven Design(领域驱动设计)

Strategic Patterns:
  • Bounded Contexts: Separate models for different domains
  • Context Mapping: How contexts relate
  • Ubiquitous Language: Shared terminology
Tactical Patterns:
  • Entities: Objects with identity
  • Value Objects: Immutable objects defined by attributes
  • Aggregates: Consistency boundaries
  • Repositories: Data access abstraction
  • Domain Events: Things that happened
战略模式:
  • Bounded Contexts:不同领域的独立模型
  • Context Mapping:上下文之间的关联方式
  • Ubiquitous Language:共享术语体系
战术模式:
  • Entities:具有唯一标识的对象
  • Value Objects:由属性定义的不可变对象
  • Aggregates:一致性边界
  • Repositories:数据访问抽象
  • Domain Events:已发生的业务事件

Clean Architecture Pattern

Clean Architecture 模式

Directory Structure

目录结构

app/
├── domain/           # Entities & business rules
│   ├── entities/
│   │   ├── user.py
│   │   └── order.py
│   ├── value_objects/
│   │   ├── email.py
│   │   └── money.py
│   └── interfaces/   # Abstract interfaces
│       ├── user_repository.py
│       └── payment_gateway.py
├── use_cases/        # Application business rules
│   ├── create_user.py
│   ├── process_order.py
│   └── send_notification.py
├── adapters/         # Interface implementations
│   ├── repositories/
│   │   ├── postgres_user_repository.py
│   │   └── redis_cache_repository.py
│   ├── controllers/
│   │   └── user_controller.py
│   └── gateways/
│       ├── stripe_payment_gateway.py
│       └── sendgrid_email_gateway.py
└── infrastructure/   # Framework & external concerns
    ├── database.py
    ├── config.py
    └── logging.py
app/
├── domain/           # Entities & business rules
│   ├── entities/
│   │   ├── user.py
│   │   └── order.py
│   ├── value_objects/
│   │   ├── email.py
│   │   └── money.py
│   └── interfaces/   # Abstract interfaces
│       ├── user_repository.py
│       └── payment_gateway.py
├── use_cases/        # Application business rules
│   ├── create_user.py
│   ├── process_order.py
│   └── send_notification.py
├── adapters/         # Interface implementations
│   ├── repositories/
│   │   ├── postgres_user_repository.py
│   │   └── redis_cache_repository.py
│   ├── controllers/
│   │   └── user_controller.py
│   └── gateways/
│       ├── stripe_payment_gateway.py
│       └── sendgrid_email_gateway.py
└── infrastructure/   # Framework & external concerns
    ├── database.py
    ├── config.py
    └── logging.py

Implementation Example

实现示例

python
undefined
python
undefined

domain/entities/user.py

domain/entities/user.py

from dataclasses import dataclass from datetime import datetime from typing import Optional
@dataclass class User: """Core user entity - no framework dependencies.""" id: str email: str name: str created_at: datetime is_active: bool = True
def deactivate(self):
    """Business rule: deactivating user."""
    self.is_active = False

def can_place_order(self) -> bool:
    """Business rule: active users can order."""
    return self.is_active
from dataclasses import dataclass from datetime import datetime from typing import Optional
@dataclass class User: """Core user entity - no framework dependencies.""" id: str email: str name: str created_at: datetime is_active: bool = True
def deactivate(self):
    """Business rule: deactivating user."""
    self.is_active = False

def can_place_order(self) -> bool:
    """Business rule: active users can order."""
    return self.is_active

domain/interfaces/user_repository.py

domain/interfaces/user_repository.py

from abc import ABC, abstractmethod from typing import Optional, List from domain.entities.user import User
class IUserRepository(ABC): """Port: defines contract, no implementation."""
@abstractmethod
async def find_by_id(self, user_id: str) -> Optional[User]:
    pass

@abstractmethod
async def find_by_email(self, email: str) -> Optional[User]:
    pass

@abstractmethod
async def save(self, user: User) -> User:
    pass

@abstractmethod
async def delete(self, user_id: str) -> bool:
    pass
from abc import ABC, abstractmethod from typing import Optional, List from domain.entities.user import User
class IUserRepository(ABC): """Port: defines contract, no implementation."""
@abstractmethod
async def find_by_id(self, user_id: str) -> Optional[User]:
    pass

@abstractmethod
async def find_by_email(self, email: str) -> Optional[User]:
    pass

@abstractmethod
async def save(self, user: User) -> User:
    pass

@abstractmethod
async def delete(self, user_id: str) -> bool:
    pass

use_cases/create_user.py

use_cases/create_user.py

from domain.entities.user import User from domain.interfaces.user_repository import IUserRepository from dataclasses import dataclass from datetime import datetime import uuid
@dataclass class CreateUserRequest: email: str name: str
@dataclass class CreateUserResponse: user: User success: bool error: Optional[str] = None
class CreateUserUseCase: """Use case: orchestrates business logic."""
def __init__(self, user_repository: IUserRepository):
    self.user_repository = user_repository

async def execute(self, request: CreateUserRequest) -> CreateUserResponse:
    # Business validation
    existing = await self.user_repository.find_by_email(request.email)
    if existing:
        return CreateUserResponse(
            user=None,
            success=False,
            error="Email already exists"
        )

    # Create entity
    user = User(
        id=str(uuid.uuid4()),
        email=request.email,
        name=request.name,
        created_at=datetime.now(),
        is_active=True
    )

    # Persist
    saved_user = await self.user_repository.save(user)

    return CreateUserResponse(
        user=saved_user,
        success=True
    )
from domain.entities.user import User from domain.interfaces.user_repository import IUserRepository from dataclasses import dataclass from datetime import datetime import uuid
@dataclass class CreateUserRequest: email: str name: str
@dataclass class CreateUserResponse: user: User success: bool error: Optional[str] = None
class CreateUserUseCase: """Use case: orchestrates business logic."""
def __init__(self, user_repository: IUserRepository):
    self.user_repository = user_repository

async def execute(self, request: CreateUserRequest) -> CreateUserResponse:
    # Business validation
    existing = await self.user_repository.find_by_email(request.email)
    if existing:
        return CreateUserResponse(
            user=None,
            success=False,
            error="Email already exists"
        )

    # Create entity
    user = User(
        id=str(uuid.uuid4()),
        email=request.email,
        name=request.name,
        created_at=datetime.now(),
        is_active=True
    )

    # Persist
    saved_user = await self.user_repository.save(user)

    return CreateUserResponse(
        user=saved_user,
        success=True
    )

adapters/repositories/postgres_user_repository.py

adapters/repositories/postgres_user_repository.py

from domain.interfaces.user_repository import IUserRepository from domain.entities.user import User from typing import Optional import asyncpg
class PostgresUserRepository(IUserRepository): """Adapter: PostgreSQL implementation."""
def __init__(self, pool: asyncpg.Pool):
    self.pool = pool

async def find_by_id(self, user_id: str) -> Optional[User]:
    async with self.pool.acquire() as conn:
        row = await conn.fetchrow(
            "SELECT * FROM users WHERE id = $1", user_id
        )
        return self._to_entity(row) if row else None

async def find_by_email(self, email: str) -> Optional[User]:
    async with self.pool.acquire() as conn:
        row = await conn.fetchrow(
            "SELECT * FROM users WHERE email = $1", email
        )
        return self._to_entity(row) if row else None

async def save(self, user: User) -> User:
    async with self.pool.acquire() as conn:
        await conn.execute(
            """
            INSERT INTO users (id, email, name, created_at, is_active)
            VALUES ($1, $2, $3, $4, $5)
            ON CONFLICT (id) DO UPDATE
            SET email = $2, name = $3, is_active = $5
            """,
            user.id, user.email, user.name, user.created_at, user.is_active
        )
        return user

async def delete(self, user_id: str) -> bool:
    async with self.pool.acquire() as conn:
        result = await conn.execute(
            "DELETE FROM users WHERE id = $1", user_id
        )
        return result == "DELETE 1"

def _to_entity(self, row) -> User:
    """Map database row to entity."""
    return User(
        id=row["id"],
        email=row["email"],
        name=row["name"],
        created_at=row["created_at"],
        is_active=row["is_active"]
    )
from domain.interfaces.user_repository import IUserRepository from domain.entities.user import User from typing import Optional import asyncpg
class PostgresUserRepository(IUserRepository): """Adapter: PostgreSQL implementation."""
def __init__(self, pool: asyncpg.Pool):
    self.pool = pool

async def find_by_id(self, user_id: str) -> Optional[User]:
    async with self.pool.acquire() as conn:
        row = await conn.fetchrow(
            "SELECT * FROM users WHERE id = $1", user_id
        )
        return self._to_entity(row) if row else None

async def find_by_email(self, email: str) -> Optional[User]:
    async with self.pool.acquire() as conn:
        row = await conn.fetchrow(
            "SELECT * FROM users WHERE email = $1", email
        )
        return self._to_entity(row) if row else None

async def save(self, user: User) -> User:
    async with self.pool.acquire() as conn:
        await conn.execute(
            """
            INSERT INTO users (id, email, name, created_at, is_active)
            VALUES ($1, $2, $3, $4, $5)
            ON CONFLICT (id) DO UPDATE
            SET email = $2, name = $3, is_active = $5
            """,
            user.id, user.email, user.name, user.created_at, user.is_active
        )
        return user

async def delete(self, user_id: str) -> bool:
    async with self.pool.acquire() as conn:
        result = await conn.execute(
            "DELETE FROM users WHERE id = $1", user_id
        )
        return result == "DELETE 1"

def _to_entity(self, row) -> User:
    """Map database row to entity."""
    return User(
        id=row["id"],
        email=row["email"],
        name=row["name"],
        created_at=row["created_at"],
        is_active=row["is_active"]
    )

adapters/controllers/user_controller.py

adapters/controllers/user_controller.py

from fastapi import APIRouter, Depends, HTTPException from use_cases.create_user import CreateUserUseCase, CreateUserRequest from pydantic import BaseModel
router = APIRouter()
class CreateUserDTO(BaseModel): email: str name: str
@router.post("/users") async def create_user( dto: CreateUserDTO, use_case: CreateUserUseCase = Depends(get_create_user_use_case) ): """Controller: handles HTTP concerns only.""" request = CreateUserRequest(email=dto.email, name=dto.name) response = await use_case.execute(request)
if not response.success:
    raise HTTPException(status_code=400, detail=response.error)

return {"user": response.user}
undefined
from fastapi import APIRouter, Depends, HTTPException from use_cases.create_user import CreateUserUseCase, CreateUserRequest from pydantic import BaseModel
router = APIRouter()
class CreateUserDTO(BaseModel): email: str name: str
@router.post("/users") async def create_user( dto: CreateUserDTO, use_case: CreateUserUseCase = Depends(get_create_user_use_case) ): """Controller: handles HTTP concerns only.""" request = CreateUserRequest(email=dto.email, name=dto.name) response = await use_case.execute(request)
if not response.success:
    raise HTTPException(status_code=400, detail=response.error)

return {"user": response.user}
undefined

Hexagonal Architecture Pattern

Hexagonal Architecture 模式

python
undefined
python
undefined

Core domain (hexagon center)

Core domain (hexagon center)

class OrderService: """Domain service - no infrastructure dependencies."""
def __init__(
    self,
    order_repository: OrderRepositoryPort,
    payment_gateway: PaymentGatewayPort,
    notification_service: NotificationPort
):
    self.orders = order_repository
    self.payments = payment_gateway
    self.notifications = notification_service

async def place_order(self, order: Order) -> OrderResult:
    # Business logic
    if not order.is_valid():
        return OrderResult(success=False, error="Invalid order")

    # Use ports (interfaces)
    payment = await self.payments.charge(
        amount=order.total,
        customer=order.customer_id
    )

    if not payment.success:
        return OrderResult(success=False, error="Payment failed")

    order.mark_as_paid()
    saved_order = await self.orders.save(order)

    await self.notifications.send(
        to=order.customer_email,
        subject="Order confirmed",
        body=f"Order {order.id} confirmed"
    )

    return OrderResult(success=True, order=saved_order)
class OrderService: """Domain service - no infrastructure dependencies."""
def __init__(
    self,
    order_repository: OrderRepositoryPort,
    payment_gateway: PaymentGatewayPort,
    notification_service: NotificationPort
):
    self.orders = order_repository
    self.payments = payment_gateway
    self.notifications = notification_service

async def place_order(self, order: Order) -> OrderResult:
    # Business logic
    if not order.is_valid():
        return OrderResult(success=False, error="Invalid order")

    # Use ports (interfaces)
    payment = await self.payments.charge(
        amount=order.total,
        customer=order.customer_id
    )

    if not payment.success:
        return OrderResult(success=False, error="Payment failed")

    order.mark_as_paid()
    saved_order = await self.orders.save(order)

    await self.notifications.send(
        to=order.customer_email,
        subject="Order confirmed",
        body=f"Order {order.id} confirmed"
    )

    return OrderResult(success=True, order=saved_order)

Ports (interfaces)

Ports (interfaces)

class OrderRepositoryPort(ABC): @abstractmethod async def save(self, order: Order) -> Order: pass
class PaymentGatewayPort(ABC): @abstractmethod async def charge(self, amount: Money, customer: str) -> PaymentResult: pass
class NotificationPort(ABC): @abstractmethod async def send(self, to: str, subject: str, body: str): pass
class OrderRepositoryPort(ABC): @abstractmethod async def save(self, order: Order) -> Order: pass
class PaymentGatewayPort(ABC): @abstractmethod async def charge(self, amount: Money, customer: str) -> PaymentResult: pass
class NotificationPort(ABC): @abstractmethod async def send(self, to: str, subject: str, body: str): pass

Adapters (implementations)

Adapters (implementations)

class StripePaymentAdapter(PaymentGatewayPort): """Primary adapter: connects to Stripe API."""
def __init__(self, api_key: str):
    self.stripe = stripe
    self.stripe.api_key = api_key

async def charge(self, amount: Money, customer: str) -> PaymentResult:
    try:
        charge = self.stripe.Charge.create(
            amount=amount.cents,
            currency=amount.currency,
            customer=customer
        )
        return PaymentResult(success=True, transaction_id=charge.id)
    except stripe.error.CardError as e:
        return PaymentResult(success=False, error=str(e))
class MockPaymentAdapter(PaymentGatewayPort): """Test adapter: no external dependencies."""
async def charge(self, amount: Money, customer: str) -> PaymentResult:
    return PaymentResult(success=True, transaction_id="mock-123")
undefined
class StripePaymentAdapter(PaymentGatewayPort): """Primary adapter: connects to Stripe API."""
def __init__(self, api_key: str):
    self.stripe = stripe
    self.stripe.api_key = api_key

async def charge(self, amount: Money, customer: str) -> PaymentResult:
    try:
        charge = self.stripe.Charge.create(
            amount=amount.cents,
            currency=amount.currency,
            customer=customer
        )
        return PaymentResult(success=True, transaction_id=charge.id)
    except stripe.error.CardError as e:
        return PaymentResult(success=False, error=str(e))
class MockPaymentAdapter(PaymentGatewayPort): """Test adapter: no external dependencies."""
async def charge(self, amount: Money, customer: str) -> PaymentResult:
    return PaymentResult(success=True, transaction_id="mock-123")
undefined

Domain-Driven Design Pattern

Domain-Driven Design 模式

python
undefined
python
undefined

Value Objects (immutable)

Value Objects (immutable)

from dataclasses import dataclass from typing import Optional
@dataclass(frozen=True) class Email: """Value object: validated email.""" value: str
def __post_init__(self):
    if "@" not in self.value:
        raise ValueError("Invalid email")
@dataclass(frozen=True) class Money: """Value object: amount with currency.""" amount: int # cents currency: str
def add(self, other: "Money") -> "Money":
    if self.currency != other.currency:
        raise ValueError("Currency mismatch")
    return Money(self.amount + other.amount, self.currency)
from dataclasses import dataclass from typing import Optional
@dataclass(frozen=True) class Email: """Value object: validated email.""" value: str
def __post_init__(self):
    if "@" not in self.value:
        raise ValueError("Invalid email")
@dataclass(frozen=True) class Money: """Value object: amount with currency.""" amount: int # cents currency: str
def add(self, other: "Money") -> "Money":
    if self.currency != other.currency:
        raise ValueError("Currency mismatch")
    return Money(self.amount + other.amount, self.currency)

Entities (with identity)

Entities (with identity)

class Order: """Entity: has identity, mutable state."""
def __init__(self, id: str, customer: Customer):
    self.id = id
    self.customer = customer
    self.items: List[OrderItem] = []
    self.status = OrderStatus.PENDING
    self._events: List[DomainEvent] = []

def add_item(self, product: Product, quantity: int):
    """Business logic in entity."""
    item = OrderItem(product, quantity)
    self.items.append(item)
    self._events.append(ItemAddedEvent(self.id, item))

def total(self) -> Money:
    """Calculated property."""
    return sum(item.subtotal() for item in self.items)

def submit(self):
    """State transition with business rules."""
    if not self.items:
        raise ValueError("Cannot submit empty order")
    if self.status != OrderStatus.PENDING:
        raise ValueError("Order already submitted")

    self.status = OrderStatus.SUBMITTED
    self._events.append(OrderSubmittedEvent(self.id))
class Order: """Entity: has identity, mutable state."""
def __init__(self, id: str, customer: Customer):
    self.id = id
    self.customer = customer
    self.items: List[OrderItem] = []
    self.status = OrderStatus.PENDING
    self._events: List[DomainEvent] = []

def add_item(self, product: Product, quantity: int):
    """Business logic in entity."""
    item = OrderItem(product, quantity)
    self.items.append(item)
    self._events.append(ItemAddedEvent(self.id, item))

def total(self) -> Money:
    """Calculated property."""
    return sum(item.subtotal() for item in self.items)

def submit(self):
    """State transition with business rules."""
    if not self.items:
        raise ValueError("Cannot submit empty order")
    if self.status != OrderStatus.PENDING:
        raise ValueError("Order already submitted")

    self.status = OrderStatus.SUBMITTED
    self._events.append(OrderSubmittedEvent(self.id))

Aggregates (consistency boundary)

Aggregates (consistency boundary)

class Customer: """Aggregate root: controls access to entities."""
def __init__(self, id: str, email: Email):
    self.id = id
    self.email = email
    self._addresses: List[Address] = []
    self._orders: List[str] = []  # Order IDs, not full objects

def add_address(self, address: Address):
    """Aggregate enforces invariants."""
    if len(self._addresses) >= 5:
        raise ValueError("Maximum 5 addresses allowed")
    self._addresses.append(address)

@property
def primary_address(self) -> Optional[Address]:
    return next((a for a in self._addresses if a.is_primary), None)
class Customer: """Aggregate root: controls access to entities."""
def __init__(self, id: str, email: Email):
    self.id = id
    self.email = email
    self._addresses: List[Address] = []
    self._orders: List[str] = []  # Order IDs, not full objects

def add_address(self, address: Address):
    """Aggregate enforces invariants."""
    if len(self._addresses) >= 5:
        raise ValueError("Maximum 5 addresses allowed")
    self._addresses.append(address)

@property
def primary_address(self) -> Optional[Address]:
    return next((a for a in self._addresses if a.is_primary), None)

Domain Events

Domain Events

@dataclass class OrderSubmittedEvent: order_id: str occurred_at: datetime = field(default_factory=datetime.now)
@dataclass class OrderSubmittedEvent: order_id: str occurred_at: datetime = field(default_factory=datetime.now)

Repository (aggregate persistence)

Repository (aggregate persistence)

class OrderRepository: """Repository: persist/retrieve aggregates."""
async def find_by_id(self, order_id: str) -> Optional[Order]:
    """Reconstitute aggregate from storage."""
    pass

async def save(self, order: Order):
    """Persist aggregate and publish events."""
    await self._persist(order)
    await self._publish_events(order._events)
    order._events.clear()
undefined
class OrderRepository: """Repository: persist/retrieve aggregates."""
async def find_by_id(self, order_id: str) -> Optional[Order]:
    """Reconstitute aggregate from storage."""
    pass

async def save(self, order: Order):
    """Persist aggregate and publish events."""
    await self._persist(order)
    await self._publish_events(order._events)
    order._events.clear()
undefined

Resources

资源

  • references/clean-architecture-guide.md: Detailed layer breakdown
  • references/hexagonal-architecture-guide.md: Ports and adapters patterns
  • references/ddd-tactical-patterns.md: Entities, value objects, aggregates
  • assets/clean-architecture-template/: Complete project structure
  • assets/ddd-examples/: Domain modeling examples
  • references/clean-architecture-guide.md:详细的层级分解指南
  • references/hexagonal-architecture-guide.md:端口与适配器模式指南
  • references/ddd-tactical-patterns.md:实体、值对象、聚合详解
  • assets/clean-architecture-template/:完整的项目结构模板
  • assets/ddd-examples/:领域建模示例

Best Practices

最佳实践

  1. Dependency Rule: Dependencies always point inward
  2. Interface Segregation: Small, focused interfaces
  3. Business Logic in Domain: Keep frameworks out of core
  4. Test Independence: Core testable without infrastructure
  5. Bounded Contexts: Clear domain boundaries
  6. Ubiquitous Language: Consistent terminology
  7. Thin Controllers: Delegate to use cases
  8. Rich Domain Models: Behavior with data
  1. 依赖规则:依赖始终指向内部
  2. 接口隔离:使用小而专注的接口
  3. 业务逻辑在领域层:核心逻辑与框架解耦
  4. 测试独立性:核心逻辑可脱离基础设施测试
  5. 有界上下文:清晰划分领域边界
  6. 通用语言:使用一致的术语体系
  7. 轻量控制器:将业务逻辑委托给用例
  8. 富领域模型:行为与数据结合

Common Pitfalls

常见陷阱

  • Anemic Domain: Entities with only data, no behavior
  • Framework Coupling: Business logic depends on frameworks
  • Fat Controllers: Business logic in controllers
  • Repository Leakage: Exposing ORM objects
  • Missing Abstractions: Concrete dependencies in core
  • Over-Engineering: Clean architecture for simple CRUD
  • 贫血领域模型:实体仅包含数据,无业务行为
  • 框架耦合:业务逻辑依赖于特定框架
  • 臃肿控制器:业务逻辑写在控制器中
  • 仓储泄漏:暴露ORM对象细节
  • 缺失抽象:核心层依赖具体实现
  • 过度设计:为简单CRUD应用使用整洁架构