Ich arbeite derzeit an einer Webanwendung, bei der wir häufig eine Serverlogik basierend auf der Seite konditionieren müssen, die an den Benutzer zurückgegeben wird.
Jede Seite erhält einen 4-Buchstaben-Seitencode. Diese Seitencodes werden derzeit in einer Klasse als statische Zeichenfolgen aufgeführt:
public class PageCodes {
public static final String FOFP = "FOFP";
public static final String FOMS = "FOMS";
public static final String BKGD = "BKGD";
public static final String ITCO = "ITCO";
public static final String PURF = "PURF";
// etc..
}
Und oft sehen wir im Code Code wie diesen ( 1. Form ):
if (PageCode.PURF.equals(destinationPageCode) || PageCodes.ITCO.equals(destinationPageCode)) {
// some code with no obvious intent
}
if (PageCode.FOFP.equals(destinationPageCode) || PageCodes.FOMS.equals(destinationPageCode)) {
// some other code with no obvious intent either
}
Das ist schrecklich zu lesen, weil es nicht zeigt, welche gemeinsamen Eigenschaften dieser Seiten den Autor des Codes veranlasst haben, sie hier zusammenzustellen. Wir müssen den Code in der if
Verzweigung lesen, um zu verstehen.
Aktuelle Lösung
Diese if
wurden teilweise vereinfacht, indem Listen von Seiten verwendet wurden, die von verschiedenen Personen in verschiedenen Klassen deklariert wurden. Dadurch sieht der Code wie folgt aus ( 2. Form ):
private static final List<String> pagesWithShoppingCart = Collections.unmodifiableList(Arrays.asList(PageCodes.ITCO, PageCodes.PURF));
private static final List<String> flightAvailabilityPages = Collections.unmodifiableList(Arrays.asList(PageCodes.FOMS, PageCodes.FOFP));
// later in the same class
if (pagesWithShoppingCart.contains(destinationPageCode)) {
// some code with no obvious intent
}
if (flightAvailabilityPages.contains(destinationPageCode)) {
// some other code with no obvious intent either
}
... was die Absicht viel besser ausdrückt. Aber...
Aktuelles Problem
Das Problem hierbei ist, dass wir, wenn wir eine Seite hinzufügen, theoretisch die gesamte Codebasis durchgehen müssten, um herauszufinden, ob wir unsere Seite einer if()
oder einer solchen Liste hinzufügen müssen .
Selbst wenn wir alle diese Listen PageCodes
als statische Konstanten in die Klasse verschoben haben, müssen die Entwickler diszipliniert prüfen, ob ihre neue Seite in eine dieser Listen passt, und sie entsprechend hinzufügen.
Neue Lösung
Meine Lösung bestand darin, eine Aufzählung zu erstellen (da es eine endliche bekannte Liste von Seitencodes gibt), in der jede Seite einige Eigenschaften enthält, die wir festlegen müssen:
public enum Page {
FOFP(true, false),
FOMS(true, false),
BKGD(false, false),
PURF(false, true),
ITCO(false, true),
// and so on
private final boolean isAvailabilityPage;
private final boolean hasShoppingCart;
PageCode(boolean isAvailabilityPage, boolean hasShoppingCart) {
// field initialization
}
// getters
}
Dann sieht der bedingte Code jetzt so aus ( 3. Form ):
if (destinationPage.hasShoppingCart()) {
// add some shopping-cart-related data to the response
}
if (destinationPage.isAvailabilityPage()) {
// add some info related to flight availability
}
Welches ist sehr gut lesbar. Wenn jemand Bedarf zusätzlich eine Seite hinzuzufügen, er / sie ist gezwungen , über jedes boolean zu denken und ob diese wahr oder falsch ist für seine neue Seite.
Neues Problem
Ein Problem, das ich sehe, ist, dass es vielleicht 10 Boolesche Werte wie diesen gibt, was den Konstruktor wirklich groß macht und es schwierig sein kann, die Deklaration richtig zu machen, wenn Sie eine Seite hinzufügen. Hat jemand eine bessere Lösung?
false
und dann einen oder zwei ändern (wahrscheinlich den falschen, da es so schwer ist, den Überblick zu behalten). Es gibt keinen perfekten Schutz vor Dummheit, und irgendwann müssen Sie Ihren Entwicklern vertrauen, dass sie das Richtige tun.