0Pricing
Clean Architecture & Design Patterns in Practice · บทเรียน

การนำกรณีใช้งานมาใช้ (ตัวประสานงาน)

พัฒนากรณีใช้งานที่ประสานงานเอนทิตีเพื่อสร้างความสามารถเฉพาะของแอปพลิเคชัน โดยสะท้อนกฎทางธุรกิจเฉพาะแอปพลิเคชัน

การนำกรณีใช้งานมาใช้ (ตัวประสานงาน) เป็นบทเรียน Clean Architecture & Design Patterns in Practice ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Clean Architecture & Design Patterns in Practice และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Clean Architecture & Design Patterns in Practice มีบทเรียนทั้งหมด 4 บทเรียน

บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ

What are Use Cases (Interactors)?

In Clean Architecture, Use Cases (sometimes called Interactors) are at the heart of your application's logic. They represent the specific tasks or features your application can perform.

Think of them as the orchestrators of your core business entities. They define how your application uses those entities to achieve a goal, like 'create a new user' or 'process an order'.

Role of Use Cases in Clean Architecture

Use Cases sit in the 'Use Cases' layer, just outside the 'Entities' layer. This means:

  • They depend on Entities.
  • They do NOT depend on external layers like the UI, databases, or web frameworks.

Their main job is to coordinate the flow of data to and from the Entities and direct the Entities to perform their specific business rules.

Embodying Application Rules

While Entities hold the enterprise-wide business rules (rules true for the entire business, regardless of application), Use Cases embody application-specific business rules.

For example, an 'Order' Entity might have a rule that an order total cannot be negative. A 'Process Order' Use Case might have an application rule that a user must be logged in to place an order, or that certain promotions apply at checkout.

Defining Use Case Boundaries

To keep Use Cases isolated, they communicate with the outside world through interfaces:

  • Input Port: An interface that defines what data a Use Case expects to receive.
  • Output Port: An interface that defines what data a Use Case will produce.

These ports ensure the Use Case doesn't know about specific UI components or database implementations.

Anatomy of a Use Case

A typical Use Case is a class with a single public method (e.g., execute or handle). This method usually takes an 'Input Data Transfer Object' (DTO) and returns an 'Output DTO'.

Inside, it interacts with entities and often uses 'Gateway' or 'Repository' interfaces to talk to data storage or external services, without knowing their concrete implementations.

Example: Create User Use Case

Let's consider a CreateUserUseCase. First, we define the simple data structures for input and output. These are plain Java objects (POJOs).

public class CreateUserInput {
  public String name;
  public String email;
}

public class CreateUserOutput {
  public String userId;
  public String message;
  public boolean success;
}

Implementing the Logic

Now, let's see how the CreateUserUseCase orchestrates a User entity and interacts with a UserRepository (an interface) to perform its task.

Try running this example:

public class User {
  private String id;
  private String name;
  private String email;

  public User(String id, String name, String email) {
    this.id = id;
    this.name = name;
    this.email = email;
  }

  public String getId() { return id; }
  public String getName() { return name; }
  public String getEmail() { return email; }
  
  public boolean isValid() { return name != null && !name.isEmpty() && email != null && email.contains("@"); }
}

interface IUserRepository {
  void save(User user);
  String generateId();
}

class InMemoryUserRepository implements IUserRepository {
  @Override
  public void save(User user) {
    System.out.println("Saving user: " + user.getName() + " with ID: " + user.getId());
  }

  @Override
  public String generateId() {
    return "user-" + System.currentTimeMillis();
  }
}

public class CreateUserInput {
  public String name;
  public String email;
}

public class CreateUserOutput {
  public String userId;
  public String message;
  public boolean success;
}

class CreateUserUseCase {
  private final IUserRepository userRepository;

  public CreateUserUseCase(IUserRepository userRepository) {
    this.userRepository = userRepository;
  }

  public CreateUserOutput execute(CreateUserInput input) {
    CreateUserOutput output = new CreateUserOutput();

    if (input.name == null || input.name.isEmpty()) {
      output.success = false;
      output.message = "Name cannot be empty.";
      return output;
    }
    if (input.email == null || !input.email.contains("@")) {
      output.success = false;
      output.message = "Invalid email address.";
      return output;
    }

    String newId = userRepository.generateId();
    User newUser = new User(newId, input.name, input.email);

    if (!newUser.isValid()) {
      output.success = false;
      output.message = "User data is invalid.";
      return output;
    }
    
    userRepository.save(newUser);
    
    output.success = true;
    output.userId = newId;
    output.message = "User created successfully.";
    return output;
  }
}

public class Main {
  public static void main(String[] args) {
    IUserRepository repo = new InMemoryUserRepository();
    CreateUserUseCase useCase = new CreateUserUseCase(repo);

    CreateUserInput input = new CreateUserInput();
    input.name = "Alice";
    input.email = "alice@example.com";

    CreateUserOutput output = useCase.execute(input);

    if (output.success) {
      System.out.println("Result: " + output.message + " ID: " + output.userId);
    } else {
      System.out.println("Error: " + output.message);
    }

    // Test with invalid input
    CreateUserInput invalidInput = new CreateUserInput();
    invalidInput.name = "";
    invalidInput.email = "invalid";
    CreateUserOutput errorOutput = useCase.execute(invalidInput);
    System.out.println("Error test: " + errorOutput.message);
  }
}

Benefits of Use Cases

Using Use Cases brings significant advantages to your software design:

  • Isolation: Application-specific logic is isolated from UI, database, and frameworks.
  • Testability: Use Cases can be tested easily in isolation, without needing a UI or database connection.
  • Independence: Changes in the UI or database technology won't directly impact your core application logic.
  • Clarity: Each Use Case clearly defines a single feature or task of the application.

Use Case Interaction Flow

When a user interacts with your application, here's a simplified flow involving a Use Case:

  1. UI/Controller: Receives a request (e.g., button click).
  2. Input Port: The controller translates the request into a specific input format for the Use Case.
  3. Use Case: Executes its logic, orchestrating entities and interacting with repositories/gateways.
  4. Output Port: The Use Case provides its result in a generic output format.
  5. Presenter/UI: Transforms the Use Case output into something displayable to the user.

This flow ensures a clean separation of concerns.

Quick Check: Use Case's Role

Based on what you've learned, what is the primary role of a Use Case (Interactor) in Clean Architecture?

Recap: Orchestrating Actions

You've now learned about Use Cases, the application-specific orchestrators in Clean Architecture. They define your app's features, coordinate entities, and encapsulate business rules specific to the application.

By using Input and Output Ports, Use Cases remain independent of external layers, making your core logic highly testable, maintainable, and flexible to change. This is a crucial step towards building robust and adaptable software systems!

คำถามที่พบบ่อย

บทเรียน “การนำกรณีใช้งานมาใช้ (ตัวประสานงาน)” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การนำกรณีใช้งานมาใช้ (ตัวประสานงาน)” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Clean Architecture & Design Patterns in Practice ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Clean Architecture & Design Patterns in Practice มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การนำกรณีใช้งานมาใช้ (ตัวประสานงาน)”

พัฒนากรณีใช้งานที่ประสานงานเอนทิตีเพื่อสร้างความสามารถเฉพาะของแอปพลิเคชัน โดยสะท้อนกฎทางธุรกิจเฉพาะแอปพลิเคชัน คุณปฏิบัติ Clean Architecture & Design Patterns in Practice ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Clean Architecture & Design Patterns in Practice หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Clean Architecture & Design Patterns in Practice บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การนำกรณีใช้งานมาใช้ (ตัวประสานงาน)” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Clean Architecture & Design Patterns in Practice นี้ได้ไหม

ได้ บทเรียน Clean Architecture & Design Patterns in Practice ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การออกแบบเอนทิตีทางธุรกิจ
  2. การนำกรณีใช้งานมาใช้ (ตัวประสานงาน)
  3. พอร์ตข้อมูลเข้าและข้อมูลออก
  4. การบังคับใช้กฎธุรกิจด้วยค่าคงสภาพ
← กลับไปที่ Clean Architecture & Design Patterns in Practice