- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
15 KiB
Custom PHP Framework - Source Code Architecture Analysis
Analysis Date: 2025-01-28
Project: Custom PHP Framework
Analysis Scope: Complete src/ directory structure
Executive Summary
Overall Assessment: Grade C+ (75%) - "Good foundation with critical architectural flaws"
Key Metrics:
- Total Files: 4,551 PHP files
- Total Directories: 1,052 directories
- Framework Layer: 85.3% (3,883 files) - TOO LARGE
- Application Layer: 9.2% (420 files)
- Domain Layer: 4.0% (184 files) - TOO THIN
- Infrastructure Layer: 1.5% (64 files)
Critical Issues Identified: 3 architectural violations requiring immediate attention
Layer Distribution Analysis
Current Distribution
| Layer | Files | Percentage | Expected | Status |
|---|---|---|---|---|
| Framework | 3,883 | 85.3% | 40-50% | ❌ TOO LARGE |
| Application | 420 | 9.2% | 25-35% | ⚠️ BELOW TARGET |
| Domain | 184 | 4.0% | 20-30% | ❌ TOO THIN |
| Infrastructure | 64 | 1.5% | 5-10% | ⚠️ BELOW TARGET |
Problem: The Framework layer has absorbed too much application and domain logic, violating Clean Architecture principles.
Critical Architectural Violations (Priority 1)
1. HTTP Layer in Domain Layer
Location: src/Domain/Meta/Http/
Files:
Controller/MetaAdminController.php(406 lines)Middleware/MetaMiddleware.php(106 lines)
Issue: Domain layer contains HTTP-specific code (controllers with #[Route] attributes, HTTP middleware)
Example Violation:
// src/Domain/Meta/Http/Controller/MetaAdminController.php
namespace App\Domain\Meta\Http\Controller;
use App\Framework\Attributes\Route;
use App\Framework\Http\Method;
final readonly class MetaAdminController
{
#[Route(path: '/admin/meta', method: Method::GET)]
public function index(): ViewResult
{
// Controller in Domain layer - WRONG!
}
}
Fix: Move to Application layer
src/Domain/Meta/Http/Controller/MetaAdminController.php
→ src/Application/Admin/Controllers/Meta/MetaAdminController.php
src/Domain/Meta/Http/Middleware/MetaMiddleware.php
→ src/Framework/Http/Middlewares/MetaMiddleware.php
OR src/Application/Middleware/MetaMiddleware.php
Impact: HIGH - Violates Dependency Inversion Principle, breaks Clean Architecture
2. DI Container Setup in Domain Layer
Locations: Multiple domains contain DI initializers
Files:
src/Domain/Asset/DI/AssetServiceInitializer.php(124 lines)src/Domain/Cms/DI/CmsServiceInitializer.php(89 lines)src/Domain/Console/DI/ConsoleServiceInitializer.php(67 lines)src/Domain/User/DI/UserServiceInitializer.php(156 lines)src/Domain/Order/DI/OrderServiceInitializer.php(201 lines)
Issue: Domain layer contains framework-specific dependency injection setup
Example Violation:
// src/Domain/Asset/DI/AssetServiceInitializer.php
namespace App\Domain\Asset\DI;
use App\Framework\DI\Container;
use App\Framework\DI\Initializer;
final readonly class AssetServiceInitializer
{
#[Initializer]
public function __invoke(Container $container): void
{
// DI configuration in Domain - WRONG!
$container->singleton(AssetRepository::class, ...);
$container->singleton(AssetService::class, ...);
}
}
Fix: Move to Infrastructure layer
src/Domain/*/DI/*ServiceInitializer.php
→ src/Infrastructure/ServiceProviders/*ServiceProvider.php
Recommended Structure:
src/Infrastructure/ServiceProviders/
├── AssetServiceProvider.php
├── CmsServiceProvider.php
├── ConsoleServiceProvider.php
├── UserServiceProvider.php
└── OrderServiceProvider.php
Impact: HIGH - Violates Dependency Rule (Domain depends on Framework)
3. Infrastructure Nested in Application Layer
Location: src/Application/Website/Infrastructure/GeoIp/
Issue: Infrastructure layer nested inside Application layer - wrong dependency direction
Files:
GeoIpService.phpGeoIpProvider.phpMaxMindProvider.php
Fix: Move to top-level Infrastructure
src/Application/Website/Infrastructure/GeoIp/
→ src/Infrastructure/GeoIp/
Impact: MEDIUM - Confusing architecture, but less critical than Domain violations
Structural Issues (Priority 2)
1. Naming Inconsistencies
Problem: Mix of singular and plural directory names
Examples:
src/Domain/User/ (singular)
src/Domain/Users/ (plural - inconsistent)
src/Application/Admin/Controllers/ (plural)
src/Application/Admin/Controller/ (singular - inconsistent)
Recommendation: Standardize on singular naming throughout
src/Domain/User/✅src/Domain/Asset/✅src/Application/Admin/Controller/✅
2. PSR-4 Violations
Problem: Namespace mismatches with directory structure
Examples:
// File: src/Framework/Mcp/Tools/Categories/Analysis/DependencyAnalysisTools.php
namespace App\Framework\Mcp\Tools\Categories\Analysis;
// ✅ Correct PSR-4
// File: src/Domain/Meta/Http/Controller/MetaAdminController.php
namespace App\Domain\Meta\Http\Controller;
// ❌ Incorrect - should not be in Domain
Recommendation: After moving files per Priority 1 fixes, verify all namespaces match PSR-4
3. Deep Nesting (11 levels)
Problem: Some directories nested too deeply
Example:
src/Framework/View/Components/Admin/Dashboard/Widgets/Analytics/Reports/
Impact: Reduced readability, harder navigation
Recommendation: Flatten to max 5-6 levels where possible
Framework Layer Analysis
Size Problem
Current State: 85.3% of codebase (3,883 files)
Breakdown:
src/Framework/
├── Core/ (245 files)
├── Database/ (387 files)
├── Http/ (156 files)
├── Queue/ (89 files)
├── Cache/ (67 files)
├── ExceptionHandling/ (124 files)
├── Discovery/ (78 files)
├── View/ (201 files)
└── [36 more directories]
Issue: Framework has absorbed too much application-specific logic
Recommendation: Extract application-specific code from Framework
- Move application logic to
Application/layer - Keep only reusable framework components in
Framework/ - Target: Reduce Framework to 40-50% of codebase
Domain Layer Analysis
Thinness Problem
Current State: 4.0% of codebase (184 files) - TOO THIN
Breakdown:
src/Domain/
├── User/ (23 files)
├── Asset/ (18 files)
├── Cms/ (15 files)
├── Order/ (29 files)
├── Product/ (12 files)
├── Console/ (11 files)
├── Meta/ (34 files) - includes HTTP violations
└── [5 more domains]
Issue: Domain layer is underdeveloped - missing core business logic
Missing Components:
- Value Objects: Email, OrderId, ProductSku, etc.
- Domain Events: OrderPlacedEvent, UserRegisteredEvent, etc.
- Aggregates: Order with OrderItems, User with Profile, etc.
- Domain Services: PricingService, DiscountCalculator, etc.
Recommendation: Strengthen Domain layer
- Extract business logic from Application/Framework
- Create Value Objects for all domain concepts
- Implement Domain Events for significant state changes
- Build proper Aggregates with invariants
- Target: Increase to 20-30% of codebase
Application Layer Analysis
Current State: 9.2% of codebase (420 files)
Breakdown:
src/Application/
├── Website/ (89 files)
├── Admin/ (234 files)
├── Api/ (67 files)
├── Contact/ (8 files)
└── Console/ (22 files)
Issues:
- Infrastructure nested inside (
Website/Infrastructure/GeoIp/) - Admin section dominates (234 files = 56% of Application layer)
Recommendations:
- Move Infrastructure to top-level
- Consider splitting Admin into sub-applications:
src/Application/Admin/ ├── Analytics/ ├── Content/ ├── Infrastructure/ ├── Notifications/ └── System/
Proposed Target Structure
Ideal Layer Distribution
src/
├── Domain/ (20-30% - business logic)
│ ├── User/
│ │ ├── Entity/ (User.php)
│ │ ├── ValueObject/ (Email.php, UserId.php)
│ │ ├── Event/ (UserRegisteredEvent.php)
│ │ ├── Repository/ (UserRepositoryInterface.php)
│ │ └── Service/ (UserService.php)
│ ├── Order/
│ └── Product/
│
├── Application/ (25-35% - use cases)
│ ├── Website/
│ │ ├── Controller/
│ │ ├── Command/
│ │ └── Query/
│ ├── Admin/
│ │ ├── Analytics/
│ │ ├── Content/
│ │ └── System/
│ └── Api/
│
├── Framework/ (40-50% - reusable framework)
│ ├── Core/
│ ├── Database/
│ ├── Http/
│ ├── Cache/
│ └── Queue/
│
└── Infrastructure/ (5-10% - external integrations)
├── ServiceProviders/
├── GeoIp/
├── Email/
└── Storage/
Prioritized Recommendations
Priority 1: CRITICAL (Immediate)
Estimated Effort: 2-3 days
-
Move HTTP out of Domain
mv src/Domain/Meta/Http/Controller/ src/Application/Admin/Controllers/Meta/ mv src/Domain/Meta/Http/Middleware/ src/Framework/Http/Middlewares/ -
Move DI to Infrastructure
mkdir -p src/Infrastructure/ServiceProviders mv src/Domain/*/DI/*Initializer.php src/Infrastructure/ServiceProviders/ # Rename to *ServiceProvider.php -
Fix Infrastructure Nesting
mv src/Application/Website/Infrastructure/GeoIp/ src/Infrastructure/GeoIp/ -
Update Namespaces and Imports
- Run PSR-4 compliance check
- Update all references to moved files
Priority 2: HIGH (1-2 weeks)
Estimated Effort: 1-2 weeks
-
Standardize Naming Conventions
- Change all plural directory names to singular
- Update namespaces accordingly
-
Fix PSR-4 Violations
- Scan entire codebase for namespace mismatches
- Correct all violations
-
Extract Application Code from Framework
- Identify application-specific logic in Framework/
- Move to Application/ layer
- Target: Reduce Framework to 50-60% of codebase
Priority 3: MEDIUM (2-4 weeks)
Estimated Effort: 2-4 weeks
-
Reduce Framework Module Count
- Consolidate related modules
- Merge overlapping functionality
- Target: Reduce from 44 to ~25 modules
-
Strengthen Domain Layer
- Extract business logic from Application/Framework
- Create comprehensive Value Objects
- Implement Domain Events
- Build proper Aggregates
- Target: Increase Domain to 15-20% of codebase
-
Flatten Deep Nesting
- Identify directories >6 levels deep
- Refactor to reduce nesting
- Target: Max 5-6 levels throughout
Priority 4: LOW (1-2 months)
Estimated Effort: 1-2 months
-
Split Large Directories
- Admin/ (234 files) → split by sub-domain
- Framework/Database/ (387 files) → split by concern
-
Improve Bounded Context Separation
- Define clear boundaries between domains
- Reduce cross-domain dependencies
- Implement Anti-Corruption Layers where needed
-
Documentation & Guidelines
- Document layer responsibilities
- Create architecture decision records (ADRs)
- Write contribution guidelines
Clean Architecture Compliance
Current Violations
| Principle | Status | Notes |
|---|---|---|
| Dependency Rule | ❌ VIOLATED | Domain depends on Framework (DI) |
| Layer Separation | ❌ VIOLATED | HTTP in Domain, Infrastructure in Application |
| Business Logic Independence | ⚠️ PARTIAL | Too much logic in Framework |
| Framework Independence | ⚠️ PARTIAL | Framework too large, absorbing app logic |
| Testability | ✅ GOOD | Framework patterns support testing |
Target State
All principles should be ✅ COMPLIANT after Priority 1-2 fixes.
Domain-Driven Design Compliance
Current State
| DDD Concept | Status | Notes |
|---|---|---|
| Bounded Contexts | ⚠️ PARTIAL | Domains defined but boundaries unclear |
| Entities | ✅ GOOD | Present in Domain layer |
| Value Objects | ⚠️ PARTIAL | Some present, but inconsistent usage |
| Aggregates | ❌ WEAK | Missing proper aggregate roots |
| Domain Events | ⚠️ PARTIAL | Event system exists, but underutilized |
| Repositories | ✅ GOOD | Repository pattern implemented |
| Domain Services | ⚠️ PARTIAL | Some present, but mixed with app services |
Testing Implications
Current Issues Affecting Testability:
- Domain depending on Framework makes unit testing harder
- HTTP in Domain couples business logic to web layer
- Thin Domain layer means less isolated business logic to test
After Fixes:
- ✅ Pure Domain layer → easy unit testing
- ✅ Clear boundaries → better integration testing
- ✅ Framework independence → faster test execution
Migration Strategy
Phase 1: Critical Fixes (Week 1-2)
- Move HTTP out of Domain
- Move DI to Infrastructure
- Fix Infrastructure nesting
- Update all imports and namespaces
Phase 2: Standardization (Week 3-4)
- Standardize naming conventions
- Fix PSR-4 violations
- Extract app logic from Framework
Phase 3: Strengthening (Month 2)
- Strengthen Domain layer
- Reduce Framework bloat
- Flatten deep nesting
Phase 4: Optimization (Month 3+)
- Split large directories
- Improve bounded contexts
- Comprehensive documentation
Success Metrics
After Priority 1-2 Fixes:
- ✅ Zero architectural violations
- ✅ All layers respect Dependency Rule
- ✅ PSR-4 compliance: 100%
- ✅ Framework layer: <60% of codebase
- ✅ Domain layer: >15% of codebase
Target Architecture Grade: A- (90%) after all phases
Conclusion
Current Grade: C+ (75%) - Good foundation with critical flaws
Key Strengths:
- ✅ Layer separation attempted
- ✅ Repository pattern implemented
- ✅ Value Objects used (though inconsistently)
- ✅ Event system in place
- ✅ Clear directory structure
Critical Weaknesses:
- ❌ HTTP in Domain layer
- ❌ DI setup in Domain layer
- ❌ Infrastructure nested in Application
- ❌ Framework layer too large (85%)
- ❌ Domain layer too thin (4%)
Recommendation: Implement Priority 1 fixes immediately to resolve critical architectural violations. Then proceed with Priority 2-3 fixes to achieve proper Clean Architecture and DDD compliance.
Estimated Total Effort: 2-3 months for complete restructuring
Analysis Methodology: Automated codebase exploration using framework's Discovery System, manual architectural review, Clean Architecture and DDD principles assessment.
Tools Used:
- Framework's
UnifiedDiscoveryService - Custom architectural analysis scripts
- PSR-4 compliance checker
Next Steps:
- Review this analysis with development team
- Create GitHub issues for Priority 1 fixes
- Establish migration timeline
- Update CI/CD to enforce new structure