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.
Refactoring ist der Prozess der Verbesserung der internen Struktur unter Beibehaltung des externen Verhaltens der Software.
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.
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.
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.
Leider ist Refactoring keine Wunderwaffe.
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.
Wenn Sie eine API entwickeln und nicht wissen, wer sie verwendet, können Sie sie nicht ändern.
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.
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.
Version: 2019-06 (4.12.0) Build id: 20190614-1200
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
)
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.
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.
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? ~~
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.
** 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.
** 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;
}
** 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;
}
** 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;
}
** 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;
}
** 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;
}
}
** 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;
}
}
** 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";
}
** 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;
}
** 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;
}
}
** 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() {}
}
** 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
}
** 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;
}
** 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 {
}
** 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;
}
}
** 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;
}
}
** 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());
}
}
** 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;
}
}
** 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;
}
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.