[JAVA] Zusammenfassung der Eclipse-Umgestaltung

Eclipse hat verschiedene Refactoring-Funktionen, aber um ehrlich zu sein, habe ich nicht wirklich verstanden, was passieren würde, wenn ich sie ausführen würde, also habe ich sie zusammengefasst.

Was ist Refactoring?

Refactoring ist der Prozess der Verbesserung der internen Struktur unter Beibehaltung des externen Verhaltens der Software.

Gründe für das Refactoring

Verbessern Sie das Software-Design

Es gibt kein perfektes Design. Genau genommen wird es im Laufe der Zeit nicht perfekt sein, auch wenn es zum Zeitpunkt des Designs perfekt erscheint. Darüber hinaus weiß niemand, welche Art von Anfragen in Zukunft kommen werden und wer wo Funktionen hinzufügen wird.

Ein Beispiel, bei dem das Design nicht perfekt ist

――Ich habe nur an Bargeld und Kreditkarten als Zahlungsmethode gedacht, aber jetzt ist es notwendig, andere bargeldlose Zahlungen zu unterstützen. ――Da die Lieferzeit kurz war, haben wir Ad-hoc-Maßnahmen ergriffen, um den Einflussbereich zu begrenzen.

Da sich das Design im Laufe der Zeit verschlechtert, ist eine regelmäßige Wartung erforderlich.

Machen Sie die Software verständlicher

Gut organisierter Code ist gut lesbar und kann die Zeit verkürzen, die Entwickler zum Lesen des Codes benötigen. Außerdem ist es einfacher, Fehler zu finden.

Beschleunigen Sie die Entwicklung auf lange Sicht

Wenn das Design nicht gut ist, werden technische Schulden angehäuft, die gleiche Änderung wird an vielen Stellen angewendet, das Ausmaß des Einflusses wird nicht bekannt sein und die Untersuchung wird einige Zeit dauern. Durch kontinuierliches Refactoring werden Schulden beseitigt, und selbst wenn die Anzahl der Funktionen zunimmt, kann der Entwicklungsaufwand reduziert werden.

Bei der Vermeidung von Refactoring

Leider ist Refactoring keine Wunderwaffe.

Wird die Schnur weiter salzen

Wenn Sie keine Änderungen an Ihrem vorhandenen Code vornehmen, hat das Refactoring nur geringe Auswirkungen und lässt nur die Risiken übrig. Es gibt dort keine wirtschaftliche Rationalität, es ist nur Selbstzufriedenheit.

Extern exponierte Schnittstelle

Wenn Sie eine API entwickeln und nicht wissen, wer sie verwendet, können Sie sie nicht ändern.

Ich kann meinen Chef nicht überzeugen

Refactoring erhöht naturgemäß nicht die Funktionalität des Systems. Wenn Ihr Chef die Bedeutung des Refactorings nicht versteht, versuchen Sie Ihr Bestes, um ihn zu überzeugen. Wenn Sie sich nicht überzeugen können, geben Sie anmutig auf, damit Sie nicht zur Verantwortung gezogen werden. ~~ (Und hinter den Kulissen lassen Sie uns als Softwareprofi stillschweigend umgestalten.) ~~ Dies kann vermieden werden, wenn die Lieferzeiten knapp sind oder wenn alle Änderungen manuell getestet werden müssen.

Refactoring in Eclipse

Das Refactoring kann von kleinen Änderungen wie dem Umbenennen lokaler Variablen bis zu großen Änderungen wie dem Ersetzen der switch-Anweisung durch Klassenpolymorphismus reichen. Wenn der zu überarbeitende Code durch Tests geschützt ist, können Sie mit Vertrauen umgestalten, aber der Legacy-Code enthält keine Tests, sodass Sie nicht mit Sicherheit umgestalten können. Die in integrierten Entwicklungsumgebungen wie Eclipse bereitgestellten Refactoring-Tools wurden jedoch tausende Male weltweit ausgeführt (getestet), sodass das Refactoring auch in einer Umgebung ohne automatische Tests relativ sicher durchgeführt werden kann. Ich werde. ⚠️ Nicht 100% sicher.

Bestätigungsumgebung

Version: 2019-06 (4.12.0) Build id: 20190614-1200

Refactoring-Methode

Wählen Sie das Teil aus, das Sie umgestalten möchten, und klicken Sie mit der rechten Maustaste → Sie können es über das Refactoring-Menü ausführen. Im Falle einer Verknüpfung ist es "Alt" + "Strg" + "T". (Für Mac Alt + + T)

Vorsichtsmaßnahmen beim Ausführen des Refactorings

Machen Sie häufige Backups

Refactoring kann mehrere Klassen betreffen und kann nach mehreren Läufen nicht mit "Strg + Z" zurückgegeben werden. Machen Sie häufige Backups, damit Sie Ihre Änderungen rückgängig machen können.

Wird häufig ausgeführt, wenn automatisierte Tests vorhanden sind

IDE-Refactoring ist grundsätzlich sicher, führen Sie jedoch so oft wie möglich automatisierte Tests durch, um sicherzustellen, dass das Refactoring Ihr Verhalten nicht geändert hat.

Wenn Reflexion verwendet wird, untersuchen Sie das Ausmaß des Aufpralls gründlich

Java verfügt über einen leistungsstarken Mechanismus namens Reflection, profitiert jedoch nicht von der Überprüfung des Compilertyps. Selbst das Refactoring-Tool der IDE ist nicht anwendbar. Wenn Sie es also in Ihrem Code verwenden, können Sie erst feststellen, dass Sie den Code beschädigt haben, wenn Sie ihn ausführen. Wenn Sie es im Programm verwenden, untersuchen Sie den Einflussbereich gründlich. Wenn Sie ein Framework oder Plug-In entwickeln, verwenden Sie möglicherweise Reflection. ~~ Verwenden Sie es, um Zugriffsmodifikatoren in Ihrem Testcode zu unterbrechen? Wer hat das getan? ~~

Jedes Refactoring

Endlich das Hauptthema. Aufgrund meines eigenen Urteils und meiner Vorurteile habe ich die Gegenstände angeordnet, die ich am häufigsten benutze, und die Gegenstände, von denen ich denke, dass ich sie verwenden kann.

Umbenennen: star :: star :: star :: star :: star ::

** Anwendbar ** Pakete, Klassen, Methoden, Variablen Wirksamkeit Umbenennen. Sie können Variablennamen, Methodennamen und Klassennamen ändern, z. B. warum haben Sie diese Abkürzung verwendet? Oder a oder instanse2 oder vernachlässigte Namen in aussagekräftige Namen. ** Optional (bei Anwendung auf die Methode) ** Behalten Sie die ursprüngliche Methode als Delegation bei der umbenannten Methode bei + markieren Sie sie als veraltet Es ist auch möglich, die nach außen offene Methode zu ändern, während die ursprüngliche Methode beibehalten wird, um die Kompatibilität zu gewährleisten. Wenn Sie die Marke als veraltet auswählen, wird "@ veraltet" hinzugefügt.

before


String getCpyNm() {
  return cpyNm;
}

after


String getCompanyName() {
  return companyName;
}

after+Möglichkeit


/**
* @deprecated  {@link #getCompanyName()}Ersatz für
*/
public String getCpyNm() {
  return getCompanyName();
}

public String getCompanyName() {
  return companyName;
}

** Optional (falls auf die Klasse angewendet) **

Die folgenden Optionen stehen zur Verfügung.

Es ist nicht sicher, den Kommentar oder einen ähnlichen Methodennamen anstelle des referenzierten Teils zu ändern. Überprüfen Sie ihn daher unbedingt in der Vorschau.

Methodenextraktion: star :: star :: star :: star :: star ::

** Anwendbar ** Ausgewählte Zeile in der Methode Wirksamkeit Trennen Sie das ausgewählte Teil als separate Methode. Wenn der Code Duplikate enthält, können mehrere Duplikate gleichzeitig ersetzt werden.

before


public void printAverage(int a, int b, int c) {
  int sum = a + b+c;
  int average = sum/3;
  System.out.println(average);
}  

after


public void printAverage(int a, int b, int c) {
  int average = getAverage(a, b, c);
  System.out.println(average);
}

private int getAverage(int a, int b, int c) {
  int sum = a + b+c;
  int average = sum/3;
  return average;
}

Lokale Variablen extrahieren: star :: star :: star :: star :: star ::

** Anwendbar ** Die ausgewählte Formel oder bedingte Formel in der Methode Wirksamkeit Teilen Sie lange Ausdrücke usw. oder führen Sie erklärende Variablen ein Inline-Umkehrung

before


  public int getTotal(int price) {
    int result = (int) (price * 0.8 * 1.10);
    return result;
  }

after


  public int getTotal(int price) {
    double discountPrice = price * 0.8;
    int result = (int) (discountPrice * 1.10);
    return result;
  }

Inline: star :: star :: star :: star :: star ::

** Anwendbar ** Variable Wirksamkeit Ersetzen Sie redundante Variablendeklarationen durch ihre Werte Umkehrung der Extraktion lokaler Variablen

before


  public int getTotal(int price) {
    double discountPrice = price * 0.8;
    int result = (int) (discountPrice * 1.10);
    return result;
  }

after


  public int getTotal(int price) {
    int result = (int) ((price * 0.8) * 1.10);
    return result;
  }

Extraktion von Konstanten: star :: star :: star :: star ::

** Anwendbar ** Konstante Wirksamkeit Ändern Sie die Konstante in eine Mitgliedsvariable. Es können nur statische Werte verwendet werden.

before


  public int getTotal(int price) {
    int result = (int) (price * 0.8 * 1.10);
    return result;
  }

after


  public static final double TAX_RATE = 1.10;

  public int getTotal(int price) {
    int result = (int) (price * 0.8 * TAX_RATE);
    return result;
  }

Feldverkapselung: star :: star :: star :: star ::

** Anwendbar ** Mitgliedsvariablen Wirksamkeit Generieren Sie eine Mitgliedsvariable getter / setter und ersetzen Sie die Referenzmethode durch eine Methode, die getter / setter verwendet. Möglichkeit Wenn Sie den deklarativen Feldzugriff so ändern, dass er die Feldreferenz enthält, können Sie den Feldwert, auf den direkt verwiesen wird, beibehalten.

before


public class Refactoring {

  private String companyName = "";
  private int companyId = 0;

  public Refactoring(String companyName, int companyId) {
    this.companyName = companyName;
    this.companyId = companyId;
  }
}

after


public class Refactoring {

  private String companyName = "";
  private int companyId = 0;

  public Refactoring(String companyName, int companyId) {
    this.companyName = companyName;
    this.setCompanyId(companyId);
  }

  /**
   * @return companyId
   */
  private int getCompanyId() {
    return companyId;
  }

  /**
   * @param companyId set companyId
   */
  private void setCompanyId(int companyId) {
    this.companyId = companyId;
  }

}

Konvertieren Sie lokale Variablen in Felder: star :: star :: star :: star ::

** Anwendbar ** Lokale Variablen Wirksamkeit Ändern Sie lokale Variablen in Mitgliedsvariablen. Ähnlich wie bei der konstanten Extraktion Möglichkeit Feldzugriffsmodifikatoren und Initialisierungspositionen können geändert werden

before


public class Refactoring {
  public int getTotal(int price) {
    double discountRate = 0.8;
    int result = (int) (price * discountRate * 1.10);
    return result;
  }
}

after


public class Refactoring {
  private double discountRate = 0.8;

  public int getTotal(int price) {
    int result = (int) (price * discountRate * 1.10);
    return result;
  }
}

Verschieben: star :: star :: star ::

** Anwendbar ** Paket, Klasse Wirksamkeit Verschieben Sie die Klasse in ein anderes Paket, verschieben / benennen Sie das Paket um. Wenn Sie ein Paket verschieben, können Sie die Unterpakete sofort ändern.

package com.example.refactoring;
package com.example.refactoring.util;

** Anwendbar ** statische Variable, statische Methode Wirksamkeit Sie können statische Variablen und statische Methoden in eine andere Klasse verschieben. Es kann auch für Elementvariablen verwendet werden. Da es jedoch keine Referenz enthalten kann, besteht eine hohe Wahrscheinlichkeit, dass ein Kompilierungsfehler auftritt. .. .. (Ist es Refactoring?)

before


public class Refactoring {
  public static final String staticString = "s";

  public static String getStaticString() {
    return staticString;
  }
}

public class OtherClass {
}

after


public class Refactoring {
  public static String getStaticString() {
    return OtherClass.staticString;
  }
}

public class OtherClass {
  public static final String staticString = "s";
}

Änderungen der Methodensignatur: star :: star :: star:

** Anwendbar ** Methode Wirksamkeit Hinzufügen, Entfernen oder Ändern von Methodenargumenten Eine problematische Sortierung ist auch beim Kopieren möglich Möglichkeit Wenn Sie "Ursprüngliche Methode als Delegation an geänderte Methode beibehalten" aktivieren, können Sie die Methode der ursprünglichen Signatur beibehalten.

before


  public Refactoring(String companyName) {
    this.companyName = companyName;
  }

after


  public Refactoring(String companyName, String newParam) {
    this.companyName = companyName;
  }

after(Behalten Sie die ursprüngliche Methode als Delegation an die geänderte Methode bei)


  /**
   * @deprecated  {@link #Refactoring(String,String)}Ersatz für
   */
  public Refactoring(String companyName) {
    this(companyName, null);
  }

  public Refactoring(String companyName, String newParam) {
    this.companyName = companyName;
  }

Schnittstellenextraktion: star :: star :: star:

** Anwendbar ** Klasse Wirksamkeit Erstellen Sie eine Schnittstelle aus einer vorhandenen Klasse. Sie können eine Schnittstelle erstellen, indem Sie eine beliebige öffentliche Methode einer vorhandenen Klasse auswählen. Die erstellte Schnittstelle wird automatisch in "implementiert" angegeben und die Methode wird mit "@ Override" versehen.

before


public class Refactoring  {
  private String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}

after


public interface RefactoringInterface {
  String getCompanyName();
}

public class Refactoring implements RefactoringInterface {
  private String companyName = "";

  @Override
  public String getCompanyName() {
    return companyName;
  }
}

Klassenextraktion: star :: star :: star:

** Anwendbar ** Klasse (wesentliche Mitgliedsvariable) Wirksamkeit Gruppieren Sie Mitgliedsvariablen in separate Klassen. Es wird verwendet, wenn die Klasse aufgebläht wird oder wenn verwandte Dinge wie IP-Adresse und Portnummer zusammengefügt werden. Methoden können nicht nur mit Mitgliedsvariablen extrahiert werden. Möglichkeit Das Extraktionsziel kann aus der Klasse der obersten Ebene und der anonymen Klasse ausgewählt werden. Im Fall der Klasse der obersten Ebene wird sie als eine andere Klasse extrahiert und Bei einer anonymen Klasse werden die Klassen in derselben Klasse extrahiert.

before


public class Refactoring {

  private String companyName = "";
  private String postNo = "";

  public void main() {}
}

after(Für erstklassige Klasse)


public class Refactoring {

  private RefactoringData data = new RefactoringData("", "");

  public void main() {}
}

public class RefactoringData {
  public String companyName;
  public String postNo;

  public RefactoringData(String companyName, String postNo) {
    this.companyName = companyName;
    this.postNo = postNo;
  }
}

after(Für anonyme Klassen)


public class Refactoring {

  public static class RefactoringData {
    public String companyName;
    public String postNo;

    public RefactoringData(String companyName, String postNo) {
      this.companyName = companyName;
      this.postNo = postNo;
    }
  }

  private RefactoringData data = new RefactoringData("", "");

  public void main() {}
}

Einführung in Parameterobjekte: star :: star :: star:

** Anwendbar ** Methode Wirksamkeit Kombinieren Sie beliebige Argumente zu einem Objekt Möglichkeit Wenn Sie "Ursprüngliche Methode als Delegation an geänderte Methode beibehalten" aktivieren, können Sie die Methode der ursprünglichen Signatur beibehalten. Sie können das zu generierende Parameterobjekt entweder aus der Klasse der obersten Ebene oder der anonymen Klasse auswählen.

before


public class Refactoring {
  public Refactoring(String companyName, int companyId) {
    this.companyName = companyName;
    this.companyId = companyId;
  }
}

after(Geben Sie die Klasse der obersten Ebene an)


public class Refactoring {
 public Refactoring(RefactoringParameter parameterObject) {
    this.companyName = parameterObject.companyName;
    this.companyId = parameterObject.companyId;
  }
}

public class RefactoringParameter {
  public String companyName;
  public int companyId;

  public RefactoringParameter(String companyName, int companyId) {
    this.companyName = companyName;
    this.companyId = companyId;
  }
}

after(Geben Sie eine anonyme Klasse an)


public class Refactoring {
  /**
   * @deprecated  {@link #Refactoring(RefactoringParameter)}Ersatz für
   */
  public Refactoring(String companyName, int companyId) {
    this(new RefactoringParameter(companyName, companyId));
  }

  public Refactoring(RefactoringParameter parameterObject) {
    this.companyName = parameterObject.companyName;
    this.companyId = parameterObject.companyId;
  }
}

public class RefactoringParameter {
  //Das Parameterobjekt ist dasselbe
}

Parametereinführung: star :: star:

** Anwendbar ** Variablen und Konstanten in der Methode Wirksamkeit Ändern Sie Variablen und Konstanten in einer Methode in Methodenargumente

before


  public String getCompanyName() {
    return "prefix_" + companyName;
  }

after


  public String getCompanyName(String prefix) {
    return prefix + companyName;
  }

Super Class Extraktion: star :: star:

** Anwendbar ** Klasse Wirksamkeit Erstellen Sie eine Superklasse aus einer vorhandenen Klasse. Eine Superklasse kann durch Angabe beliebiger Elementvariablen und -methoden aus einer vorhandenen Klasse erstellt werden, und "Erweitert" wird automatisch angegeben.

before


public class Refactoring  {
  private String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}

after


public class RefactoringSuper {
  private String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}

public class Refactoring extends RefactoringSuper {
}

Pull-up / Push-down: star :: star:

** Anwendbar ** Variablen und Methoden für Mitglieder der Oberklasse / Unterklasse Wirksamkeit Verschieben Sie Elementvariablen und Methoden zwischen Oberklassen / Unterklassen Pull-up bewegt sich von Unterklasse zu Oberklasse, Pushdown wechselt von der Superklasse zur Unterklasse. ** Optional (während des Pushdowns) ** Wenn Sie "Abstrakte Deklaration verlassen" auswählen, können Sie die Methode als abstruct in die Superklasse verschieben lassen.

Nach dem Hochziehen


public class SuperClass {

  private String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}

public class Refactoring extends SuperClass {

}

Nach dem Herunterdrücken


public class SuperClass {

}

public class Refactoring extends SuperClass {
  private String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}

Nach dem Herunterdrücken+Hinterlassen Sie eine abstrakte Erklärung


public abstract class SuperClass {
  public abstract String getCompanyName();
}

public class Refactoring extends SuperClass {
  private String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}

Vorstellung der Fabrik: star :: star:

** Anwendbar ** Konstrukteur Wirksamkeit Ersetzen Sie den Konstruktor durch eine statische Factory-Methode. Es wird verwendet, wenn Sie die Zielklasse zu einer Singleton-Klasse machen möchten oder wenn Sie die Generierungsmethode flexibel ändern möchten.

before


public class Refactoring {

  private String companyName = "";

  public Refactoring(String companyName) {
    this.companyName = companyName;
  }
}

after


public class Refactoring {

  public static Refactoring createRefactoring(String companyName) {
    return new Refactoring(companyName);
  }

  private String companyName = "";

  private Refactoring(String companyName) {
    this.companyName = companyName;
  }
}

Verwenden Sie den Supertyp, falls verfügbar: Stern:

** Anwendbar ** Klasse (Referenz innerhalb praktisch anderer Methoden) Wirksamkeit Wenn eine Superklasse als Ersatz verwendet werden kann, ersetzen Sie sie durch eine Superklasse. Im folgenden Beispiel wurde die Deklaration der Use-Klasse ersetzt, aber es ist die Unterklasse, die das Refactoring durchführt.

Klassendefinition


public class SuperClass {
  protected String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}
public class Refactoring extends SuperClass {
}

before


public class Use {
  public void main() {
    Refactoring instance = new Refactoring("", 0);
    System.out.println(instance.getCompanyName());
  }
}

after


public class Use {
  public void main() {
    SuperClass instance = new Refactoring("", 0);
    System.out.println(instance.getCompanyName());
  }
}

Typ in neue Datei verschieben: star:

** Anwendbar ** Anonyme Klasse (innere Klasse) Wirksamkeit Verschieben Sie eine anonyme Klasse in eine andere Datei

before


public class Refactoring {
  private String companyName = "";
  private int companyId = 0;

  public static class RefactoringParameter {
    public String companyName;
    public int companyId;

    public RefactoringParameter(String companyName, int companyId) {
      this.companyName = companyName;
      this.companyId = companyId;
    }
  }

  public Refactoring(RefactoringParameter parameterObject) {
    this.companyName = parameterObject.companyName;
    this.companyId = parameterObject.companyId;
  }
}

after


public class Refactoring {

  private String companyName = "";
  private int companyId = 0;

  public Refactoring(RefactoringParameter parameterObject) {
    this.companyName = parameterObject.companyName;
    this.companyId = parameterObject.companyId;
  }
}

public class RefactoringParameter {
  public String companyName;
  public int companyId;

  public RefactoringParameter(String companyName, int companyId) {
    this.companyName = companyName;
    this.companyId = companyId;
  }
}

Verallgemeinerung des deklarierten Typs: Stern:

** Anwendbar ** Elementvariablentyp, Methodenrückgabetyp, Variablentyp Wirksamkeit Ersetzen Sie den Typ durch einen Superklassentyp. Es kann in eine Superklasse wie String type → Object type geändert werden. Es kann jedoch nicht geändert werden, wenn es in einer anderen Klasse als String-Typ referenziert wird und nicht kompatibel ist.

before


public String getCompanyName() {
  return companyName;
}

after


public Object getCompanyName() {
  return companyName;
}

Schließlich

Es gab viele Funktionen, die ich zum ersten Mal über das Refactoring von Eclipse gelernt habe. Die Anzahl von: star: ist gering für diejenigen, die ich persönlich nicht verwenden konnte. Bitte lassen Sie mich wissen, ob es eine bequeme Verwendung gibt. Es ist nicht 100% sicher, aber es ist überwältigend schneller und sicherer als die Methode zur manuellen Behebung des Teils, bei dem der Fehler nach dem Ändern aufgetreten ist. Lassen Sie uns ihn also stetig umgestalten.

Recommended Posts

Zusammenfassung der Eclipse-Umgestaltung
Zusammenfassung
Eclipse-Fehler
Ransack Zusammenfassung
Eclipse --Springboot