7 evolutionary tasks implemented: 1. PHP web development: php-developer agent + 6 skills (Laravel, Symfony, WordPress, security, testing, modular architecture) + 2 pipeline commands (/laravel, /wordpress) 2. Atomic task decomposition: 1 action = 1 task rule, task sizing guide, decomposition protocol for orchestrator, token budgets per complexity 3. Modular code rules: max 100 lines/file, max 30 lines/function, service/repository patterns, cross-module communication via events only 4. Gitea-centric workflow: mandatory issue creation before work, research with links, progress checkboxes, screenshots on test, git history as knowledge base 5. Fix: target project auto-detection — removed all hardcoded UniqueSoft/APAW from API calls, added get_target_repo() via git remote, GITEA_TARGET_REPO env override 6. Agent execution monitoring: agent-executions.jsonl logging, agent-stats.ts statistics script, required fields per invocation, Gitea comment includes duration/tokens 7. Token optimization: 1 action = 1 task principle, token budgets by task type, routing matrix, no scope creep, skip unnecessary pipeline steps
200 lines
5.4 KiB
Markdown
200 lines
5.4 KiB
Markdown
# Modular Code Rules
|
|
|
|
CRITICAL: Never write giant monolithic files. Split code into modules, libraries, and microservice-ready components.
|
|
|
|
## Problem
|
|
|
|
Agents write enormous single files that are hard to review, test, debug, and maintain. No clear boundaries between features.
|
|
|
|
## Core Principles
|
|
|
|
1. **Maximum file size**: 100 lines per file (excluding tests and migrations)
|
|
2. **Maximum function/method size**: 30 lines
|
|
3. **Maximum class size**: 5 public methods
|
|
4. **One responsibility per file**: A file does ONE thing
|
|
|
|
## Module Structure (Mandatory)
|
|
|
|
Every feature must be organized as an independent module:
|
|
|
|
```
|
|
{feature}/
|
|
├── Controllers/ # HTTP request handling (thin)
|
|
├── Services/ # Business logic (fat)
|
|
├── Repositories/ # Data access (abstracted)
|
|
├── Models/ # Data definitions
|
|
├── Routes/ # Route definitions
|
|
├── Events/ # Events this module emits
|
|
├── Listeners/ # Events this module handles
|
|
├── Jobs/ # Async work this module performs
|
|
├── Requests/ # Input validation (not in controller)
|
|
├── Resources/ # Output transformation (not raw model)
|
|
├── Exceptions/ # Module-specific exceptions
|
|
├── Tests/ # Module-specific tests
|
|
└── ModuleServiceProvider.php # Module registration
|
|
```
|
|
|
|
## Service Layer Rules
|
|
|
|
```php
|
|
// ❌ BAD: Business logic in controller
|
|
class ProductController
|
|
{
|
|
public function store(Request $request)
|
|
{
|
|
$product = Product::create($request->all());
|
|
Cache::forget('products');
|
|
event(new ProductCreated($product));
|
|
Mail::to($product->vendor)->send(new NewProduct($product));
|
|
return response()->json($product);
|
|
}
|
|
}
|
|
|
|
// ✅ GOOD: Business logic in service
|
|
class ProductController
|
|
{
|
|
public function __construct(private ProductService $service) {}
|
|
|
|
public function store(ProductStoreRequest $request): JsonResponse
|
|
{
|
|
$product = $this->service->create($request->validated());
|
|
return response()->json(new ProductResource($product), 201);
|
|
}
|
|
}
|
|
|
|
class ProductService
|
|
{
|
|
public function create(array $data): Product
|
|
{
|
|
$product = $this->repository->create($data);
|
|
$this->clearCache();
|
|
ProductCreated::dispatch($product);
|
|
$this->notifyVendor($product);
|
|
return $product;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Repository Pattern (Mandatory for Data Access)
|
|
|
|
```php
|
|
// ❌ BAD: Query in controller or service
|
|
$products = Product::where('active', true)->paginate(20);
|
|
|
|
// ✅ GOOD: Query in repository
|
|
interface ProductRepositoryInterface
|
|
{
|
|
public function listActive(int $perPage = 20): LengthAwarePaginator;
|
|
}
|
|
|
|
class ProductRepository implements ProductRepositoryInterface
|
|
{
|
|
public function __construct(private Product $model) {}
|
|
|
|
public function listActive(int $perPage = 20): LengthAwarePaginator
|
|
{
|
|
return $this->model->query()
|
|
->where('is_active', true)
|
|
->orderBy('created_at', 'desc')
|
|
->paginate($perPage);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Cross-Module Communication
|
|
|
|
Modules MUST NOT import models or repositories from other modules.
|
|
|
|
```
|
|
❌ Product module imports Order model directly
|
|
❌ Order module calls ProductRepository directly
|
|
|
|
✅ Product module dispatches ProductCreated event
|
|
✅ Order module listens to ProductCreated event
|
|
✅ Module boundaries enforced via interfaces
|
|
```
|
|
|
|
## Microservice Readiness
|
|
|
|
Every module must be extractable as an independent service:
|
|
|
|
1. **Own database migrations**: Module manages its own tables
|
|
2. **Own routes**: Module registers its own routes
|
|
3. **Own config**: Module has its own configuration
|
|
4. **Own tests**: Module tests run independently
|
|
5. **Interface contracts**: Module exposes interfaces, not implementations
|
|
|
|
## File Splitting Rules
|
|
|
|
When a file exceeds 100 lines:
|
|
|
|
```
|
|
Original: ProductController.php (250 lines)
|
|
↓ Split into:
|
|
ProductController.php # index, show (thin delegates)
|
|
ProductStoreController.php # store endpoint (thin delegates)
|
|
ProductUpdateController.php # update endpoint (thin delegates)
|
|
ProductService.php # business logic (called by all)
|
|
```
|
|
|
|
When a service exceeds 5 methods:
|
|
|
|
```
|
|
Original: ProductService.php (8 methods)
|
|
↓ Split into:
|
|
ProductCrudService.php # create, update, delete
|
|
ProductSearchService.php # list, search, filter
|
|
ProductPricingService.php # calculatePrice, applyDiscount
|
|
```
|
|
|
|
## Language-Specific Module Patterns
|
|
|
|
### Node.js
|
|
```
|
|
src/modules/product/
|
|
├── routes.js
|
|
├── controller.js
|
|
├── service.js
|
|
├── repository.js
|
|
├── model.js
|
|
├── validators.js
|
|
└── __tests__/
|
|
```
|
|
|
|
### Go
|
|
```
|
|
internal/product/
|
|
├── handler.go
|
|
├── service.go
|
|
├── repository.go
|
|
├── model.go
|
|
└── handler_test.go
|
|
```
|
|
|
|
### Flutter/Dart
|
|
```
|
|
lib/features/product/
|
|
├── data/
|
|
│ ├── repositories/
|
|
│ └── models/
|
|
├── domain/
|
|
│ ├── entities/
|
|
│ └── usecases/
|
|
└── presentation/
|
|
├── pages/
|
|
├── widgets/
|
|
└── providers/
|
|
```
|
|
|
|
## Checklist
|
|
|
|
- [ ] Every file under 100 lines
|
|
- [ ] Every function under 30 lines
|
|
- [ ] Every class under 5 public methods
|
|
- [ ] Features organized as modules
|
|
- [ ] Service layer contains business logic
|
|
- [ ] Repository layer abstracts data access
|
|
- [ ] Controllers are thin (5-10 lines per method)
|
|
- [ ] Cross-module communication via events
|
|
- [ ] Each module testable independently
|
|
- [ ] Each module extractable to microservice |