算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
project-ddd【设计与创意】Pragmatic Domain-Driven Design for Laravel projects — business-first, not academic. Helps restructure Laravel apps from default flat structure into domain-based organisation with clear bounded contexts, domain layers (Models, Events, Contracts, Value Objects), application layers (Actions, Jobs, Services), and infrastructure layers (Registrars, Export…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Restructure Laravel applications into domain-based organisation. Business objectives first — increase revenue, reduce OPEX, ship faster. Not academic DDD, but practical domain separation that your team can maintain.
"Kita orang meniaga nak increase sales, kurangkan OPEX. Bukan nak berfilasuf pasal kod."
This skill applies DDD where it creates real business value:
| Command | Description |
|---|---|
/project-ddd discover | Interview to identify bounded contexts from business processes |
/project-ddd plan | Generate migration plan from flat Laravel to domain structure |
/project-ddd scaffold | Scaffold a new domain with all layers |
/project-ddd migrate | Move existing code into domain structure (guided, step-by-step) |
/project-ddd wire | Create/update domain service providers and autoloading |
/project-ddd test | Update architecture tests for DDD structure |
/project-ddd audit | Check existing domain structure for violations |
graphify builds a persistent, queryable knowledge graph of a codebase — tree-sitter AST
parsing for code plus semantic extraction for docs. It answers structural questions far faster
than grepping, and it is installed by default with this toolkit.
Use it before a manual sweep whenever the question is structural.
graphify extract . # build (or refresh) the graph — once per repo
graphify query "how does authentication work"
graphify path UserController InvoiceRepository # call chain between two nodes
graphify explain app/Services/BillingService.php
If graphify-out/ already exists in the target repo, treat the question as a graph query
first and fall back to file reading only for what the graph cannot answer. If graphify is
not installed, carry on with the normal file-reading approach — it is an accelerator, never a
prerequisite.
/project-ddd discover — Domain DiscoveryIdentify bounded contexts by interviewing the user about their business processes, not their code structure.
Ask in this order:
Produce a Domain Map table:
## Domain Map
| Domain | Business Capability | Key Models | Owner | Priority |
|---|---|---|---|---|
| Identity | User auth, roles, profiles | User, Role, Team | Core | High |
| Billing | Subscriptions, invoicing | Plan, Subscription, Invoice | Revenue | High |
| Catalogue | Products, pricing, inventory | Product, Category, Price | Revenue | Medium |
| Fulfilment | Orders, shipping, tracking | Order, Shipment, Tracking | Ops | Medium |
| Notification | Alerts, emails, SMS | Channel, Template, Delivery | Support | Low |
| Shared | Base models, common traits | Base, Activity, Setting | Core | — |
Rules:
/project-ddd plan — Migration PlanGenerate a step-by-step migration plan to move from flat Laravel to domain structure.
Read the project's current app/ directory and categorise:
Produce a numbered task list grouped by domain:
## Migration Plan
### Phase 1: Foundation
- [ ] Task 1: Scaffold src/ directories and configure autoloading
- [ ] Task 2: Move Shared domain models (Base, Activity, Setting)
### Phase 2: Core Domains
- [ ] Task 3: Move [Domain] domain layer (Models, Events, Contracts)
- [ ] Task 4: Move [Domain] application layer (Jobs, Services, Actions)
- [ ] Task 5: Move [Domain] infrastructure layer (Registrars, Exports)
### Phase 3: Supporting Domains
- [ ] Task 6: Move [Domain] domain (Models, Jobs, webhook handlers)
- [ ] Task 7: Move remaining shared infrastructure
### Phase 4: Wiring
- [ ] Task 8: Create domain service providers and clean up AppServiceProvider
- [ ] Task 9: Update architecture tests for DDD structure
### Phase 5: Verification
- [ ] Task 10: Clean up empty directories, full verification
Rules:
/project-ddd scaffold — Scaffold DomainCreate a new domain directory structure with all layers.
Ask the user:
Billing, DomainManagement)src/
└── Domain/
└── {DomainName}/
├── Domain/
│ ├── Models/
│ │ └── {Model}.php
│ ├── Events/
│ │ └── {Model}Created.php
│ ├── Contracts/
│ │ └── {Model}Repository.php
│ └── ValueObjects/
│ └── {ValueObject}.php
├── Application/
│ ├── Actions/
│ │ └── Create{Model}.php
│ ├── Jobs/
│ │ └── Process{Model}.php
│ └── Services/
│ └── {DomainName}Service.php
├── Infrastructure/
│ ├── Registrars/
│ │ └── {DomainName}Registrar.php
│ └── Providers/
│ └── {DomainName}ServiceProvider.php
└── Presentation/
├── Controllers/
│ └── {Model}Controller.php
└── Resources/
└── {Model}Resource.php
| Layer | Contains | Depends On | DO NOT |
|---|---|---|---|
| Domain | Models, Events, Contracts, VOs | Nothing (pure) | Import from Application/Infrastructure |
| Application | Actions, Jobs, Services | Domain only | Import from Infrastructure/Presentation |
| Infrastructure | Providers, Registrars, Exports | Domain + Application | Contain business logic |
| Presentation | Controllers, Resources, Requests | Application | Contain business logic |
<?php
namespace Src\Domain\{DomainName}\Infrastructure\Providers;
use Illuminate\Support\ServiceProvider;
class {DomainName}ServiceProvider extends ServiceProvider
{
public function register(): void
{
// Bind contracts to implementations
}
public function boot(): void
{
// Register domain event listeners, routes, etc.
}
}
<?php
namespace Src\Domain\{DomainName}\Application\Actions;
use CleaniqueCoders\LaravelAction\Action;
class Create{Model} extends Action
{
public function execute(array $data): {Model}
{
return {Model}::create($data);
}
}
/project-ddd migrate — Guided MigrationMove existing code from flat app/ into domain structure, one step at a time.
For each migration task:
composer.json PSR-4 mapping| From (flat) | To (domain) |
|---|---|
App\Models\{Model} | Src\Domain\{Domain}\Domain\Models\{Model} |
App\Events\{Event} | Src\Domain\{Domain}\Domain\Events\{Event} |
App\Contracts\{Contract} | Src\Domain\{Domain}\Domain\Contracts\{Contract} |
App\Actions\{Action} | Src\Domain\{Domain}\Application\Actions\{Action} |
App\Jobs\{Job} | Src\Domain\{Domain}\Application\Jobs\{Job} |
App\Services\{Service} | Src\Domain\{Domain}\Application\Services\{Service} |
App\Http\Controllers\{Ctrl} | Src\Domain\{Domain}\Presentation\Controllers\{Ctrl} |
App\Http\Resources\{Res} | Src\Domain\{Domain}\Presentation\Resources\{Res} |
After scaffolding src/, update composer.json:
{
"autoload": {
"psr-4": {
"App\\": "app/",
"Src\\": "src/"
}
}
}
Then run composer dump-autoload.
/project-ddd wire — Service Provider WiringCreate or update domain service providers and register them in the app.
{DomainName}ServiceProvider for each domain under src/bootstrap/providers.php (Laravel 11+) or config/app.phpAppServiceProvider — move domain-specific bindings to domain providers// bootstrap/providers.php
return [
App\Providers\AppServiceProvider::class,
// Domain providers
Src\Domain\Identity\Infrastructure\Providers\IdentityServiceProvider::class,
Src\Domain\Billing\Infrastructure\Providers\BillingServiceProvider::class,
Src\Domain\Catalogue\Infrastructure\Providers\CatalogueServiceProvider::class,
];
/project-ddd test — Architecture TestsUpdate Pest architecture tests to enforce DDD boundaries.
// tests/Architecture/DomainTest.php
arch('domain layer has no infrastructure imports')
->expect('Src\Domain\*\Domain')
->not->toUse([
'Illuminate\Support\ServiceProvider',
'Illuminate\Http',
]);
arch('domain models extend base')
->expect('Src\Domain\*\Domain\Models')
->toExtend('Src\Domain\Shared\Domain\Models\Base');
arch('application layer does not import presentation')
->expect('Src\Domain\*\Application')
->not->toUse('Src\Domain\*\Presentation');
arch('infrastructure layer does not contain business logic')
->expect('Src\Domain\*\Infrastructure')
->not->toUse('Src\Domain\*\Domain\Models');
arch('controllers use actions, not models directly')
->expect('Src\Domain\*\Presentation\Controllers')
->toOnlyUse([
'Src\Domain\*\Application',
'Illuminate\Http',
'Illuminate\Routing',
]);
arch('domain events follow naming convention')
->expect('Src\Domain\*\Domain\Events')
->toHaveSuffix('Event')
->orThat()
->toMatch('/Created|Updated|Deleted|Activated|Deactivated|Completed/');
arch('value objects are final and readonly')
->expect('Src\Domain\*\Domain\ValueObjects')
->toBeFinal()
->toBeReadonly();
/project-ddd audit — Domain AuditCheck existing domain structure for boundary violations and misplaced code.
| Check | What It Looks For |
|---|---|
| Layer violations | Domain importing from Infrastructure/Presentation |
| Orphan models | Models in app/Models/ that should be in a domain |
| Fat controllers | Controllers with business logic (should use Actions) |
| Cross-domain coupling | Domain A directly importing Domain B's models |
| Missing providers | Domains without a registered ServiceProvider |
| Shared bloat | Too many things in Shared (should be in specific domains) |
## DDD Audit Report
### Violations (3)
- Domain\Billing\Domain\Models\Invoice imports from Infrastructure
- Domain\Identity uses Domain\Billing\Domain\Models\Plan directly
- AppServiceProvider still has Billing-specific bindings
### Warnings (2)
- app/Models/Legacy.php not assigned to any domain
- Shared domain has 12 models (consider splitting)
### Healthy (4 domains)
- Identity: clean boundaries
- Billing: clean boundaries
- Catalogue: clean boundaries
- Fulfilment: clean boundaries
Be honest with the user. DDD adds complexity. Skip it when:
DDD pays off when:
| File | Description |
|---|---|
| references/domain-structure.md | Full directory structure template with all layers |
| references/migration-checklist.md | Step-by-step migration checklist with verification gates |
| references/arch-tests.md | Complete Pest architecture test suite for DDD boundaries |