Introduction to Structus
Welcome to Structus - a pure Kotlin JVM library providing the foundational building blocks for implementing Explicit Architecture.
What is Structus?
Structus is a shared kernel for large-scale projects that synthesizes:
- 🏛️ Domain-Driven Design (DDD)
- 📝 Command/Query Separation (CQS)
- 📡 Event-Driven Architecture (EDA)
It defines interfaces and base classes for all core business concepts and architectural patterns while remaining completely framework-agnostic.
Key Features
- 🚀 Pure Kotlin: No framework dependencies (Spring, Ktor, Micronaut, etc.)
- 🔄 Coroutine-Ready: All I/O operations use suspend functions
- 📦 Minimal Dependencies: Only Kotlin stdlib + kotlinx-coroutines-core
- 📚 Comprehensive Documentation: Every component includes KDoc and examples
- 🏗️ Framework-Agnostic: Works with any framework or pure Kotlin
- 🎨 Clean Architecture: Enforces proper layer separation and dependencies
Why Explicit Architecture?
Explicit Architecture helps you:
- Separate Concerns: Clear boundaries between domain, application, and infrastructure
- Testability: Easy to test business logic in isolation
- Flexibility: Switch frameworks or databases without rewriting business logic
- Maintainability: Code is organized and predictable
- Scalability: Architecture scales with your team and codebase
Architecture Layers
┌─────────────────────────────────────────┐
│ Presentation Layer │
│ (Controllers, DTOs, REST APIs) │
└─────────────────────────────────────────┘
↓ depends on
┌─────────────────────────────────────────┐
│ Application Layer │
│ (Commands, Queries, Handlers, Events) │
└─────────────────────────────────────────┘
↓ depends on
┌─────────────────────────────────────────┐
│ Domain Layer │
│ (Entities, Aggregates, Value Objects) │
└─────────────────────────────────────────┘
↑ implemented by
┌─────────────────────────────────────────┐
│ Infrastructure Layer │
│ (Database, External APIs, Messaging) │
└─────────────────────────────────────────┘
Quick Example
Here's a taste of what Structus code looks like:
// Domain Layer - Pure business logic
class User(
override val id: UserId,
var email: Email,
var name: String
) : AggregateRoot<UserId>() {
fun activate() {
status = UserStatus.ACTIVE
recordEvent(UserActivatedEvent(id.value))
}
}
// Application Layer - Use case
class RegisterUserCommandHandler(
private val userRepository: UserRepository,
private val outboxRepository: MessageOutboxRepository
) : CommandHandler<RegisterUserCommand, Result<UserId>> {
override suspend operator fun invoke(command: RegisterUserCommand): Result<UserId> {
return runCatching {
val user = User.create(Email(command.email), command.name)
userRepository.save(user)
// Transactional Outbox Pattern
user.domainEvents.forEach { outboxRepository.save(it) }
user.clearEvents()
user.id
}
}
}
Next Steps
Ready to get started? Here's what to do next:
- About Structus - Learn about Structus and its creator
- Installation Guide - Set up Structus in your project
- Quick Start Tutorial - Build your first app in 15 minutes
- Core Concepts - Understand the fundamental concepts
- Architecture Overview - Deep dive into the architecture
- Roadmap - Explore upcoming Structus ecosystem projects
Community & Support
Made with ❤️ for the Kotlin community