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
- Wenn man aus einem Funktion-Namen eine andere Funktion extrahieren kann, ist das ein Kandidat für eine Aufgabe zu viel.
- 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)
zurenderForSuite()
undrenderForSingletest()
- mehr als 3 Argumente sollten nicht genutzt werden oder sehr gut begründet sein (also Ausnahme)
- Sideeffects vermeiden
- Anweisungen und Abfragen trennen
if(set("key"))
if(attributeExists("key")){
setAttribute("key");
}
Wichtiger shortcut: