[JAVA] Eine Sammlung von Mustern, die Sie kennen möchten, um den Code nicht zu komplizieren

Einführung

Ursprünglich einfacher Code wird ebenfalls angehäuft. Durch Hinzufügen oder Ändern von Funktionen, Beheben von Fehlern usw. wird der Code allmählich kompliziert, was zu einer Erhöhung der Korrekturkosten und einer Verringerung der Qualität führt. Dies ist für ein Produkt einer bestimmten Größe ganz natürlich und muss bewusst so gestaltet werden, dass dies verhindert wird.

Hier werden wir die Methoden und Muster vorstellen, die uns normalerweise bekannt sind, um den Code nicht zu komplizieren. (Große Menge an DDD- und Clean Architecture-Komponenten) Der Code in diesem Artikel ist ebenfalls Java, aber ich denke, Sie können ihn bis zu einem gewissen Grad verstehen, ohne Java zu kennen.

Außerdem ist es lang, weil ich es in einem weiten Bereich geschrieben habe, ohne zusammenhängend zu sein ... Da es sich um einen Ankerlink für jeden Artikel unten handelt, bitte nur den Artikel, an dem Sie interessiert sind.

Warum Getter / Setter nicht gut ist

Besser, wo es um Geschäftslogik geht

Der "Getter" bezieht sich hier auf eine Instanzvariable, auf die von außen verwiesen werden kann. Der Grund für die Beschränkung auf "wo es um Geschäftslogik geht" ist, dass es aufgrund von Rahmenbeschränkungen möglicherweise nicht möglich ist, bedingungslos damit umzugehen.

Klasse mit Getter


public class Employee {
    private String name; //OK, da von außen nicht darauf verwiesen werden kann
    private LocalDate contractDate;
    public int salary; //Öffentliche Instanzvariablen sind verboten, da sie von außen referenziert werden können
    ...

    //Verboten, da Instanzvariablen mit getter von außen referenziert werden können
    public LocalDate getContractDate() {
        return this.contractDate;
    }
}

Der Prozess "getContractDate" in diesem Beispiel "das Vertragsdatum eines Mitarbeiters abrufen" hat keine geschäftliche Bedeutung. Sie wissen nicht, was Sie tun möchten, indem Sie das Vertragsdatum eines Mitarbeiters abrufen. Wurde hier erreicht, um Mitarbeiter anhand des Vertragsdatums zu identifizieren? Handelt es sich um eine Änderung der Mitarbeiterinformationen aufgrund des Vertragsdatums? ?? Und so weiter ist dies allein bedeutungslos geworden. Dies ist gleichbedeutend mit der Verwendung der erfassten Daten, die auf die Benutzerseite übertragen werden, und ist eine Verschiebung des Entwurfs.

Schauen wir uns nun die Seite an, die die Klasse verwendet, in der "Designverschiebung" auftritt.

Die Seite, die die Klasse verwendet, in der "Entwurfsverschiebung" auftritt


int salary;
if (employee.getContractDate().isBefore(LocalDate.now())) {
    //Werden Sie für Vertragsangestellte bezahlt(Es enthält nicht den Tag, aber es gibt Details...)
    salary = employee.salary;
}

Wie oben erwähnt, gelangt die Geschäftslogik zu der Klasse, die "Mitarbeiter" verwenden möchte. Wenn es Klassen gibt, die "Mitarbeiter" in Zukunft für denselben Zweck verwenden möchten, wird überall ein ähnlicher Kopiercode in Massenproduktion hergestellt. Um dies zu verhindern, schreiben Sie die Geschäftslogik direkt in die Klasse, die die unten gezeigten Daten enthält.

Klasse, die Getter verbietet


public class Employee {
    private LocalDate contractDate;
    private int salary;
    ...

    public int calculateSalary() {
        if (this.contractDate.isBefore(LocalDate.now())) {
            return this.salary;
        }
        return 0; //Diese Art der Rückkehr ist nicht gut, aber als Beispiel...
    }
}

Benutzerklasse


int salary = employee.calculateSalary();

Indem Sie getter stoppen und Geschäftslogik in die Klasse schreiben, die die Daten enthält, können Sie die Massenproduktion von Kopiercode verhindern und die Geschäftsregeln kennen, indem Sie sich nur die entsprechende Klasse ansehen.

Setter, wo es um Geschäftslogik geht

Der "Setter" bezieht sich hier auch auf eine Instanzvariable, deren Wert von außen geändert werden kann.

Klasse mit Setter


public class Employee {
    public LocalDate contractDate;  //Öffentliche Instanzvariablen können von außen zugewiesen werden, was verboten ist
    private int salary;
    ...

    //Verboten, da Instanzvariablen mit dem Setter extern zugewiesen werden können
    public void setSalary(int salary) {
        this.salary = salary;
    }
}

Wieder ist die Logik "setSalary", was keine geschäftliche Bedeutung hat, "das Gehalt eines Mitarbeiters zu ändern". Zum Beispiel sollte es eine Methode sein, die den Geschäftsfluss und die Regeln ausdrückt, z. B. "Ich habe sie hinzugefügt, weil ich eine gute Leistung erbracht habe" und "Ich habe sie korrigiert, weil ich einen Fehler bei der Eingabe gemacht habe".

Die Tatsache, dass der Wert durch "Setter" geändert werden kann, bedeutet auch, dass sich der Status ändert, sodass er nicht sicher ist. Insbesondere wenn die Verarbeitung wie unten gezeigt tiefer wird, wird der Zustand, der vom Menschen leicht erkannt werden kann, überschritten und die Lesbarkeit verschlechtert sich.

methodA(Employee employee)
  └ methodB(Employee employee)
    └ methodC(Employee employee)
      └ methodD(Employee employee) <-Es ist nicht möglich, den Mitarbeiterstatus hier neu zu schreiben!Kann nicht aufholen!
        └ methodE(Employee employee)

Vermeiden Sie Setter mit vollständigen Konstruktoren und unveränderlichen Objekten

Vollständiger Konstruktor: Vollständiger Konstruktor

Ein vollständiger Konstruktor bedeutet "Fixieren Sie die Werte aller Instanzvariablen mit dem Konstruktor". Insbesondere in Klassen, die sich mit Geschäftsregeln befassen, garantieren wir, dass der Konstruktor die folgenden Zustände erstellt.

Definieren Sie als einfaches Beispiel eine Klasse, die die Geschäftsregel ausdrückt, dass "Mitarbeiter immer einen Vertrag haben (es gibt ein Vertragsdatum) und sie können bis zu 3 Monate im Voraus einen Vertrag abschließen".

public class Employee {
    private LocalDate contractDate;

    public Employee(LocalDate contractDate) {
        if (contractDate == null) {
            throw new IllegalArgumentException("Vertragsdatum ist erforderlich");
        }
        LocalDate currentDate = LocalDate.now();
        if (contractDate.isAfter(currentDate.plusMonths(3))) {
            throw new IllegalArgumentException("Vertragsdaten über 3 Monate im Voraus sind ungültig");
        }
        this.contractDate = contractDate;
    }
}

Indem der Konstruktor so gestaltet wird, dass das Vertragsdatum des Mitarbeiters unbedingt erforderlich ist und das Datum, das 3 Monate im Voraus überschreitet, auf diese Weise eingeschränkt wird, werden die Einschränkungen der Geschäftsregeln bei Verwendung dieser Instanz zwangsweise eingehalten. Es ist auch garantiert eine sichere Instanz. Darüber hinaus wird es zu einer sicheren und vorhersehbaren Instanz, unabhängig vom Wert, und der Benutzer kann sie verwenden, ohne sich um unnötige Dinge kümmern zu müssen.

Nach dem einmaligen Erstellen einer Instanz verringern Vorgänge wie das Ändern des Status oder das schrittweise Zusammenstellen einiger Felder die Sicherheit und Lesbarkeit. Die Instanzgenerierung sollte immer mit atomaren Operationen abgeschlossen werden.

Statische Factory-Methode anstelle des Konstruktors

Einführung statischer Factory-Methoden in Bezug auf Konstruktoren. Möglicherweise möchten Sie mehrere Konstruktoren erstellen, die in Bezug auf Geschäftsregeln überlastet sind. Wie im Kommentar des folgenden Beispiels beschrieben, ist es wie "dieser Konstruktor im Fall von ○○" und "dieser Konstruktor im Fall von △△".

public class SearchDateTime {
   private LocalDate date;
   private LocalTime time;

    //Ich möchte, dass Sie diesen Konstruktor nur am Tag verwenden...
    public SearchDateTime(LocalDate date, LocalTime time) {
        this.date = date;
        this.time = time;
    }

    //Ich möchte, dass Sie den Konstruktor nur am Tag verwenden...
    public SearchDateTime() {
        this.date = LocalDate.now();
        this.time = LocalTime.now();
        //Es spielt keine Rolle, aber lassen Sie uns den Konstruktor verketten!
        // this(LocalDate.now(), LocalTime.now());
    }
}

Wenn es für das oben Gesagte mehrere Konstruktoren gibt, wird dies im Kommentar geschrieben, aber es ist für den Benutzer schwierig zu verstehen, welchen er verwenden soll, allein aufgrund des Unterschieds in den Argumenten.

Die Lösung hierfür ist der Titel "Statische Factory-Methode anstelle des Konstruktors". Bereiten Sie eine statische Factory-Methode vor, die für jede Verwendung wie unten gezeigt benannt ist.

public class SearchDateTime {
   private LocalDate date;
   private LocalTime time;

    public static SearchDateTime of(LocalDate date, LocalTime time) {
        return new SearchDateTime(date, time);
    }

    public static SearchDateTime ofToday() {
        return new SearchDateTime(LocalDate.now(), LocalTime.now());
    }

    //Der Konstruktor wird privat gemacht und nicht nach außen ausgesetzt
    private SearchDateTime(LocalDate date, LocalTime time) {
        this.date = date;
        this.time = time;
    }
}

Der ursprüngliche Konstruktor reduziert die Sichtbarkeit auf "privat" und verhindert, dass sie direkt von außen verwendet wird. Der Vorteil statischer Factory-Methoden besteht darin, dass sie ** benannt ** werden können. Indem Sie den Namen explizit angeben, können Sie dem Benutzer Ihre Absicht mitteilen, ohne ihn mehrdeutig zu machen. Als weiteres Anwendungsfallbeispiel ist es außerdem effektiv, die von der Administratorrolle und der normalen Rolle zu bedienenden Objekte einzuschränken und die Vorgänge zu klären, die nicht durch die Benennung und den Argumenttyp verwechselt werden dürfen.

Unveränderliches Objekt

Sie können die Sicherheit erhöhen, indem Sie sicherstellen, dass der Wert nach dem Festlegen nicht geändert wird. Durch Definieren des Modifikators "final" für die Instanzvariable ändert sich der Wert nach der Initialisierung im Konstruktor nicht.

public class Employee {
    //Fügen Sie allen Instanzvariablen den letzten Modifikator hinzu
    private final String name;
    private final LocalDate contractDate;
    private final int salary;

    public Employee(String name, LocalDate contractDate, int salary) {
        this.name = name;
        this.contractDate = contractDate;
        this.salary = salary;
    }

    public void addSalary(int salary) {
        this.salary += salary //Kompilierungsfehler!!
    }
}

Der Hauptzweck des Beendens von Setter besteht darin, es zu einem vollständigen Konstruktor und unveränderlichen Objekt zu machen, damit Sie sich keine Gedanken über Statusänderungen machen müssen. Da die Menge an Informationen, an die sich eine Person vorübergehend erinnern kann, gering ist, ist es wichtig, die Menge an Bedenken so weit wie möglich zu reduzieren.

Jetzt haben Sie ein unveränderliches Objekt mit einem unveränderlichen Wert. Wenn Sie den Wert jedoch ändern möchten, erstellen Sie eine neue Instanz und geben Sie sie zurück. Es ändert seinen eigenen Wert nicht.

public class Employee {
    private final String name;
    private final LocalDate contractDate;
    private final int salary;
    ...

    //Vertragsdatum und Gehalt neu vergeben und ändern
    public Employee contractRenewal(int salary) {
        return new Employee(this.name, LocalDate.now(), salary);
    }
}

//Benutzerseite
Employee employee = new Employee(...);
Employee extendedEmployee = employee.contractRenewal(200000); //Als separate Instanz behandeln.

Fragen Sie nicht nach Demetels Gesetz (Sagen Sie, fragen Sie nicht!)

Sowohl "Demeter's Law" als auch "Don't Ask" sind Gestaltungsprinzipien im Zusammenhang mit dem Verstecken von Informationen. Schauen wir uns zunächst ein Bild eines Beispiels an, in dem dieses Konstruktionsprinzip nicht eingehalten wird, und ein Beispiel, in dem es eingehalten wird.

Beispiele für die Nichtbeachtung von Gestaltungsprinzipien

No good.png

Beispiel für die Einhaltung von Gestaltungsprinzipien

good.png

Sie können sehen, dass Sie eine schöne V-Form erhalten, wenn Sie diesem Designprinzip folgen.

Schauen wir uns als nächstes den Code an. Als einfaches Beispiel zeigt es die Logik, "den Verkaufspreis eines Produkts mit einer Gutscheingebühr zu ermitteln".

Fragen Sie nicht nach Demeters Gesetz Benutzerlogik, die dem Befehl nicht folgt


Product product = new Product(something);
int sellingPrice;
if (product.price.couponExpiration.isAfore(LocalDate.now())) {
    //Gibt den Gutscheinpreis des Artikels zurück, wenn der Gutschein gültig ist(Dies beinhaltet auch nicht den Tag, aber es gibt Details...)
    sellingPrice = product.price.couponValue;
} else {
    //Produktpreis zurückgeben, wenn das Ablaufdatum des Gutscheins ungültig ist
    sellingPrice = product.price.value;
}

Oben wird eine Anfrage von if in "product.price.couponExpiration" generiert, um das Ablaufdatum des Gutscheins zu bestimmen. Wir greifen auch auf den "Preis" zu, der dem "Produkt" gehört.

Der Code, der durch Anwenden von "Demeters Gesetz" und "Nicht fragen" auf diesen Code verbessert wurde, lautet wie folgt.

Demeters Gesetz und nicht fragen, Benutzerlogik


Product product = new Product(something);
int sellingPrice = product.sellingPrice();

Die obige "Benutzerlogik, in der Demeters Gesetz und der Befehl, nicht zu fragen", wird mit einer Anweisungszeile vervollständigt. Der Benutzer erhält nur ** Mindestkenntnisse ** und muss nur den Befehl "Find the Selling Price" aufrufen.

Die "Produkt" -Klasse, die dieses "Demeter-Gesetz und nicht fragen" enthält, lautet wie folgt.

public class Product {
    private Price price;
    ...
    int sellingPrice() {
      return price.sellingPrice();
    }
}

class Price {
    private int value;
    private int couponValue;
    private LocalDate couponExpiration;
    ...
    int sellingPrice() {
        if expirationDate.isAfore(LocalDate.now()) {
            return couponValue;
        }
        return value;
    }
}

Ursprünglich ist die Klasse "Preis" für die Beurteilungsverarbeitung zuständig, z. B. für die Verzweigung auf der Benutzerseite, und sie ist in der Klasse "Produkt" zusammengefasst. Geschäftslogik wie Berechnung und Beurteilung wird ** von der Klasse behandelt, die die Daten hat **. Darüber hinaus ist die Klasse "Preis" als paketprivat definiert, und die Methode "verkaufspreis" ist ebenfalls paketprivat. Mit anderen Worten, diese Klasse und Methode können von der Benutzerseite aus nicht gesehen werden (unter der Annahme eines anderen Pakets), und eine direkte Ausführung ist nicht zulässig. Auf diese Weise können Sie die ** Wissensexposition ** zwangsweise reduzieren, die Abhängigkeit verringern und lose koppeln.

Nach Demeters Gesetz ist dies das Bild. product.png

Interessentrennung: Trennung von Bedenken (SoC)

In MVC und Layered Architecture wird oft über die Trennung von Interesse gesprochen, aber es ist ein Prinzip, das ich unabhängig von der Granularität beachten möchte. Angenommen, Sie haben eine Klasse, die sich mit "Mitarbeitern" befasst. In dieser "Mitarbeiter" -Klasse sind wir nicht besorgt darüber, wie Sie benachrichtigen sollen, wenn ein Geschäftsfehler auftritt. Wenn es sich um eine API handelt, sollte die Nachricht in einem Format wie JSON gepackt sein. Wenn ein Bildschirm wie eine Website angezeigt wird, sollte er geändert und ausgegeben werden, damit der Benutzer ihn leicht erkennen kann. In dieser Klasse "Mitarbeiter" sind "das Auftreten eines Geschäftsfehlers" und "der Inhalt des Geschäftsfehlers (Fehlermeldung)" die Bedenken, die bekannt sein sollten. Wie es ausgegeben und geändert wird, ist ein Anliegen einer anderen Klasse (z. B. Präsentationsebene). Wenn die Bildschirmverarbeitung auf der Benutzerseite in die Klasse "Mitarbeiter" geschrieben ist, ohne die oben genannte Interessentrennung zu kennen, sollte die Klasse "Mitarbeiter" nicht relevant sein, wenn sich die Bildschirmausgabemethode ändert. Wird auch korrigiert, wodurch der Einflussbereich erweitert wird. Es verstößt auch gegen eines der SOLID-Prinzipien, das ** Prinzip der Einzelverantwortung **. https://qiita.com/UWControl/items/98671f53120ae47ff93a

Durch die Trennung der Interessen nach Rollen, die Festlegung und Abgrenzung der Verantwortungsgrenzen ist es möglich, lose gekoppelte und sichere Anwendungen mit geringerer Abhängigkeit von außen zu entwerfen. Ist möglich. Dies führt auch zu einer Verringerung der ** Wissensexposition **.

Abhängigkeiten und ihre Richtungen

TL;DR Weil es ein bisschen lang ist.

Grundsätze zum Umgang mit Komponentenassoziationen

Eine "Komponente" ist ein Modul oder eine Einheit aus Glas oder Edelstein. Es ist jedoch nicht auf Komponenten beschränkt, sondern sollte auf jedes Objekt angewendet werden. Daher basiert die Erklärung hier auf der Klasse.

** Prinzip der azyklischen Abhängigkeiten (ADP) **

Das Komponentenabhängigkeitsdiagramm darf keine zirkulären Abhängigkeiten aufweisen

Es gibt ein Prinzip. Es sollte so gestaltet sein, dass es in keiner Struktur eine zirkuläre Abhängigkeit gibt, nicht nur in "Komponenten". Stellen Sie sicher, dass die Abhängigkeit nach innen gerichtet ist und nur von einer Richtung ohne Zirkulation abhängt. Es ist wichtig, das Äußere nicht von innen zu kennen und das Wissen und die Regeln von außen nicht nach innen zu bringen.

** Prinzip der Stabilitätsabhängigkeit: Prinzip der stabilen Abhängigkeiten (SDP) **

Abhängig von der Richtung der hohen Stabilität

In Bezug auf Klassen ist es umso stabiler, je weniger Klassen davon abhängen. Es ist auch stabil genug, um von seiner eigenen Klasse abhängig zu sein. Insbesondere aus dem letzteren Grund (je stabiler es von seiner eigenen Klasse abhängt) ist der Effekt der Änderung groß und es ist schwierig, sie zu ändern, daher muss sie stabil sein. (Abhängig von der Sprache denke ich, dass die Anzahl der Importe, Anforderungen und Einschlüsse ein bestimmter Standard sein wird.)

Daher sollte eine Klasse, die sich ändern soll, nicht von einer Klasse abhängig sein, die schwer zu ändern ist.

** Prinzip der Stabilität und Abstraktionsäquivalenz: Stabiles Abstraktionsprinzip (SAP) **

Der Abstraktionsgrad einer Komponente muss mit ihrer Stabilität vergleichbar sein

Das Prinzip ist, dass hochstabile Komponenten auch sehr abstrakt sein sollten und dass eine hohe Stabilität die Expansion nicht beeinträchtigen sollte. Umgekehrt sollten weniger stabile Komponenten spezifischer sein. Dies liegt daran, dass die geringe Stabilität das Ändern des darin enthaltenen Codes erleichtert.

Das "Prinzip der Stabilitätsabhängigkeit (SDP)" sollte von der Richtung höherer Stabilität abhängen, und das "Prinzip der Äquivalenz von Stabilität und Abstraktion (SAP)" bedeutet, dass die Stabilität proportional zum Abstraktionsgrad sein sollte. Mit anderen Worten, ** sollte von der Richtung der höheren Abstraktion ** abhängen.

Prinzip der Abhängigkeitsinversion (DIP)

Es ist notwendig, die Richtung der Abhängigkeit zu ändern, um das "Prinzip der Stabilitätsabhängigkeit (SDP)" und das "Prinzip der Äquivalenz von Stabilität und Abstraktion (SAP)" zu realisieren. Durch die Einführung einer Schnittstelle können wir die Richtung der Abhängigkeiten umkehren und dies erreichen.

Lassen Sie uns einen Blick darauf werfen, bevor Sie DIP anwenden. before_dependency_inversion_principle.png Im obigen "Vor der Änderung" hängt die "stabile Klasse" von der "instabilen Klasse mit vielen Modifikationen" ab. Wenn sich also die letztere Klasse ändert, wirkt sich dies auf die erstere Klasse aus. .. Im Einzelnen ist das Folgende ein Beispiel.

Hier ist ein Zustand, in dem die Abhängigkeit umgekehrt wird und das Problem für ein solches Problem gelöst ist.

dependency_inversion_principle.png

Durch die Verwendung der Abstraktion über die Schnittstelle sind "instabile Klassen mit vielen Modifikationen" nicht mehr direkt abhängig. Unabhängig davon, wie oft Sie eine "instabile Klasse mit vielen Änderungen" reparieren, müssen Sie keine "stabile Klasse" ändern, solange Sie die Schnittstelle erben.

Was hier wichtig ist, wird auch in "Prinzip der Stabilitätsabhängigkeit (SDP)" und "Prinzip der Stabilität und Abstraktionsäquivalenz (SAP)" beschrieben, aber die abhängige abstrakte Klasse muss äußerst stabil sein. nicht. Daher ist das Design dieses Teils wichtig.

Bei der tatsächlichen Anwendung des Dependency Reversal Principle (DIP)

Persönlich halte ich es nicht für notwendig, dieses Prinzip der Abhängigkeitsumkehr (DIP) um jeden Preis anzuwenden. Insbesondere im Fall einer einfachen Struktur kann es derzeit schwierig sein, ein einschichtiges abstraktes Objekt einzuschließen.

Als konkretes Beispiel denke ich, dass es viele Fälle gibt, in denen Sie denken, "Ich möchte nicht von dieser Klasse abhängig sein", wenn Sie die Abhängigkeitsrichtung umkehren.

Als Projekt sollten Sie die Richtung bis zu einem gewissen Grad im Voraus festlegen, z. B. "Wie weit können Sie vom Framework gesperrt werden".

Gut trocken und schlecht trocken

Im Allgemeinen ist "Duplikat ist schlecht" im Quellcode. "Wiederholen Sie sich nicht" Dies ist das DRY-Prinzip.

Angenommen, Sie haben mehrere Anwendungsfälle mit ähnlichen Bildschirmkonfigurationen. Nehmen wir zu Beginn der Herstellung an, dass dieselbe Verarbeitung standardisiert ist, um sie TROCKEN zu machen. Obwohl es zu diesem Zeitpunkt kein Problem gab, sind die Anforderungen für jeden Anwendungsfall unterschiedlich, sodass die ** gemeinsame Logik ** für jeden Benutzer einen if-Zweig mit seinen eigenen individuellen Absichten hat, und einige Jahre später. Kann sich in eine aufgeblähte ** gemeinsame Logik ** voller Urteilszweige verwandeln.

Um dies zu vermeiden, müssen die Problembereiche (Domänen) geklärt werden, mit denen sich das Produkt befasst, z. B. die Bereiche, an denen das Unternehmen interessiert ist. Darüber hinaus müssen Sie sorgfältig feststellen, ob es ** versehentlich ** oder ** wirklich dupliziert ** ist. Im ersteren Fall muss es nicht trocken gemacht werden, da es nur ** versehentlich dupliziert ** wird.

Dies ist ein Problem, das eher auftritt, wenn das Produkt größer wird. Es ist besonders wichtig zu beachten, dass Klassen, die Geschäftsregeln behandeln, Namen wie "common" und "base" haben können.

Name wichtig

Aus irgendeinem Grund ist es die ** wichtigste Angelegenheit ** für die Programmierung. Der Inhalt, der sich auf den Namen bezieht, wird in vielen anderen Artikeln erwähnt, daher werde ich nur einen Überblick geben, aber ich denke, die folgenden Bücher werden sehr hilfreich sein.

Danach werde ich die Benennung von "dem Teil, der Geschäftsregeln behandelt" zusammenfassen.

In DDD gibt es "strategisches Design" und "taktisches Design".

Wichtig ist, dass "der richtige Name nur festgelegt werden kann, wenn das strategische Design festgelegt ist". Da ich es in DRY erwähnt habe, werde ich es erneut veröffentlichen. Was ist jedoch der Bereich, an dem unser Unternehmen interessiert ist, und wenn es etwas gibt, das in diesen Bereich usw. unterteilt werden kann, wird der vom Produkt behandelte Problembereich (Domäne) beschrieben. Die Arbeit, den Paketnamen und den Klassennamen danach zu klären und zu entscheiden, ist für eine gute Benennung notwendig.

Schließlich

Es ist wichtig, die bisher beschriebenen Methoden und Muster nicht einmal anzuwenden, sondern immer wieder zurückzublicken, wenn sie nicht passen. Zu dieser Zeit denke ich, dass selbst wenn Sie denken, dass Sie guten Code geschrieben haben, wenn Sie später darauf zurückblicken, es ein schlechter Code sein wird. Code, der sich eines solchen Designs bewusst war, sollte jedoch viel billiger zu modifizieren und einfacher zu ändern sein als zuvor. Es ist wichtig, ständig Verbesserungen vorzunehmen und kleine Refactorings zu wiederholen.

Recommended Posts

Eine Sammlung von Mustern, die Sie kennen möchten, um den Code nicht zu komplizieren
Ein Beispiel für kleine Arbeiten, bei denen Sie den Definitionswert nach der Umgebung aufteilen möchten, sich dessen jedoch nicht bewusst sein möchten
7 Dinge, die du behalten sollst, damit es kein verdammter Code wird
Um auf einfach zu lesenden Code zu achten
Ein Memo, wenn Sie den Zeitteil des Kalenders löschen möchten
Die Geschichte der Einführung von Gradle als Nachrüstung eines bestehenden Systems, das keine Pakete verwaltet
Grundregeln zum Schreiben von einfach zu lesendem Code
Selbst in Java möchte ich true mit == 1 && a == 2 && a == 3 ausgeben (graue Magie, die weniger schwarze Magie ist)
[Active Admin] Ich möchte den Umfang der Sammlung angeben, die in select_box angezeigt werden soll
Wenn Sie den Wortlaut ändern möchten, der angezeigt werden soll, wenn Sie ein Auswahlfeld aus enum erstellen
Ein Memo des Programms, mit dem Sie feststellen können, dass die Wahrscheinlichkeit eines Würfelwurfs etwa 1/6 beträgt
Dinge, die Sie beim Schreiben von Code in Java beachten sollten
Verschwenderische Verarbeitung von Sammlungen - ich möchte Ihnen die Möglichkeit geben, guten Code zu schreiben. 5 [C # Refactoring Sample]
Die Geschichte von Collectors.groupingBy, die ich für die Nachwelt behalten möchte
Eine Geschichte, die mithilfe von Polymorphismus sauber implementiert werden kann, wenn Sie zwei Datentypen in einer Tabelle ausdrücken möchten
Erstellen einer ArrayList, mit der Sie die Koordinaten einer zweidimensionalen Ebene eingeben und abrufen können
Entspricht "Fehler, dass die Basisauthentifizierung nicht bestanden wird" im Testcode "Die Geschichte, die nicht gemacht werden konnte".
[Java] Es kann glücklich sein, wenn der Rückgabewert der Methode, die null zurückgibt, Optional <> ist
[Java] Äquivalenzvergleich, bei dem Anfänger beim Vergleich von Zeichenfolgen fehlschlagen. Möglicherweise sind Sie sich des Fehlers nicht einmal bewusst! ??
[RSpec] Wenn Sie die Instanzvariable des Controllers im Test verwenden möchten [Zuweisungen wird nicht empfohlen]
Über die Angelegenheit, die tendenziell mit ARG von Dockerfile verwechselt wird, einem mehrstufigen Build
Um kein statischer Onkel zu sein
Ein Memo, das nüchtern von der Anfrage nach mehrteiligen / Formulardaten abhängig war
So interagieren Sie mit einem Server, der die App nicht zum Absturz bringt
Eine Sammlung von Phrasen, die das "unterschiedliche Gefühl" von Java und JavaScript beeindruckt
Für Sie, die beklagen, dass die Konvertierung von JODConverter + LibreOffice langsam ist
Beachten Sie, dass VS Code + JUnit 5 unter Windows 10 verwendet werden kann
Ich möchte, dass Sie Enum # name () für den Schlüssel von SharedPreference verwenden
Wenn Sie die Testabdeckung privater Methoden in JUnit erfüllen möchten
So erstellen Sie eine Route direkt aus der URL, die Sie + α angeben möchten
[Android] Ich möchte einen ViewPager erstellen, der für Tutorials verwendet werden kann
Stellen Sie sich RxJava als eine Bibliothek vor, die das Schreiben von asynchroner Verarbeitung erleichtert
Möglicherweise möchten Sie die Methode remove in ArrayList nicht sehr oft verwenden
Fassen Sie den Lebenszyklus von Java-Objekten zusammen, die bei der Android-Entwicklung berücksichtigt werden müssen
Ich möchte, dass Sie Scala vorerst als besseres Java verwenden
Ich möchte rekursiv die Oberklasse und die Schnittstelle einer bestimmten Klasse erhalten
Speichern Sie die Daten, die von JavaFX gelesen werden können, als PNG
[Java-Tool] Ein nützliches Tool, wenn Sie das IPMSG-Protokoll von PC-A regelmäßig an den angegebenen PC senden möchten.
Ich möchte, dass Sie die Geschichte erzählen, dass der Fehler behoben wurde, als Sie das Ladegerät in die Ecke Ihres Kopfes gestochen haben
Ich möchte die MD5-Prüfsumme einer Datei in Java finden und das Ergebnis als Zeichenfolge in hexadezimaler Notation erhalten.
Eine Geschichte, dass eine Person, die ein solides iOS gemacht hat, möglicherweise von der Implementierung von Listener abhängig ist, wenn sie zu Android wechselt
Ich habe Docker als Anfänger für mein Portfolio verwendet, daher hoffe ich, dass sogar 1 mm für jemanden hilfreich ist.