Clean Code: kleine Methoden

Die erste Regel für Funktionen lautet: Funktionen sollten klein sein. Die Zweite Regel für Funktionen lautet: Funktionen sollten noch kleiner sein.

public abstract class AbstractListImporter<T, E extends ApplicationEvent> implements ApplicationEventPublisherAware, ApplicationListener<E>, ApplicationContextAware {
// ...
    protected void handle(E event) {
        int importCount = 0;

        for (Resource resource : resources) {
            if (!resource.exists()) {
                log.error("Unable to import list cause {} does not exists", resource.getFilename());
                continue;
            }
            if (importOutdatedCheck != null && importOutdatedCheck.isUpToDate(resource)) {
                continue;
            }
            try {
                importCount += handleImport(resource, event);
                if (importOutdatedCheck != null) {
                    importOutdatedCheck.upsertImport(resource);
                }
            } catch (Exception e) {
                log.error("Unable to import {}", resource, e);
                String resourceName = Optional.ofNullable(resource.getFilename()).orElse("[null]");
                if (resource.getFilename() != null) {
                    MDC.put("resource", resourceName);
                }
            }
        }
        applicationEventPublisher.publishEvent(createImportCompletedEvent(importCount));
    }
//...
Antwort
public abstract class AbstractListImporter<T, E extends ApplicationEvent> implements ApplicationEventPublisherAware, ApplicationListener<E>, ApplicationContextAware {
// ...
    protected void handle(E event) {
        int importCount = this.handleImportForAllResourcesAndCount(event);
        applicationEventPublisher.publishEvent(createImportCompletedEvent(importCount));
    }

    private int handleImportForAllResourcesAndCount(E event) {
        int importCount = 0;
        for (Resource resource : resources) {
            if (this.isResourceNotAllowedToImport(resource)) continue;
            importCount = tryHandleImport(event, importCount, resource);
        }
        return importCount;
    }

    private int tryHandleImport(E event, int importCount, Resource resource) {
        try {
            importCount = this.handleImportAndSave(event, importCount, resource);
        } catch (Exception e) {
            this.handleException(resource, e);
        }
        return importCount;
    }

    private int handleImportAndSave(E event, int importCount, Resource resource) {
        importCount += this.handleImport(resource, event);
        if (importOutdatedCheck != null) {
            importOutdatedCheck.upsertImport(resource);
        }
        return importCount;
    }

    private void handleException(Resource resource, Exception e) {
        log.error("Unable to import {}", resource, e);
        String resourceName = Optional.ofNullable(resource.getFilename()).orElse("[null]");
        if (resource.getFilename() != null) {
            MDC.put("resource", resourceName);
        }
    }

    private boolean isResourceNotAllowedToImport(Resource resource) {
        if (!resource.exists()) {
            log.error("Unable to import list cause {} does not exists", resource.getFilename());
            return true;
        }
        return this.isImportOutdatedCheckUpToDate(resource);
    }

    private boolean isImportOutdatedCheckUpToDate(Resource resource) {
        return importOutdatedCheck != null && importOutdatedCheck.isUpToDate(resource);
    }
// ...
Regeln
  • kleine Funktions-Blöcke
    • if, else, while, try, catch... sollten nur eine Zeile beinhalten -> möglicherweise Funktion Aufruf
  • eine Aufgabe erledigen
    • Wenn man aus einem Funktion-Namen eine andere Funktion extrahieren kann, ist das ein Kandidat für eine Aufgabe zu viel. handleImportAndSave
  • Nur eine Abstraktionsebene pro Funktion
  • Switch Anweisung vermeiden
    • machen mehr als eine Sache
    • Single Responsibiliy wird oft verletzt
    • Nutzen in Abstarct Factoty Pattern und niemals jemanden sehen lassen.
  • Beschreibende Namen verwenden
    • Man kann sauberen Code daran erkennen, dass er tut, was man erwartet

  • Funktions-Argumente
    • mehr als 3 Argumente sollten nicht genutzt werden oder sehr gut begründet sein (also Ausnahme)
      • bei mehr bietet sich ein Objekt an
    • Flag-Argumente vermeiden:
      • deutet darauf hin, dass mehr als eine sache gemacht wird
      • manchmal unvermeidbar
      • besser in 2 Methoden aufteilen. render(true)zu renderForSuite() und renderForSingletest()
  • Sideeffects vermeiden
  • Anweisungen und Abfragen trennen
    • if(set("key"))
if(attributeExists("key")){
    setAttribute("key");
}

Wichtiger shortcut:

⌘+⌥+M -> Method extraction

Wir freuen uns Sie kennen zu lernen

Hat Sie unser Angebot überzeugt? Dann freuen wir uns, Sie kennen zu lernen. Kontaktieren Sie uns gerne für ein unverbindliches Erstgespräch.

newcubator GmbH
Freie-Vogel-Straße 369
44269 Dortmund
dortmund@newcubator.com
+49 231/586 873 80
newcubator GmbH
Bödekerstraße 22
30161 Hannover
hannover@newcubator.com
+49 511/957 313 00