CodeGym /Java-Blog /Random-DE /Codierungsregeln: Von der Erstellung eines Systems bis zu...
John Squirrels
Level 41
San Francisco

Codierungsregeln: Von der Erstellung eines Systems bis zur Arbeit mit Objekten

Veröffentlicht in der Gruppe Random-DE
Guten Tag alle zusammen! Heute möchten wir mit Ihnen über das Schreiben von gutem Code sprechen. Natürlich möchte nicht jeder sofort Bücher wie Clean Code durchkauen, da sie zwar reichlich Informationen enthalten, aber zunächst nicht viel klar ist. Und wenn Sie mit dem Lesen fertig sind, vernichten Sie möglicherweise Ihre ganze Lust am Programmieren. In Anbetracht all dessen möchte ich Ihnen heute einen kleinen Leitfaden (eine kleine Reihe von Empfehlungen) zum Schreiben von besserem Code zur Verfügung stellen. In diesem Artikel gehen wir die grundlegenden Regeln und Konzepte im Zusammenhang mit der Erstellung eines Systems und der Arbeit mit Schnittstellen, Klassen und Objekten durch. Das Lesen dieses Artikels wird nicht viel Zeit in Anspruch nehmen und Sie hoffentlich nicht langweilen. Ich arbeite mich von oben nach unten vor, also von der allgemeinen Struktur einer Anwendung bis zu den engeren Details. Codierungsregeln: Von der Erstellung eines Systems bis zur Arbeit mit Objekten – 1

Systeme

Die folgenden Eigenschaften sind im Allgemeinen wünschenswerte Eigenschaften eines Systems:
  • Minimale Komplexität. Zu komplizierte Projekte müssen vermieden werden. Das Wichtigste ist Einfachheit und Klarheit (einfacher = besser).
  • Einfache Wartung. Wenn Sie eine Anwendung erstellen, müssen Sie bedenken, dass diese gewartet werden muss (auch wenn Sie persönlich nicht für die Wartung verantwortlich sind). Das bedeutet, dass der Code klar und offensichtlich sein muss.
  • Lose Kopplung. Das bedeutet, dass wir die Anzahl der Abhängigkeiten zwischen verschiedenen Teilen des Programms minimieren (wodurch wir die Einhaltung der OOP-Prinzipien maximieren).
  • Wiederverwendbarkeit. Wir entwerfen unser System mit der Möglichkeit, Komponenten in anderen Anwendungen wiederzuverwenden.
  • Portabilität. Es sollte einfach sein, ein System an eine andere Umgebung anzupassen.
  • Einheitlicher Stil. Wir gestalten unser System mit einem einheitlichen Stil in seinen verschiedenen Komponenten.
  • Erweiterbarkeit (Skalierbarkeit). Wir können das System verbessern, ohne seine Grundstruktur zu verletzen (das Hinzufügen oder Ändern einer Komponente sollte sich nicht auf alle anderen auswirken).
Es ist praktisch unmöglich, eine Anwendung zu erstellen, die keine Änderungen oder neue Funktionen erfordert. Wir müssen ständig neue Teile hinzufügen, um unserer Idee zu helfen, mit der Zeit Schritt zu halten. Hier kommt die Skalierbarkeit ins Spiel. Unter Skalierbarkeit versteht man im Wesentlichen die Erweiterung der Anwendung, das Hinzufügen neuer Funktionen und das Arbeiten mit mehr Ressourcen (oder mit anderen Worten: mit einer größeren Last). Mit anderen Worten: Um das Hinzufügen neuer Logik zu erleichtern, halten wir uns an einige Regeln, wie z. B. die Reduzierung der Systemkopplung durch Erhöhung der Modularität.Codierungsregeln: Von der Erstellung eines Systems bis zur Arbeit mit Objekten – 2

Bildquelle

Phasen des Entwurfs eines Systems

  1. Software System. Entwerfen Sie die Anwendung insgesamt.
  2. Aufteilung in Subsysteme/Pakete. Definieren Sie logisch unterschiedliche Teile und definieren Sie die Regeln für die Interaktion zwischen ihnen.
  3. Einteilung von Subsystemen in Klassen. Teilen Sie Teile des Systems in bestimmte Klassen und Schnittstellen ein und definieren Sie die Interaktion zwischen ihnen.
  4. Einteilung von Klassen in Methoden. Erstellen Sie eine vollständige Definition der notwendigen Methoden für eine Klasse, basierend auf der ihr zugewiesenen Verantwortung.
  5. Methodendesign. Erstellen Sie eine detaillierte Definition der Funktionalität einzelner Methoden.
Normalerweise kümmern sich normale Entwickler um diesen Entwurf, während sich der Architekt der Anwendung um die oben beschriebenen Punkte kümmert.

Allgemeine Prinzipien und Konzepte des Systemdesigns

Verzögerte Initialisierung. Bei dieser Programmiersprache verschwendet die Anwendung keine Zeit mit der Erstellung eines Objekts, bis es tatsächlich verwendet wird. Dies beschleunigt den Initialisierungsprozess und reduziert die Belastung des Garbage Collectors. Allerdings sollte man damit nicht zu weit gehen, denn das kann gegen das Prinzip der Modularität verstoßen. Vielleicht lohnt es sich, alle Konstruktionsinstanzen in einen bestimmten Teil zu verschieben, beispielsweise in die Hauptmethode oder in eine Factory- Klasse. Ein Merkmal von gutem Code ist das Fehlen sich wiederholender Standardcodes. In der Regel wird solcher Code in einer separaten Klasse abgelegt, damit er bei Bedarf aufgerufen werden kann.

AOP

Hervorheben möchte ich auch die aspektorientierte Programmierung. Bei diesem Programmierparadigma geht es vor allem um die Einführung transparenter Logik. Das heißt, sich wiederholender Code wird in Klassen (Aspekte) eingeteilt und aufgerufen, wenn bestimmte Bedingungen erfüllt sind. Zum Beispiel beim Aufrufen einer Methode mit einem bestimmten Namen oder beim Zugriff auf eine Variable eines bestimmten Typs. Manchmal können Aspekte verwirrend sein, da nicht sofort klar ist, woher der Code aufgerufen wird, aber es handelt sich dennoch um eine sehr nützliche Funktionalität. Vor allem beim Caching oder Logging. Wir fügen diese Funktionalität hinzu, ohne den gewöhnlichen Klassen zusätzliche Logik hinzuzufügen. Die vier Regeln von Kent Beck für eine einfache Architektur:
  1. Ausdruckskraft – Die Absicht einer Klasse sollte klar zum Ausdruck gebracht werden. Dies wird durch die richtige Benennung, geringe Größe und die Einhaltung des Prinzips der Einzelverantwortung erreicht (auf das wir weiter unten näher eingehen werden).
  2. Mindestanzahl an Kursen und Methoden – In Ihrem Wunsch, die Kurse so klein und eng fokussiert wie möglich zu gestalten, können Sie zu weit gehen (was zum Anti-Pattern der Shotgun-Chirurgie führt). Dieses Prinzip erfordert, das System kompakt zu halten und nicht zu weit zu gehen, indem für jede mögliche Aktion eine eigene Klasse erstellt wird.
  3. Keine Duplizierung – Doppelter Code, der Verwirrung stiftet und auf ein suboptimales Systemdesign hinweist, wird extrahiert und an einen separaten Speicherort verschoben.
  4. Führt alle Tests durch – Ein System, das alle Tests besteht, ist überschaubar. Jede Änderung könnte dazu führen, dass ein Test fehlschlägt, was uns zeigt, dass unsere Änderung in der internen Logik einer Methode auch das Verhalten des Systems auf unerwartete Weise verändert.

SOLIDE

Beim Entwurf eines Systems sind die bekannten SOLID-Prinzipien eine Überlegung wert:

S (Einzelverantwortung), O (offen-geschlossen), L (Liskov-Substitution), I (Schnittstellentrennung), D (Abhängigkeitsumkehr).

Wir werden nicht auf jedes einzelne Prinzip näher eingehen. Das würde den Rahmen dieses Artikels ein wenig sprengen, aber Sie können hier mehr lesen .

Schnittstelle

Einer der vielleicht wichtigsten Schritte bei der Erstellung einer gut gestalteten Klasse ist die Erstellung einer gut gestalteten Schnittstelle, die eine gute Abstraktion darstellt, die Implementierungsdetails der Klasse verbirgt und gleichzeitig eine Gruppe von Methoden präsentiert, die eindeutig miteinander konsistent sind. Werfen wir einen genaueren Blick auf eines der SOLID-Prinzipien – Schnittstellentrennung: Clients (Klassen) sollten keine unnötigen Methoden implementieren, die sie nicht verwenden. Mit anderen Worten: Wenn es darum geht, eine Schnittstelle mit der geringsten Anzahl von Methoden zu erstellen, die darauf abzielen, die einzige Aufgabe der Schnittstelle auszuführen (was meiner Meinung nach dem Prinzip der Einzelverantwortung sehr ähnlich ist), ist es besser, stattdessen ein paar kleinere Methoden zu erstellen einer aufgeblähten Schnittstelle. Glücklicherweise kann eine Klasse mehr als eine Schnittstelle implementieren. Denken Sie daran, Ihre Schnittstellen richtig zu benennen: Der Name sollte die zugewiesene Aufgabe so genau wie möglich widerspiegeln. Und je kürzer es ist, desto weniger Verwirrung wird es natürlich verursachen. Dokumentationskommentare werden normalerweise auf Schnittstellenebene geschrieben. Diese Kommentare enthalten Details darüber, was jede Methode tun soll, welche Argumente sie akzeptiert und was sie zurückgibt.

Klasse

Codierungsregeln: Von der Erstellung eines Systems bis zur Arbeit mit Objekten – 3

Bildquelle

Werfen wir einen Blick darauf, wie der Unterricht intern organisiert ist. Oder besser gesagt, einige Perspektiven und Regeln, die beim Schreiben von Kursen beachtet werden sollten. In der Regel sollte eine Klasse mit einer Liste von Variablen in einer bestimmten Reihenfolge beginnen:
  1. öffentliche statische Konstanten;
  2. private statische Konstanten;
  3. private Instanzvariablen.
Als nächstes kommen die verschiedenen Konstruktoren, in der Reihenfolge von denen mit den wenigsten Argumenten zu denen mit den meisten. Ihnen folgen Methoden von den öffentlichsten bis zu den privatesten. Im Allgemeinen befinden sich ganz unten private Methoden, die die Implementierung einiger Funktionen verbergen, die wir einschränken möchten.

Klassengröße

Jetzt möchte ich über die Größe der Klassen sprechen. Erinnern wir uns an eines der SOLID-Prinzipien – das Prinzip der Einzelverantwortung. Es besagt, dass jedes Objekt nur einen Zweck (Verantwortung) hat und die Logik aller seiner Methoden darauf abzielt, diesen zu erreichen. Dies sagt uns, dass wir große, aufgeblähte Klassen vermeiden sollen (die eigentlich das Anti-Muster des Gottesobjekts sind), und wenn wir viele Methoden mit allen möglichen unterschiedlichen Logiken in einer Klasse zusammengepfercht haben, müssen wir darüber nachdenken, sie in eine Klasse aufzuteilen ein paar logische Teile (Klassen). Dies wiederum erhöht die Lesbarkeit des Codes, da es nicht lange dauern wird, den Zweck jeder Methode zu verstehen, wenn wir den ungefähren Zweck einer bestimmten Klasse kennen. Behalten Sie außerdem den Klassennamen im Auge, der die darin enthaltene Logik widerspiegeln sollte. Wenn wir beispielsweise eine Klasse mit mehr als 20 Wörtern im Namen haben, Wir müssen über Refactoring nachdenken. Jede Klasse mit Selbstachtung sollte nicht so viele interne Variablen haben. Tatsächlich arbeitet jede Methode mit einer oder mehreren davon und sorgt so für viel Zusammenhalt innerhalb der Klasse (was genau so ist, wie es sein sollte, da die Klasse ein einheitliches Ganzes sein sollte). Folglich führt die Erhöhung des Zusammenhalts einer Klasse zu einer Verringerung der Klassengröße, und natürlich nimmt die Anzahl der Klassen zu. Für manche Leute ist das ärgerlich, da Sie sich mehr in den Klassendateien umsehen müssen, um zu sehen, wie eine bestimmte große Aufgabe funktioniert. Darüber hinaus ist jede Klasse ein kleines Modul, das nur minimale Beziehungen zu anderen haben sollte. Diese Isolation reduziert die Anzahl der Änderungen, die wir vornehmen müssen, wenn wir einer Klasse zusätzliche Logik hinzufügen. Jede Methode arbeitet mit einer oder mehreren davon und sorgt so für viel Zusammenhalt innerhalb der Klasse (was genau so ist, wie es sein sollte, da die Klasse ein einheitliches Ganzes sein sollte). Folglich führt die Erhöhung des Zusammenhalts einer Klasse zu einer Verringerung der Klassengröße, und natürlich nimmt die Anzahl der Klassen zu. Für manche Leute ist das ärgerlich, da Sie sich mehr in den Klassendateien umsehen müssen, um zu sehen, wie eine bestimmte große Aufgabe funktioniert. Darüber hinaus ist jede Klasse ein kleines Modul, das nur minimale Beziehungen zu anderen haben sollte. Diese Isolation reduziert die Anzahl der Änderungen, die wir vornehmen müssen, wenn wir einer Klasse zusätzliche Logik hinzufügen. Jede Methode arbeitet mit einer oder mehreren davon und sorgt so für viel Zusammenhalt innerhalb der Klasse (was genau so ist, wie es sein sollte, da die Klasse ein einheitliches Ganzes sein sollte). Folglich führt die Erhöhung des Zusammenhalts einer Klasse zu einer Verringerung der Klassengröße, und natürlich nimmt die Anzahl der Klassen zu. Für manche Leute ist das ärgerlich, da Sie sich mehr in den Klassendateien umsehen müssen, um zu sehen, wie eine bestimmte große Aufgabe funktioniert. Darüber hinaus ist jede Klasse ein kleines Modul, das nur minimale Beziehungen zu anderen haben sollte. Diese Isolation reduziert die Anzahl der Änderungen, die wir vornehmen müssen, wenn wir einer Klasse zusätzliche Logik hinzufügen. Der Zusammenhalt führt zu einer Verringerung der Klassengröße, und natürlich nimmt die Anzahl der Klassen zu. Für manche Leute ist das ärgerlich, da Sie sich mehr in den Klassendateien umsehen müssen, um zu sehen, wie eine bestimmte große Aufgabe funktioniert. Darüber hinaus ist jede Klasse ein kleines Modul, das nur minimale Beziehungen zu anderen haben sollte. Diese Isolation reduziert die Anzahl der Änderungen, die wir vornehmen müssen, wenn wir einer Klasse zusätzliche Logik hinzufügen. Der Zusammenhalt führt zu einer Verringerung der Klassengröße, und natürlich nimmt die Anzahl der Klassen zu. Für manche Leute ist das ärgerlich, da Sie sich mehr in den Klassendateien umsehen müssen, um zu sehen, wie eine bestimmte große Aufgabe funktioniert. Darüber hinaus ist jede Klasse ein kleines Modul, das nur minimale Beziehungen zu anderen haben sollte. Diese Isolation reduziert die Anzahl der Änderungen, die wir vornehmen müssen, wenn wir einer Klasse zusätzliche Logik hinzufügen.

Objekte

Verkapselung

Hier sprechen wir zunächst über ein OOP-Prinzip: die Kapselung. Das Verstecken der Implementierung bedeutet nicht, eine Methode zum Isolieren von Variablen zu erstellen (den Zugriff durch einzelne Methoden, Getter und Setter gedankenlos einzuschränken, was nicht gut ist, da der Sinn der Kapselung verloren geht). Das Ausblenden des Zugriffs zielt darauf ab, Abstraktionen zu bilden, das heißt, die Klasse stellt gemeinsam genutzte konkrete Methoden bereit, die wir zum Arbeiten mit unseren Daten verwenden. Und der Benutzer muss nicht genau wissen, wie wir mit diesen Daten arbeiten – es funktioniert und das reicht.

Gesetz von Demeter

Wir können auch das Demeter-Gesetz berücksichtigen: Es handelt sich um eine kleine Reihe von Regeln, die bei der Bewältigung der Komplexität auf Klassen- und Methodenebene helfen. Angenommen, wir haben ein Car- Objekt und es verfügt über eine move(Object arg1, Object arg2) -Methode. Nach dem Gesetz von Demeter ist diese Methode auf den Aufruf beschränkt:
  • Methoden des Car -Objekts selbst (mit anderen Worten des „this“-Objekts);
  • Methoden von Objekten, die innerhalb der Move- Methode erstellt wurden;
  • Methoden von Objekten, die als Argumente übergeben wurden ( arg1 , arg2 );
  • Methoden interner Car- Objekte (wieder „this“).
Mit anderen Worten, das Gesetz von Demeter ist so etwas wie das, was Eltern zu einem Kind sagen könnten: „Du kannst mit deinen Freunden reden, aber nicht mit Fremden.“

Datenstruktur

Eine Datenstruktur ist eine Sammlung zusammengehöriger Elemente. Wenn man ein Objekt als Datenstruktur betrachtet, gibt es eine Reihe von Datenelementen, mit denen Methoden arbeiten. Die Existenz dieser Methoden wird implizit vorausgesetzt. Das heißt, eine Datenstruktur ist ein Objekt, dessen Zweck darin besteht, die gespeicherten Daten zu speichern und damit zu arbeiten (zu verarbeiten). Der Hauptunterschied zu einem regulären Objekt besteht darin, dass ein gewöhnliches Objekt eine Sammlung von Methoden ist, die mit Datenelementen arbeiten, von denen implizit angenommen wird, dass sie existieren. Verstehst du? Der Hauptaspekt eines gewöhnlichen Objekts sind Methoden. Interne Variablen erleichtern deren korrekten Betrieb. Aber in einer Datenstruktur sind die Methoden dazu da, Ihre Arbeit mit den gespeicherten Datenelementen zu unterstützen, die hier von größter Bedeutung sind. Eine Art von Datenstruktur ist ein Data Transfer Object (DTO). Hierbei handelt es sich um eine Klasse mit öffentlichen Variablen und keinen Methoden (oder nur Methoden zum Lesen/Schreiben), die zum Übertragen von Daten bei der Arbeit mit Datenbanken, dem Parsen von Nachrichten von Sockets usw. verwendet wird. Daten werden in solchen Objekten normalerweise nicht über einen längeren Zeitraum gespeichert. Es wird fast sofort in den Entitätstyp konvertiert, mit dem unsere Anwendung funktioniert. Eine Entität wiederum ist ebenfalls eine Datenstruktur, ihr Zweck besteht jedoch darin, an der Geschäftslogik auf verschiedenen Ebenen der Anwendung teilzunehmen. Der Zweck eines DTO besteht darin, Daten zur/von der Anwendung zu transportieren. Beispiel für ein DTO: ist ebenfalls eine Datenstruktur, deren Zweck jedoch darin besteht, an der Geschäftslogik auf verschiedenen Ebenen der Anwendung teilzunehmen. Der Zweck eines DTO besteht darin, Daten zur/von der Anwendung zu transportieren. Beispiel für ein DTO: ist ebenfalls eine Datenstruktur, deren Zweck jedoch darin besteht, an der Geschäftslogik auf verschiedenen Ebenen der Anwendung teilzunehmen. Der Zweck eines DTO besteht darin, Daten zur/von der Anwendung zu transportieren. Beispiel für ein DTO:

@Setter
@Getter
@NoArgsConstructor
public class UserDto {
    private long id;
    private String firstName;
    private String lastName;
    private String email;
    private String password;
}
Alles scheint klar genug, aber hier erfahren wir etwas über die Existenz von Hybriden. Hybride sind Objekte, die über Methoden zur Handhabung wichtiger Logik verfügen, interne Elemente speichern und auch Zugriffsmethoden (Get/Set) enthalten. Solche Objekte sind chaotisch und erschweren das Hinzufügen neuer Methoden. Sie sollten sie vermeiden, da nicht klar ist, wozu sie dienen – Elemente speichern oder Logik ausführen?

Prinzipien zum Erstellen von Variablen

Lassen Sie uns ein wenig über Variablen nachdenken. Lassen Sie uns genauer darüber nachdenken, welche Prinzipien bei der Erstellung gelten:
  1. Idealerweise sollten Sie eine Variable unmittelbar vor der Verwendung deklarieren und initialisieren (erstellen Sie keine und vergessen Sie sie nicht).
  2. Deklarieren Sie Variablen nach Möglichkeit als endgültig, um zu verhindern, dass sich ihr Wert nach der Initialisierung ändert.
  3. Vergessen Sie nicht die Zählervariablen, die wir normalerweise in einer Art for- Schleife verwenden. Vergessen Sie also nicht, sie auf Null zu setzen. Andernfalls könnte unsere gesamte Logik kaputt gehen.
  4. Sie sollten versuchen, Variablen im Konstruktor zu initialisieren.
  5. Wenn die Wahl zwischen der Verwendung eines Objekts mit oder ohne Referenz ( new SomeObject() ) besteht, entscheiden Sie sich für „ohne“, da das Objekt nach der Verwendung im nächsten Garbage-Collection-Zyklus gelöscht wird und seine Ressourcen nicht verschwendet werden.
  6. Halten Sie die Lebensdauer einer Variablen (den Abstand zwischen der Erstellung der Variablen und dem letzten Verweis auf sie) so kurz wie möglich.
  7. Initialisieren Sie Variablen, die in einer Schleife verwendet werden, unmittelbar vor der Schleife, nicht am Anfang der Methode, die die Schleife enthält.
  8. Beginnen Sie immer mit dem begrenztesten Bereich und erweitern Sie ihn nur bei Bedarf (Sie sollten versuchen, eine Variable so lokal wie möglich zu gestalten).
  9. Verwenden Sie jede Variable nur für einen Zweck.
  10. Vermeiden Sie Variablen mit einem versteckten Zweck, z. B. eine Variable, die auf zwei Aufgaben aufgeteilt ist – das bedeutet, dass ihr Typ nicht für die Lösung einer dieser Aufgaben geeignet ist.

Methoden

Codierungsregeln: Von der Erstellung eines Systems bis zur Arbeit mit Objekten – 4

aus dem Film „Star Wars: Episode III – Die Rache der Sith“ (2005)

Kommen wir direkt zur Implementierung unserer Logik, also zu den Methoden.
  1. Regel Nr. 1 – Kompaktheit. Idealerweise sollte eine Methode 20 Zeilen nicht überschreiten. Das heißt, wenn eine öffentliche Methode erheblich „anwächst“, müssen Sie darüber nachdenken, die Logik aufzubrechen und in separate private Methoden zu verschieben.

  2. Regel Nr. 2 – if- , else- , while- und andere Anweisungen sollten keine stark verschachtelten Blöcke haben: Viele Verschachtelungen verringern die Lesbarkeit des Codes erheblich. Idealerweise sollten Sie nicht mehr als zwei verschachtelte {} -Blöcke haben.

    Und es ist auch wünschenswert, den Code in diesen Blöcken kompakt und einfach zu halten.

  3. Regel Nr. 3 – Eine Methode sollte nur eine Operation ausführen. Das heißt, wenn eine Methode alle Arten komplexer Logik ausführt, unterteilen wir sie in Untermethoden. Dadurch ist die Methode selbst eine Fassade, deren Zweck darin besteht, alle anderen Operationen in der richtigen Reihenfolge aufzurufen.

    Was aber, wenn die Operation zu einfach erscheint, um sie in eine separate Methode zu integrieren? Zwar fühlt es sich manchmal so an, als würde man mit einer Kanone auf Spatzen schießen, aber kleine Methoden bieten eine Reihe von Vorteilen:

    • Besseres Codeverständnis;
    • Mit fortschreitender Entwicklung werden Methoden tendenziell komplexer. Wenn eine Methode zunächst einfach ist, ist es etwas einfacher, ihre Funktionalität zu komplizieren.
    • Implementierungsdetails sind ausgeblendet;
    • Einfachere Code-Wiederverwendung;
    • Zuverlässigerer Code.

  4. Die Stepdown-Regel – Code sollte von oben nach unten gelesen werden: Je tiefer Sie lesen, desto tiefer tauchen Sie in die Logik ein. Und umgekehrt gilt: Je höher man geht, desto abstrakter werden die Methoden. Beispielsweise sind Switch-Anweisungen eher unkompakt und unerwünscht, aber wenn Sie die Verwendung eines Switch nicht vermeiden können, sollten Sie versuchen, ihn so weit wie möglich nach unten zu verschieben, in die Methoden der untersten Ebene.

  5. Methodenargumente – Was ist die ideale Zahl? Im Idealfall gar keine :) Aber kommt das wirklich vor? Allerdings sollten Sie versuchen, so wenige Argumente wie möglich zu haben, denn je weniger es gibt, desto einfacher ist es, eine Methode zu verwenden und desto einfacher ist es, sie zu testen. Versuchen Sie im Zweifelsfall, alle Szenarien für den Einsatz der Methode mit einer großen Anzahl von Eingabeparametern vorherzusehen.

  6. Darüber hinaus wäre es sinnvoll, Methoden zu trennen, die ein boolesches Flag als Eingabeparameter haben, da dies allein impliziert, dass die Methode mehr als eine Operation ausführt (wenn wahr, dann eine Sache ausführen; wenn falsch, dann eine andere ausführen). Wie ich oben geschrieben habe, ist das nicht gut und sollte nach Möglichkeit vermieden werden.

  7. Wenn eine Methode eine große Anzahl von Eingabeparametern hat (ein Extremwert ist 7, aber Sie sollten nach 2-3 wirklich mit dem Nachdenken beginnen), sollten einige der Argumente in einem separaten Objekt gruppiert werden.

  8. Wenn mehrere ähnliche (überladene) Methoden vorhanden sind, müssen ähnliche Parameter in derselben Reihenfolge übergeben werden: Dies verbessert die Lesbarkeit und Benutzerfreundlichkeit.

  9. Wenn Sie Parameter an eine Methode übergeben, müssen Sie sicherstellen, dass sie alle verwendet werden. Wozu brauchen Sie sie sonst? Schneiden Sie alle nicht verwendeten Parameter aus der Schnittstelle und fertig.

  10. try/catch sieht von Natur aus nicht sehr schön aus, daher wäre es eine gute Idee, es in eine separate Zwischenmethode (eine Methode zur Behandlung von Ausnahmen) zu verschieben:

    
    public void exceptionHandling(SomeObject obj) {
        try {  
            someMethod(obj);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

Ich habe oben über doppelten Code gesprochen, aber ich möchte es noch einmal wiederholen: Wenn wir mehrere Methoden mit wiederholtem Code haben, müssen wir ihn in eine separate Methode verschieben. Dadurch werden sowohl die Methode als auch die Klasse kompakter. Vergessen Sie nicht die Regeln, die Namen regeln: Einzelheiten zur richtigen Benennung von Klassen, Schnittstellen, Methoden und Variablen werden im nächsten Teil des Artikels besprochen. Aber das ist alles, was ich heute für Sie habe.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION