Architecture Design
Table of Contents
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
- Appendix
Introduction
This document is designed for architects and senior developers, systematically explaining how the Sparrow framework implements "Clean Architecture" at the code level. By clarifying the responsibility boundaries and interaction relationships between the application layer, adapter layer, domain layer, and infrastructure layer, it explains the dependency inversion principle, layered design, and modular implementation, providing technical considerations, trade-offs, and extensibility design recommendations for architectural decisions. The document includes multiple architecture and class diagrams to help readers quickly grasp the system overview.
Project Structure
Sparrow adopts a directory organization layered by "concerns", combined with Go modular features, forming clear layered boundaries:
- Domain Layer (entity): Carries business entities and aggregate roots, defines business invariants and behavioral contracts
- Use Case Layer (usecase): Encapsulates business use cases and process orchestration, defines repository interfaces and generic query models
- Adapter Layer (adapter): HTTP routing and handlers, middleware, projections/Saga and other external adapters
- Infrastructure Layer (bootstrap, config, persistence, messaging, tasks, etc.): Provides runtime environment, configuration, persistence, message bus, task scheduling and other support capabilities
Diagram Sources
- pkg/entity/base_entity.go
- pkg/entity/agg_root.go
- pkg/entity/task.go
- pkg/usecase/repo.go
- pkg/usecase/base_repo.go
- pkg/usecase/session.go
- pkg/bootstrap/app.go
- pkg/bootstrap/container.go
- pkg/config/config.go
- pkg/persistence/repo/sqldb.go
- pkg/messaging/bus.go
- pkg/tasks/core.go
Core Components
Application Entry and Container
- App: Global application object, responsible for configuration loading, logging initialization, HTTP server startup, subprocess lifecycle management, event bus/message bus integration, task scheduler integration
- Container: Lightweight IoC container, supports anonymous and named dependency registration and resolution, implements dependency injection and singleton caching
Domain Model
- BaseEntity: Unified entity base class, provides standard fields and timestamps
- AggregateRoot: Aggregate root interface, defines core contracts such as event sourcing, version control, business validation
- Task: Task entity, embodies domain layer business objects
Use Cases and Repositories
- Repository[T]: Use case layer's abstract interface for persistence
- BaseRepository[T]: Repository generic implementation skeleton, provides default errors and query option tools
- SessionService: Session management use case, encapsulates business rules and repository interaction
Infrastructure
- Config: Centralized configuration structure, covers server, logging, database, cache, message middleware, etc.
- SqlDBRepository[T]: Generic repository implementation based on database/sql, supports soft delete, transactions, conditional queries, pagination, random sampling, etc.
- StreamHub: Event stream bus based on NATS JetStream, supports subscription, graceful shutdown and startup
- TaskScheduler: Task scheduler interface, abstracts task scheduling, cancellation, status query and lifecycle management
Architecture Overview
Sparrow's clean architecture is centered on "dependency inversion": upper layers (application layer, adapter layer) only depend on abstractions (interfaces), lower layers (infrastructure layer) implement these abstractions; domain layer is independent of technical details, only exposes interfaces for use case layer consumption. The diagram below shows key components and dependency directions:
Diagram Sources
- pkg/adapter/http/router/tasks.go
- pkg/usecase/session.go
- pkg/usecase/repo.go
- pkg/usecase/base_repo.go
- pkg/entity/base_entity.go
- pkg/entity/agg_root.go
- pkg/entity/task.go
- pkg/bootstrap/app.go
- pkg/bootstrap/container.go
- pkg/config/config.go
- pkg/persistence/repo/sqldb.go
- pkg/messaging/bus.go
- pkg/tasks/core.go
Detailed Component Analysis
Dependency Injection and Container (IoC)
Design Points:
- Supports anonymous and named provider registration, prioritizes named matches during resolution, otherwise falls back to anonymous
- Constructor parameters resolve dependencies by type, automatically caches first resolution result (singleton)
- Provides convenient resolution by name and instance injection methods
Collaboration with Application Layer:
- App registers and resolves global services through Container (such as NATS connection, event publisher, task service, etc.)
- Use case layer obtains repositories, session services and other dependencies through App's resolution methods
Diagram Sources
Domain Layer: Entity and Aggregate Root
- BaseEntity: Unified entity identifier and timestamp fields, provides consistent lifecycle management for all entities
- AggregateRoot: Defines interfaces that aggregate roots must implement, including version control, event sourcing (command handling, event application, uncommitted event management), rebuilding state from event stream/snapshot, business validation, etc.
- Task: Task entity, encapsulates task state machine and retry logic, embodies domain layer business invariants
Diagram Sources
Use Case Layer: Repository and Service
- Repository[T]: Defines unified abstraction for use case layer persistence, covers CRUD, batch operations, pagination, conditional queries, random sampling, etc.
- BaseRepository[T]: Provides default implementation skeleton, unified error wrapping, query option building, field validation, etc., concrete database implementations only need to focus on SQL construction and scanning
- SessionService: Session management use case, combines repository interface, encapsulates business rules (expiration check, auto-renewal, data read/write)
Diagram Sources
Infrastructure Layer: Configuration, Persistence, and Messaging
- Config: Centralized configuration structure, provides default values and configuration items for each subsystem (server, logging, database, cache, message middleware, permissions, etc.)
- SqlDBRepository[T]: Generic repository implementation based on database/sql, supports soft delete, transactions, conditional/sorting/pagination, random sampling, batch operations, etc.
- StreamHub: Event stream bus based on NATS JetStream, encapsulates subscription, startup/shutdown, event handler registration, etc.
- App: Integrates configuration, container, logging, HTTP server, message bus, task scheduler, provides unified startup/shutdown process and retry mechanism
Diagram Sources
- pkg/bootstrap/app.go
- pkg/bootstrap/container.go
- pkg/persistence/repo/sqldb.go
- pkg/usecase/session.go
Task Scheduling
- TaskScheduler: Abstract task scheduler interface, supports scheduling, cancellation, status query, concurrent limit setting, startup/shutdown/graceful shutdown
- App: Provides task scheduler integration point, convenient for registering and managing task executors during application startup phase
Diagram Sources
Dependency Analysis
Dependency Direction
- Upper layers (adapters, use cases) only depend on abstractions (interfaces)
- Lower layers (infrastructure) implement abstractions (concrete repositories, message buses, task schedulers)
- Domain layer does not depend on any technical details, only exposes interfaces for use case layer
Coupling and Cohesion
- Through interface segregation and dependency injection, reduces coupling between modules
- Use case layer and repository interface separation, convenient for replacing different storage implementations
Circular Dependencies
- Through interfaces and container decoupling, avoids direct circular references
External Dependencies
- Through go.mod clearly defines third-party library scope, infrastructure layer adapts around these libraries
Diagram Sources
Performance Considerations
Repository Layer
- Transactions and Batch Operations: SqlDBRepository uses transactions for batch save/delete operations, reduces round-trip overhead
- Conditional Queries and Pagination: Supports multi-condition, sorting, pagination, avoids loading all data at once
- Soft Delete: Implements soft delete through deleted_at field, balances auditing and performance
Task Scheduling
- Concurrent and Sequential: Two scheduler types, can choose execution mode based on task characteristics
- Supports Maximum Concurrency Limit: Prevents resource contention
Logging and Configuration
- Centralized Configuration and Pluggable Logging: Convenient for adjusting performance-related parameters in production environment
Troubleshooting Guide
Startup and Retry
- App provides subprocess exponential backoff retry mechanism, maximum retry count and wait limit are controllable
- Graceful Shutdown: Unified shutdown process and timeout control, ensures resource release
Repository Errors
- BaseRepository uniformly wraps common errors like empty ID, empty fields, convenient for problem location
- SqlDBRepository classifies and handles query exceptions (such as not found, transaction rollback, etc.)
Session Service
- Expiration check and auto-cleanup, avoids dirty data affecting business
Message Bus
- StreamHub supports subscriber startup/shutdown, convenient for enabling/disabling event handling during debugging
Conclusion
Sparrow decouples business logic from technical implementation through clean architecture and dependency inversion, forming a high-cohesion, low-coupling layered system. Use case layer abstracts repositories through interfaces, domain layer focuses on business invariants, infrastructure layer provides replaceable implementations, adapter layer handles external interactions. Combined with IoC container, centralized configuration and task/messaging infrastructure, the system has good extensibility and maintainability. It is recommended to follow the principle of "upper layers depend on abstractions, lower layers implement abstractions" when extending new features, continuously maintaining architectural clarity.
Appendix
Key Process Diagram (Startup and Event Subscription)
Diagram Sources