مقاله

مقایسه عملی Service چندمتدی و Single Action — معیار انتخاب، ترکیب هر دو و anti-patternهای رایج.

Service Layer در مقابل Action Class — کدام را در Laravel انتخاب کنیم؟

Service Layer در مقابل Action Class — کدام را در Laravel انتخاب کنیم؟

در Laravel دو الگوی محبوب برای خروج logic از Controller داریم: Service Layer (یک کلاس با چند متد مرتبط مثل PostService) و Action Class (یک کلاس یک use case مثل CreatePostAction). بحث forum اغلب «کدام بهتر» است — جواب: بستگی به اندازه تیم و پیچیدگی domain دارد.

Service Layer چیست؟

class PostService
{
    public function __construct(private PostRepositoryInterface $posts) {}

    public function create(CreatePostData $data, User $author): Post { /* ... */ }
    public function update(Post $post, UpdatePostData $data): Post { /* ... */ }
    public function publish(Post $post): Post { /* ... */ }
}

گروه عملیات روی یک aggregate — معماری لایه‌ای.

Action Class چیست؟

class CreatePostAction
{
    public function handle(CreatePostData $data, User $author): Post { /* ... */ }
}

Action classes — یک فایل یک مسئولیت use case.

مقایسه سریع

معیارServiceAction
تعداد فایلکمتربیشتر
یافتن use casescroll متدهانام فایل = use case
پروژه کوچکراحت‌ترشاید overkill
پروژه بزرگrisk god servicescale بهتر
تستmock یک serviceتست یک action ایزوله
Route invokableمعمولاً نهبله با __invoke

کی Service؟

  • CRUD ساده یک domain کوچک
  • تیم ۱–۲ نفره — سرعت مهم‌تر از ساختار
  • متدها واقعاً cohesive (همه درباره Post)

کی Action؟

  • use case با مراحل زیاد (transaction، event، queue)
  • نیاز به traceability (لاگ کدام عملیات)
  • تیم بزرگ — conflict کمتر روی یک فایل بزرگ

ترکیب هر دو — رایج و سالم

class PostService
{
    public function __construct(
        private CreatePostAction $create,
        private PublishPostAction $publish,
    ) {}

    public function createAndPublish(CreatePostData $data, User $user): Post
    {
        $post = $this->create->handle($data, $user);
        return $this->publish->handle($post);
    }
}

Service نازک orchestrator؛ Actionها executable. یا Service per subdomain و Action برای complex flows.

Anti-patterns

  • God Service — ۲۰۰۰ خط همه چیز
  • Anemic Action — فقط Post::create($data) wrap
  • Service در Service در Service — بدون مرز واضح
  • static Service — تست و DI می‌شکند

SOLID SRP.

ساختار پوشه پیشنهادی

app/Services/PostService.php          // اختیاری facade نازک
app/Actions/Posts/CreatePostAction.php
app/Actions/Posts/PublishPostAction.php
app/DTO/Posts/CreatePostData.php

Repository کجا صدا زده شود؟

داخل Action یا Service — نه Controller. Repository.

Filament و Service/Action

Resource method می‌تواند Action را inject کند — logic یکسان web و admin.

جمع‌بندی

شروع با Service ساده OK؛ وقتی فایل شلوغ شد split به Action. DTO: DTO. VO: Value Object.

طراحی لایه business