aymanmsh's avatar

Difference between Use Case, Action, and Application Service in DDD

I’m currently learning Domain-Driven Design (DDD) and trying to properly structure the Application Layer in a Laravel-based project.

I keep seeing different terms used, sometimes interchangeably, such as:

  • Use Case
  • Action
  • Application Service

From my understanding, they all seem to represent “application logic” that orchestrates domain behavior, but I’m struggling to clearly distinguish their responsibilities and when to use each one.

For example, in a typical authentication flow (like login or register):

  • Should I create a LoginUseCase, LoginAction, or LoginService?

  • Are these just naming conventions, or do they have real architectural differences?

  • Is it correct that:

    • A Use Case represents a single business interaction?
    • An Application Service coordinates domain objects and infrastructure?
    • An Action is just a Laravel-style way of structuring a single task?

Also, how do these concepts relate in practice:

  • Should a Use Case call an Application Service?
  • Or is an Application Service itself the Use Case?
  • Where do DTOs and domain services fit in this structure?

I’m looking for a clear explanation with practical examples (preferably in Laravel or PHP), especially from people who have applied DDD in real projects.

Thanks in advance!

2 likes
3 replies
LaryAI's avatar
Level 58

Absolutely, this is a common point of confusion—partly because the terms overlap and different communities use them differently. Here's a breakdown with practical Laravely-PHP examples:


1. Definitions & Differences

1. Use Case

  • What: Represents a specific business interaction or operation—as described by the user's needs.
  • Role: Encapsulates application logic for a single, meaningful action.
  • Example: "Login", "Register", "TransferFunds".

2. Application Service

  • What: A layer that orchestrates domain entities, integrating domain logic with infrastructure.
  • Role: Coordinates tasks between domain models, repositories and possibly other systems (emails, events, etc).
  • Sometimes: In many DDD applications, the Application Service and the Use Case are the same. The service is named according to the use case.

3. Action

  • What: Laravely naming convention, where each task (sometimes a "single action") is encapsulated in its own class. Not a formal DDD term.
  • Role: Helps break up controllers, keeps code clean, and makes things reusable/testable.
  • Example: "AuthenticateUserAction", "SendWelcomeEmailAction".

2. How They Relate

  • Usually:
    • In "classic" DDD, the Application Service is the Use Case (e.g., LoginUserService handles the "Login User" use case).
    • "Action" is a code-organization idea from Laravel and not part of DDD proper, but it plays a similar role.

3. Where Do DTOs and Domain Services Fit?

  • DTOs (Data Transfer Objects):
    Used to carry data between layers (controller → service, etc), without passing raw requests or Eloquent Models to your domain.
  • Domain Services:
    Implement domain logic that doesn’t naturally fit a single entity/value object (e.g., money transfer between accounts).

4. Practical Example

Let's imagine a Login feature in Laravel + DDD style.

Directory Example:

app
 └── Application
      └── UseCases
           └── LoginUser.php
      └── DTOs
           └── LoginUserDTO.php
 └── Domain
      └── User
           └── Entities
                └── User.php
           └── Services
                └── PasswordHasher.php

A. The DTO

<?php
namespace App\Application\DTOs;

class LoginUserDTO
{
    public string $email;
    public string $password;

    public function __construct(string $email, string $password)
    {
        $this->email = $email;
        $this->password = $password;
    }
}

B. The Use Case (or ApplicationService)

C. The Controller

public function login(Request $request, LoginUser $loginUser)
{
    $dto = new LoginUserDTO($request->email, $request->password);
    $token = $loginUser->execute($dto);

    if (! $token) {
        return response()->json(['error' => 'Invalid credentials'], 401);
    }
    return response()->json(['token' => $token]);
}

5. So, Which To Use?

  • For pure DDD-inspired architecture:
    • Use Use Cases (each one in its own "ApplicationService"/"UseCase" class).
    • The name can be LoginUser, LoginUserUseCase, or LoginUserService (be consistent!).
  • For Laravel-style single job classes:
    • You might call them Actions, but if possible, stick to use-case language—it communicates intent better.

6. Summary Table

Term DDD Proper? Role Practical Example
Use Case YES Encapsulates business operation LoginUser
Application Service YES Orchestrates use case & domain objects LoginUserService
Action NO (Laravel) Single action, task-based class LoginUserAction
  • DTOs carry data between layers.
  • Domain services contain domain logic not tied to one entity.

7. Key Takeaways

  • Use Case == Application Service in most DDD setups.
  • Action is a Laravel-ism, but can follow same principles.
  • Name classes according to the business operation.
  • DTOs are for data transport, Domain Services for cross-entity logic.

In essence:
Don’t get too hung up on naming: focus on clear layers, clear responsibilities, and let your code communicate intent!


References:


Hope this helps clear things up!

imranbru's avatar

You’re overthinking the terminology because the industry uses them interchangeably, but here is the breakdown from a practical, "in the trenches" perspective.

Using the single-task approach (Action/Use Case) is usually superior in Laravel because it keeps your classes small and makes injection easier.

class RegisterUserAction 
{
    public function __construct(
        protected UserRepository $users,
        protected BillingService $billing // Domain Service
    ) {}

    public function execute(UserData $data): User
    {
        $user = User::register($data->email, $data->password);

        $this->users->save($user);
        $this->billing->createCustomer($user);

        UserRegistered::dispatch($user);

        return $user;
    }
}
1 like
martinbean's avatar

@aymanmsh That’s because they pretty much are interchangeable. Those names just refer to a class that encapsulates business logic.

Use cases and actions tend to be individual classes that encapsulate a single process, whereas an application service tends to be a class that groups one or more methods related to a particular concept in a single class. So you might have a OrderService with methods for creating an order, updating an order, cancelling an order, etc.

The important thing is to choose one approach and stick to it. Your codebase should look like a single person has authored it, so that means not using multiple names and approaches for the same thing.

Also, my customary DDD gripe: DDD is more about working with people in a business to create software that accurately models that business and its processes. DDD is not carving your codebase up into modules that you then you then call “domains” instead.

1 like

Please or to participate in this conversation.