Ren arkitektur og designmønstre i praksis · Lektion

Implementering af Use Cases (Interactors)

Udvikl Use Cases, der orkestrerer Entities for at realisere specifikke programfunktioner og udtrykke applikationsspecifikke forretningsregler.

Lektion 2 af 411 trin

Implementering af Use Cases (Interactors) er en gratis Ren arkitektur og designmønstre i praksis-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Ren arkitektur og designmønstre i praksis, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Ren arkitektur og designmønstre i praksis-kurset indeholder 4 lektioner i alt.

Hvad er Use Cases (Interactors)?

I Clean Architecture er Use Cases (som nogle gange kaldes Interactors) kernen i din applikations logik. De repræsenterer de specifikke opgaver eller funktioner, som din applikation kan udføre.

Tænk på dem som koordinatorerne for dine centrale forretningsentiteter. De definerer hvordan din applikation bruger disse entiteter til at nå et mål, f.eks. 'opret en ny bruger' eller 'behandl en ordre'.

Use Cases' rolle i Clean Architecture

Use Cases ligger i laget 'Use Cases', lige uden for laget 'Entities'. Det betyder:

  • De afhænger af Entities.
  • De afhænger IKKE af eksterne lag som brugergrænsefladen, databaser eller webframeworks.

Deres vigtigste opgave er at koordinere dataflowet til og fra Entities og få Entities til at udføre deres specifikke forretningsregler.

Implementering af applikationsregler

Mens Entities indeholder de forretningsregler, der gælder for hele virksomheden (regler, der gælder for hele virksomheden uanset applikation), repræsenterer Use Cases applikationsspecifikke forretningsregler.

En 'Order'-Entity kan f.eks. have en regel om, at en ordres total ikke må være negativ. Et 'Process Order'-Use Case kan have en applikationsregel om, at en bruger skal være logget ind for at placere en ordre, eller at bestemte kampagner gælder ved betaling.

Definition af Use Case-grænser

For at holde Use Cases isolerede kommunikerer de med omverdenen gennem grænseflader:

  • Input Port: En grænseflade, der definerer, hvilke data et Use Case forventer at modtage.
  • Output Port: En grænseflade, der definerer, hvilke data et Use Case producerer.

Disse porte sikrer, at Use Case'et ikke kender til bestemte brugergrænsefladekomponenter eller databaseimplementeringer.

Et Use Cases opbygning

Et typisk Use Case er en klasse med én offentlig metode (f.eks. execute eller handle). Denne metode modtager normalt et 'Input Data Transfer Object' (DTO) og returnerer en 'Output DTO'.

Indeni interagerer det med entities og bruger ofte 'Gateway'- eller 'Repository'-grænseflader til at kommunikere med datalagring eller eksterne tjenester uden at kende deres konkrete implementeringer.

Eksempel: Use Case til oprettelse af bruger

Lad os se på et CreateUserUseCase. Først definerer vi de simple datastrukturer til input og output. Det er almindelige Java-objekter (POJO'er).

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

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

Implementering af logikken

Lad os nu se, hvordan CreateUserUseCase koordinerer en User-entity og interagerer med et UserRepository (en grænseflade) for at udføre sin opgave.

Prøv at køre dette eksempel:

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);
  }
}

Fordele ved Use Cases

Brugen af Use Cases giver betydelige fordele for dit softwaredesign:

  • Isolation: Applikationsspecifik logik er isoleret fra brugergrænseflade, database og frameworks.
  • Testbarhed: Use Cases kan nemt testes isoleret uden at kræve en brugergrænseflade eller databaseforbindelse.
  • Uafhængighed: Ændringer i brugergrænsefladen eller databaseteknologien påvirker ikke din centrale applikationslogik direkte.
  • Klarhed: Hvert Use Case definerer tydeligt én funktion eller opgave i applikationen.

Interaktionsforløb for et Use Case

Når en bruger interagerer med din applikation, ser et forenklet forløb med et Use Case sådan ud:

  1. UI/Controller: Modtager en anmodning (f.eks. et klik på en knap).
  2. Input Port: Controlleren oversætter anmodningen til et bestemt inputformat for Use Case'et.
  3. Use Case: Udfører sin logik, koordinerer entities og interagerer med repositories/gateways.
  4. Output Port: Use Case'et leverer sit resultat i et generisk outputformat.
  5. Presenter/UI: Omdanner Use Case'ets output til noget, der kan vises for brugeren.

Dette forløb sikrer en ren adskillelse af ansvar.

Hurtigt tjek: Use Case'ets rolle

Ud fra det, du har lært, hvad er den primære rolle for et Use Case (Interactor) i Clean Architecture?

Opsummering: Koordinering af handlinger

Du har nu lært om Use Cases, de applikationsspecifikke koordinatorer i Clean Architecture. De definerer din apps funktioner, koordinerer entities og indkapsler forretningsregler, der er specifikke for applikationen.

Ved at bruge Input- og Output-Ports forbliver Use Cases uafhængige af eksterne lag, hvilket gør din centrale logik meget testbar, vedligeholdelsesvenlig og fleksibel over for ændringer. Det er et afgørende skridt mod at bygge robuste og tilpasningsdygtige softwaresystemer!

Gratis at komme i gang

Lær Ren arkitektur og designmønstre i praksis med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
12
Lektioner
48

Ofte stillede spørgsmål

Er lektionen “Implementering af Use Cases (Interactors)” gratis?

Ja — hele teksten til “Implementering af Use Cases (Interactors)” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Ren arkitektur og designmønstre i praksis-kurset, skal du opgradere til CoddyKit PRO. Ren arkitektur og designmønstre i praksis-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Implementering af Use Cases (Interactors)”?

Udvikl Use Cases, der orkestrerer Entities for at realisere specifikke programfunktioner og udtrykke applikationsspecifikke forretningsregler. Du øver dig i Ren arkitektur og designmønstre i praksis med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Ren arkitektur og designmønstre i praksis?

Der kræves ingen tidligere erfaring. Ren arkitektur og designmønstre i praksis på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “Implementering af Use Cases (Interactors)”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Ren arkitektur og designmønstre i praksis-lektion?

Ja. Alle Ren arkitektur og designmønstre i praksis-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Design af forretningsentiteter
  2. Implementering af Use Cases (Interactors)
  3. Input- og Output-porte
  4. Håndhævelse af forretningsregler med invariants
← Tilbage til Ren arkitektur og designmønstre i praksis