Clean Architecture en ontwerppatronen in de praktijk · Les

Refactoring met designpatterns

Leer bestaande codebases systematisch te refactoren door geschikte designpatterns toe te passen voor een betere structuur en onderhoudbaarheid.

Les 3 van 411 stappen

Refactoring met designpatterns is een gratis Clean Architecture en ontwerppatronen in de praktijk-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Clean Architecture en ontwerppatronen in de praktijk. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Clean Architecture en ontwerppatronen in de praktijk bevat in totaal 4 lessen.

Herstructureren met ontwerppatronen

Wat is herstructureren? Het gaat om het verbeteren van de structuur van bestaande code zonder het externe gedrag ervan te veranderen. Waarom zou je er ontwerppatronen bij betrekken? Patronen bieden bewezen, herbruikbare oplossingen voor veelvoorkomende ontwerpproblemen, waardoor je herstructurering systematischer en effectiever wordt. Dit leidt tot duidelijkere, beter onderhoudbare en uitbreidbare code.

Codegeuren herkennen

Voordat je code herstructureert, moet je weten wat je moet aanpassen. Codegeuren zijn aanwijzingen dat er mogelijk iets mis is met het ontwerp van je code. Het zijn geen fouten, maar ze kunnen wel tot fouten leiden of het moeilijker maken om code te wijzigen.

  • Lange methode: Een methode die te veel doet.
  • Grote klasse: Een klasse met te veel verantwoordelijkheden.
  • Dubbele code: Dezelfde codelogica die op meerdere plaatsen voorkomt.
  • Complexe voorwaarden: Te veel if/else- of switch-instructies.

Systematische stappen voor herstructurering

Herstructureren moet een gedisciplineerd proces zijn, geen overhaaste herschrijving. Dit is een eenvoudige werkwijze:

  1. Herken een codegeur: Zoek een deel van je code dat beter kan.
  2. Kies een ontwerppatroon: Selecteer een patroon dat de herkende codegeur aanpakt.
  3. Pas het patroon toe: Voer kleine, stapsgewijze wijzigingen door en zorg ervoor dat de tests na elke stap slagen.
  4. Test grondig: Controleer of het externe gedrag onveranderd blijft.

Onthoud: "Red, Green, Refactor" is een krachtige mantra!

Strategie voor voorwaardelijke logica

Laten we een veelvoorkomende codegeur aanpakken: methoden met uitgebreide voorwaardelijke logica (veel if/else- of switch-instructies). Hierdoor wordt code moeilijk te lezen, te testen en uit te breiden. Het Strategypatroon helpt door variërend gedrag in afzonderlijke, uitwisselbare objecten onder te brengen.

Neem een eenvoudige rekenmachine:

public class SimpleCalculator {
  public int calculate(String operation, int a, int b) {
    if ("add".equals(operation)) {
      return a + b;
    } else if ("subtract".equals(operation)) {
      return a - b;
    } else if ("multiply".equals(operation)) {
      return a * b;
    }
    throw new IllegalArgumentException("Unknown operation");
  }

  public static void main(String[] args) {
    SimpleCalculator calc = new SimpleCalculator();
    System.out.println("Add: " + calc.calculate("add", 5, 3));
    System.out.println("Subtract: " + calc.calculate("subtract", 5, 3));
  }
}

Herstructureren naar Strategy

Om de rekenmachine te herstructureren, introduceren we een Operation-interface en specifieke strategieklassen voor elke bewerking. De Calculator gebruikt vervolgens een exemplaar van een Operation-strategie. Zo kun je eenvoudig nieuwe bewerkingen toevoegen zonder de klasse Calculator te wijzigen.

interface Operation {
  int execute(int a, int b);
}

class AddOperation implements Operation {
  @Override
  public int execute(int a, int b) {
    return a + b;
  }
}

class SubtractOperation implements Operation {
  @Override
  public int execute(int a, int b) {
    return a - b;
  }
}

public class RefactoredCalculator {
  private Operation operation;

  public void setOperation(Operation operation) {
    this.operation = operation;
  }

  public int calculate(int a, int b) {
    if (operation == null) {
      throw new IllegalStateException("Operation not set");
    }
    return operation.execute(a, b);
  }

  public static void main(String[] args) {
    RefactoredCalculator calc = new RefactoredCalculator();
    
    calc.setOperation(new AddOperation());
    System.out.println("Add: " + calc.calculate(5, 3));
    
    calc.setOperation(new SubtractOperation());
    System.out.println("Subtract: " + calc.calculate(5, 3));
  }
}

Het State-patroon voor gedragswijzigingen

Een andere veelvoorkomende codegeur is een object waarvan het gedrag verandert op basis van zijn interne toestand, vaak beheerd door veel if/else- of switch-instructies binnen de methoden. Met het State-patroon kan een object zijn gedrag aanpassen wanneer zijn interne toestand verandert, waardoor het lijkt alsof het object van klasse is veranderd.

Laten we naar een verkeerslicht kijken:

public class SimpleTrafficLight {
  private String currentState;

  public SimpleTrafficLight() {
    this.currentState = "RED"; // Initial state
  }

  public void change() {
    if ("RED".equals(currentState)) {
      currentState = "GREEN";
      System.out.println("Traffic light is now GREEN.");
    } else if ("GREEN".equals(currentState)) {
      currentState = "YELLOW";
      System.out.println("Traffic light is now YELLOW.");
    } else if ("YELLOW".equals(currentState)) {
      currentState = "RED";
      System.out.println("Traffic light is now RED.");
    }
  }

  public static void main(String[] args) {
    SimpleTrafficLight light = new SimpleTrafficLight();
    light.change(); // GREEN
    light.change(); // YELLOW
    light.change(); // RED
  }
}

Herstructureren naar State

Met het State-patroon definiëren we een interface voor de toestand van het verkeerslicht (TrafficLightState) en concrete klassen voor elke toestand (RedState, GreenState, YellowState). De klasse TrafficLight bevat een verwijzing naar zijn huidige toestandsobject en delegeert het gedrag daaraan. Zo wordt toestandspecifiek gedrag netjes gescheiden.

interface TrafficLightState {
  void change(TrafficLight context);
}

class RedState implements TrafficLightState {
  @Override
  public void change(TrafficLight context) {
    System.out.println("Traffic light is now GREEN.");
    context.setState(new GreenState());
  }
}

class GreenState implements TrafficLightState {
  @Override
  public void change(TrafficLight context) {
    System.out.println("Traffic light is now YELLOW.");
    context.setState(new YellowState());
  }
}

class YellowState implements TrafficLightState {
  @Override
  public void change(TrafficLight context) {
    System.out.println("Traffic light is now RED.");
    context.setState(new RedState());
  }
}

public class TrafficLight {
  private TrafficLightState currentState;

  public TrafficLight() {
    this.currentState = new RedState(); // Initial state
  }

  public void setState(TrafficLightState state) {
    this.currentState = state;
  }

  public void change() {
    currentState.change(this);
  }

  public static void main(String[] args) {
    TrafficLight light = new TrafficLight();
    light.change(); // GREEN
    light.change(); // YELLOW
    light.change(); // RED
  }
}

Het juiste patroon kiezen

Bepalen welk patroon je moet toepassen, kan lastig zijn. Hier zijn enkele veelvoorkomende codegeuren en geschikte patronen:

  • Voorwaardelijke complexiteit (if/else, switch): Wordt vaak geherstructureerd met Strategy, State of Command.
  • Dubbele code: Kan vaak worden opgelost met Factory Method, Template Method of door gemeenschappelijke logica naar een superklasse te verplaatsen.
  • Sterke koppeling: Facade, Mediator en Observer kunnen afhankelijkheden verminderen.
  • Niet-compatibele interfaces: Het Adapter-patroon is hiervoor perfect geschikt.
  • Functionaliteit dynamisch toevoegen: Het Decorator-patroon.

Waarom herstructureren met patronen?

Het systematisch toepassen van ontwerppatronen tijdens het herstructureren biedt aanzienlijke voordelen:

  • Verbeterde leesbaarheid: Patronen bieden een gemeenschappelijke woordenschat en structuur.
  • Betere onderhoudbaarheid: Wijzigingen blijven beperkt tot één plek en zijn eenvoudiger door te voeren.
  • Grotere uitbreidbaarheid: Nieuwe functies kunnen vaak worden toegevoegd zonder bestaande code te wijzigen (het Open/Closed-principe).
  • Betere testbaarheid: Ontkoppelde componenten zijn eenvoudiger met unittests te testen.

Hierdoor verandert rommelige code in een goed gestructureerd, robuust systeem.

Quiz over herstructureren

Stel dat je een klasse hebt die verschillende indelingen voor rapporten (PDF, CSV, XML) verwerkt met een grote switch-instructie. Je wilt eenvoudig nieuwe indelingen kunnen toevoegen zonder de kernklasse voor het genereren van rapporten te wijzigen.

Samenvatting: herstructureren met patronen

Vandaag hebben we geleerd hoe je herstructurering systematisch kunt aanpakken met behulp van ontwerppatronen. We hebben veelvoorkomende codegeuren verkend en gezien hoe patronen zoals Strategy en State complexe voorwaardelijke logica kunnen omvormen tot schonere, beter uitbreidbare ontwerpen.

Onthoud dat herstructurering een doorlopend proces is. Wanneer ontwerppatronen dit proces sturen, verbeteren ze de kwaliteit en aanpasbaarheid van je codebasis aanzienlijk.

Gratis beginnen

Leer Clean Architecture en ontwerppatronen in de praktijk met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
12
Lessen
48

Veelgestelde vragen

Is de les “Refactoring met designpatterns” gratis?

Ja — de volledige tekst van “Refactoring met designpatterns” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Clean Architecture en ontwerppatronen in de praktijk wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Clean Architecture en ontwerppatronen in de praktijk bevat in totaal 4 lessen.

Wat leer ik in “Refactoring met designpatterns”?

Leer bestaande codebases systematisch te refactoren door geschikte designpatterns toe te passen voor een betere structuur en onderhoudbaarheid. Je oefent met Clean Architecture en ontwerppatronen in de praktijk door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Clean Architecture en ontwerppatronen in de praktijk te beginnen?

Ervaring vooraf is niet nodig. Clean Architecture en ontwerppatronen in de praktijk op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Refactoring met designpatterns”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Clean Architecture en ontwerppatronen in de praktijk?

Ja. Elke les over Clean Architecture en ontwerppatronen in de praktijk bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Diepgaande behandeling van Dependency Inversion
  2. Interface Segregation in de praktijk
  3. Refactoring met designpatterns
  4. Beheersing van Single Responsibility en Open-Closed
← Terug naar Clean Architecture en ontwerppatronen in de praktijk