ADR-0002: Project Structure and Development Tools¶
Status¶
ACCEPTED
Date: 2025-07-05
Changelog¶
| Date | Revision | Description | Author |
|---|---|---|---|
| 2025-07-05 | 1.0 | Initial version | souperk |
| 2025-07-19 | 1.1 | Added subdomain service organization | AI Assistant |
Context¶
As we begin development, we need to establish a clear and consistent project structure that:
- Promotes code organization and maintainability
- Supports modularity and separation of concerns
- Provides consistent development workflows
- Ensures code quality through automated checks
- Facilitates local development and testing
Currently, we need to define:
- How code should be organized
- What development tools to use
- How to ensure code quality
- How to support local development
Decision¶
Project Structure¶
We will organize the project with the following directory structure:
server/
├── libs/ # Reusable library packages
├── services/ # Service implementations
└── tools/ # Development and operational tooling
Each directory serves a specific purpose:
server/libs/: Contains shared library code that can be reused across servicesserver/services/: Contains individual service implementations, each potentially with its own deploymentserver/tools/: Contains utility packages and tools for development, deployment, and operations
Package Structure¶
Each package will maintain a consistent structure with the following key files:
package/
├── Makefile # Build, test, and development commands
├── src/ # Package source code
│ └── loryth/ # Loryth namespace package
│ └── package/ # Package module
│ ├── api/ # (service) API module
│ ├── worker/ # (service) Worker module
│ ├── domain/ # (service) Domain module
│ │ └── sub_domain/ # Subdomain modules and implementations
│ ├── config/ # (service) Config module
│ ├── persistence/ # (service) Persistence module
│ └── __init__.py # Module
├── tests/ # Package test suite
├── pyproject.toml # Python package configuration and dependencies
└── docker-compose.yml # Local development environment (for services)
Domain Structure¶
The domain module will be organized with subdomains, where each subdomain contains its own services and domain models:
- All services should be implemented within their respective subdomain folder:
loryth.package.domain.sub_domain - This maintains clear separation of concerns and makes it easier to identify which subdomain owns each service
- It provides consistent organization that scales as the application grows
- Domain models related to a specific subdomain should also be placed within the subdomain folder
Development Tools¶
We will use the following tools for development and quality assurance:
-
Type Checking:
mypy- Strict type checking enabled
- Required for all Python code
- Configuration in
pyproject.toml
-
Code Linting:
ruff- Modern, fast Python linter
- Enforces code style and catches common errors
- Configuration in
pyproject.toml
-
Testing:
pytest- All code must have unit tests
- Integration tests for services
- Configuration in
pyproject.toml
-
Dependency Management:
uv- Fast, reliable Python package management
- Handles local development dependencies
- Supports editable local package installations
- Configuration in
pyproject.tomlunder[tool.uv.sources]
Build and Development¶
Makefilewill provide standard targets:make build: Build the packagemake test: Run testsmake lint: Run lintingmake typecheck: Run type checkingmake check: Run all checks (lint, typecheck, test)make clean: Clean build artifacts
Consequences¶
Positive¶
- Clear organization of code by responsibility
- Consistent development experience across packages
- Easier to find and understand code organization
- Automated quality checks ensure code standards
- Local development environment matches production
- Standardized build and test processes
- Reusable code properly separated in libs
Negative¶
- Additional setup time for new packages
- Learning curve for developers new to the tools
- Need to maintain consistency across multiple packages
- Docker overhead for local development
Neutral¶
- Regular updates needed for development tools
- May need to adjust structure as project grows
- Teams need to agree on when to create new services vs libraries
Alternatives Considered¶
-
Monolithic Repository Structure
- Description: Single flat directory structure
- Pros:
- Simpler initial setup
- Easier dependency management
- Cons:
- Harder to scale
- Less clear separation of concerns
- Not chosen because we need better separation for maintainability
-
Black for Code Formatting
- Description: Using Black instead of ruff for formatting
- Pros:
- More established tool
- Zero configuration
- Cons:
- Slower than ruff
- Less comprehensive (formatting only)
- Not chosen because ruff provides more features and better performance
-
Poetry for Package Management
- Description: Using Poetry instead of standard setuptools
- Pros:
- Better dependency resolution
- Modern tooling
- Cons:
- Additional tool to learn
- Not as widely adopted
- Not chosen to keep tooling minimal and standard
-
Virtualenv for Dependency Management
- Description: Using virtualenv directly instead of uv
- Pros:
- Established, standard tool
- Well-known workflow
- Cons:
- Slower than uv
- Less robust dependency resolution
- More complex editable package handling
-
Not chosen because uv provides better performance and reliability
-
Alternative Service Organization Approaches
- Description: Placing services directly at the domain level (
loryth.package.domain) or using a mixed approach - Pros:
- Flatter hierarchy in the domain level approach
- More flexibility in the mixed approach
- Cons:
- Less clear ownership boundaries
- Harder to maintain consistency
- Potential service location confusion
- Not chosen because placing services in their respective subdomains provides clearer ownership boundaries and better separation of concerns