[JAVA] Résumé de la refactorisation Eclipse

Eclipse a diverses fonctions de refactoring, mais pour être honnête, je n'ai pas vraiment compris ce qui se passerait si je les exécutais, alors je les ai résumées.

Qu'est-ce que le refactoring?

Le refactoring est le processus d'amélioration de la structure interne tout en préservant le comportement externe du logiciel.

Raisons du refactoring

Améliorer la conception de logiciels

Il n'y a pas de design parfait. À proprement parler, même si cela semble parfait au moment de la conception, il ne le sera pas avec le temps. De plus, personne ne sait quel type de requêtes sortira à l'avenir et qui ajoutera des fonctions où.

Un exemple où le design n'est pas parfait

«Je ne pensais qu'aux espèces et aux cartes de crédit comme moyens de paiement, mais il est maintenant nécessaire de prendre en charge d'autres paiements sans espèces. ――Le délai de livraison étant court, nous avons pris des mesures ad hoc pour limiter la portée d'influence.

Comme la conception se détériore avec le temps, il est nécessaire d'effectuer un entretien régulier.

Rendre le logiciel plus facile à comprendre

Un code bien organisé est hautement lisible et peut réduire le temps nécessaire aux développeurs pour lire le code. De plus, cela facilite la recherche de bogues.

Accélérer le développement à long terme

Si la conception n'est pas bonne, la dette technique sera accumulée et le même changement sera appliqué à de nombreux endroits. En continuant à refactoriser, la dette est éliminée, et même si le nombre de fonctions augmente, l'effort de développement peut être réduit.

En évitant le refactoring

Malheureusement, la refactorisation n'est pas une solution miracle.

Continuera à saler le cordon

Si vous n'apportez aucune modification à votre code existant, la refactorisation aura peu d'effet, ne laissant que les risques. Il n'y a pas de rationalité économique là-bas, c'est juste l'auto-satisfaction.

Interface exposée de l'extérieur

Si vous développez une API et que vous ne savez pas qui l'utilise, vous ne pouvez pas la modifier.

Je ne peux pas convaincre mon patron

De par sa nature même, le refactoring n'augmente pas la fonctionnalité du système. Si votre patron ne comprend pas l'importance de la refactorisation, faites de votre mieux pour le convaincre. Si vous ne pouvez pas vous convaincre, abandonnez gracieusement pour ne pas être tenu responsable. ~~ (Et dans les coulisses, refactorisons silencieusement en tant que professionnel du logiciel.) ~~ Cela peut être évité lorsque les délais de livraison sont serrés ou lorsque toutes les modifications doivent être testées manuellement.

Refactoring dans Eclipse

La refactorisation peut aller de petits changements tels que le changement de nom des variables locales à des changements majeurs tels que le remplacement de l'instruction switch par un polymorphisme dans la classe. Si le code à refactoriser est protégé par des tests, vous pouvez le refactoriser en toute confiance, mais le code hérité n'a pas de tests, vous ne pouvez donc pas refactoriser en toute confiance. Cependant, en ce qui concerne les outils de refactoring fournis dans des environnements de développement intégrés tels qu'Eclipse, ils ont été exécutés (testés) des milliers de fois dans le monde, de sorte que le refactoring peut être effectué de manière relativement sûre, même dans un environnement sans test automatique. Je vais. ⚠️ Pas sûr à 100%.

Environnement de confirmation

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

Méthode de refactoring

Sélectionnez la pièce que vous souhaitez refactoriser et cliquez avec le bouton droit de la souris → Vous pouvez l'exécuter à partir du menu de refactorisation. Dans le cas d'un raccourci, c'est ʻAlt+Ctrl + T. (Pour Mac, ʻAlt + + T)

Précautions lors de l'exécution du refactoring

Faites des sauvegardes fréquentes

Le refactoring peut affecter plusieurs classes et ne peut pas être retourné avec ctrl + z après plusieurs exécutions. Effectuez des sauvegardes fréquentes afin de pouvoir annuler vos modifications.

Exécuter fréquemment, si des tests automatisés existent

Le refactoring IDE est fondamentalement sûr, mais exécutez des tests automatisés aussi souvent que possible pour vous assurer que le refactoring n'a pas changé votre comportement.

Si la réflexion est utilisée, examinez minutieusement l'étendue de l'impact

Java a un mécanisme puissant appelé réflexion, mais il ne bénéficie pas de la vérification du type de compilateur. Même l'outil de refactoring de l'EDI ne sera pas applicable, donc si vous l'utilisez dans votre code, vous ne pourrez pas détecter que vous avez cassé le code jusqu'à ce que vous l'exécutiez. Si vous l'utilisez dans le programme, examinez en profondeur la plage d'influence. Si vous développez un framework ou un plug-in, vous utilisez peut-être la réflexion. ~~ L'utilisez-vous pour interrompre les modificateurs d'accès dans votre code de test? Qui a fait cela? ~~

Chaque refactoring

Enfin le sujet principal. Sur la base de mon propre jugement et de mes préjugés, j'ai organisé les éléments que j'utilise le plus souvent et les éléments que je pense pouvoir utiliser.

Renommer: star :: star :: star :: star :: star ::

** Applicable ** Paquets, classes, méthodes, variables efficacité Renommer. Vous pouvez changer les noms de variables, les noms de méthodes et les noms de classes, tels que "Pourquoi avez-vous utilisé cette abréviation?" Ou ʻa ou ʻinstanse2, ou la dénomination négligée, en noms significatifs. ** Facultatif (lorsqu'il est appliqué à la méthode) ** Conserver la méthode d'origine en tant que délégation à la méthode renommée + marquer comme obsolète Il est également possible de changer la méthode ouverte sur l'extérieur tout en conservant la méthode d'origine pour maintenir la compatibilité. Si vous sélectionnez la marque comme obsolète, «@ deprecated» sera ajouté.

before


String getCpyNm() {
  return cpyNm;
}

after


String getCompanyName() {
  return companyName;
}

after+option


/**
* @deprecated  {@link #getCompanyName()}Substitut
*/
public String getCpyNm() {
  return getCompanyName();
}

public String getCompanyName() {
  return companyName;
}

** Facultatif (si appliqué à la classe) **

Les options suivantes sont disponibles.

--Mises à jour des variables et des méthodes avec des noms similaires

Il n'est pas sûr de changer le commentaire ou le nom de méthode similaire au lieu de la partie référencée, il est donc essentiel de le vérifier dans l'aperçu.

Méthode d'extraction: star :: star :: star :: star :: star ::

** Applicable ** Ligne sélectionnée dans la méthode efficacité Séparez la pièce sélectionnée comme une méthode distincte. S'il y a des doublons dans le code, il est possible de remplacer plusieurs doublons à la fois.

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;
}

Extraction des variables locales: star :: star :: star :: star :: star ::

** Applicable ** Formule sélectionnée ou formule conditionnelle dans la méthode efficacité Divisez de longues expressions, etc., ou introduisez des variables explicatives Inverse de en ligne

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;
  }

En ligne: star :: star :: star :: star :: star ::

** Applicable ** variable efficacité Remplacer les déclarations de variables redondantes par leurs valeurs Inverse de l'extraction de variables locales

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;
  }

Extraction des constantes: star :: star :: star :: star ::

** Applicable ** constant efficacité Remplacez la constante par une variable membre. Seules les valeurs statiques peuvent être utilisées.

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;
  }

Encapsulation de champ: star :: star :: star :: star ::

** Applicable ** Variables de membre efficacité Générez une variable membre getter / setter et remplacez la méthode de référence par une qui utilise getter / setter. option Si vous définissez «accès au champ en type déclaratif» sur «contenir la référence de champ», vous pouvez conserver la valeur du champ directement référencée.

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;
  }

}

Convertit les variables locales en champs: star :: star :: star :: star ::

** Applicable ** Variables locales efficacité Remplacez les variables locales par des variables membres. Similaire à l'extraction constante option Les modificateurs d'accès aux champs et les positions d'initialisation peuvent être modifiés

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;
  }
}

Déplacer: star :: star :: star ::

** Applicable ** Paquet, classe efficacité Déplacer une classe vers un autre package, déplacer / renommer un package. Si vous déplacez un package, vous pouvez modifier les sous-packages à la fois.

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

** Applicable ** variable statique, méthode statique efficacité Vous pouvez déplacer des variables statiques et des méthodes statiques vers une autre classe. Il peut également être utilisé pour les variables membres, mais comme il ne peut pas contenir de référence, il y a une forte probabilité qu'une erreur de compilation se produise. .. .. (S'agit-il de 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";
}

Changements de signature de méthode: star :: star :: star:

** Applicable ** Méthode efficacité Ajouter, supprimer ou modifier des arguments de méthode Un tri problématique est également possible avec copie option Si vous cochez «Conserver la méthode d'origine comme délégation à la méthode modifiée», vous pouvez conserver la méthode de signature d'origine.

before


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

after


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

after(Conserver la méthode d'origine en tant que délégation à la méthode modifiée)


  /**
   * @deprecated  {@link #Refactoring(String,String)}Substitut
   */
  public Refactoring(String companyName) {
    this(companyName, null);
  }

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

Extraction d'interface: star :: star :: star:

** Applicable ** classe efficacité Créez une interface à partir d'une classe existante. Vous pouvez créer une interface en sélectionnant n'importe quelle méthode publique d'une classe existante, l'interface créée est automatiquement spécifiée dans ʻimplements, et la méthode est annotée avec @ Override`.

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;
  }
}

Extraction de classe: star :: star :: star:

** Applicable ** Classe (variable de membre substantielle) efficacité Regroupez les variables de membre dans des classes distinctes. Il est utilisé lorsque la classe devient gonflée ou lorsque des éléments connexes tels que l'adresse IP et le numéro de port sont réunis. Les méthodes ne peuvent pas être extraites en utilisant uniquement des variables membres. option La destination d'extraction peut être sélectionnée à partir de la classe de premier niveau et de la classe anonyme. Dans le cas de la classe de niveau supérieur, elle est extraite comme une autre classe et Dans le cas d'une classe anonyme, les classes sont extraites dans la même classe.

before


public class Refactoring {

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

  public void main() {}
}

after(Pour une classe de haut niveau)


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(Pour les cours anonymes)


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() {}
}

Présentation des objets paramètres: star :: star :: star:

** Applicable ** Méthode efficacité Combinez des arguments arbitraires en un seul objet option Si vous cochez «Conserver la méthode d'origine comme délégation à la méthode modifiée», vous pouvez conserver la méthode de signature d'origine. Vous pouvez sélectionner l'objet paramètre à générer à partir de la «classe de premier niveau» ou de la «classe anonyme».

before


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

after(Spécifier la classe de niveau supérieur)


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(Spécifiez la classe anonyme)


public class Refactoring {
  /**
   * @deprecated  {@link #Refactoring(RefactoringParameter)}Substitut
   */
  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 {
  //L'objet de paramètre est le même
}

Introduction des paramètres: star :: star:

** Applicable ** Variables et constantes dans la méthode efficacité Changer les variables et les constantes d'une méthode en arguments de méthode

before


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

after


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

Extraction de super classe: star :: star:

** Applicable ** classe efficacité Créez une super classe à partir d'une classe existante. Une super classe peut être créée en spécifiant des variables membres et des méthodes arbitraires à partir d'une classe existante, et ʻextends` est automatiquement spécifié.

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: étoile :: étoile:

** Applicable ** Variables et méthodes des membres de la superclasse / sous-classe efficacité Déplacer les variables membres et les méthodes entre les superclasses / sous-classes Le pull-up passe de la sous-classe à la superclasse, Le refoulement passe de la super classe à la sous-classe. ** Facultatif (pendant le pushdown) ** Si vous sélectionnez «Laisser la déclaration abstraite», vous pouvez laisser la méthode déplacée vers la super classe en tant qu'abstruct.

Après le pull-up


public class SuperClass {

  private String companyName = "";

  public String getCompanyName() {
    return companyName;
  }
}

public class Refactoring extends SuperClass {

}

Après le refoulement


public class SuperClass {

}

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

  public String getCompanyName() {
    return companyName;
  }
}

Après le refoulement+Laisser une déclaration abstraite


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

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

  public String getCompanyName() {
    return companyName;
  }
}

Présentation de l'usine: star :: star:

** Applicable ** constructeur efficacité Remplacez le constructeur par une méthode de fabrique statique. Il est utilisé lorsque vous souhaitez faire de la classe cible une classe singleton ou lorsque vous souhaitez modifier de manière flexible la méthode de génération.

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;
  }
}

Utilisez le supertype si disponible: star:

** Applicable ** Classe (référence dans pratiquement d'autres méthodes) efficacité Si une super classe peut être utilisée comme substitut, remplacez-la par une super classe. Dans l'exemple ci-dessous, la déclaration de la classe Use a été remplacée, mais c'est la sous-classe qui effectue le refactoring.

Définition de classe


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());
  }
}

Déplacer le type vers un nouveau fichier: étoile:

** Applicable ** Classe anonyme (classe interne) efficacité Déplacer la classe anonyme vers un autre fichier

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;
  }
}

Généralisation du type déclaré: étoile:

** Applicable ** Type de variable membre, type de retour de méthode, type de variable efficacité Remplacez le type par un type de superclasse. Il peut être changé en une super classe comme le type String → Type d'objet. Cependant, il ne peut pas être modifié s'il est référencé en tant que type String dans une autre classe et n'est pas compatible.

before


public String getCompanyName() {
  return companyName;
}

after


public Object getCompanyName() {
  return companyName;
}

finalement

J'ai appris beaucoup de fonctionnalités sur le refactoring d'Eclipse pour la première fois. Le nombre de: star: est petit pour ceux que je ne savais pas personnellement utiliser. S'il vous plaît laissez-moi savoir s'il y a une utilisation pratique. Ce n'est pas sûr à 100%, mais c'est extrêmement plus rapide et plus sûr que la méthode de réparation manuelle de la pièce où l'erreur s'est produite après l'avoir modifiée, alors refactorisons-la régulièrement.

Recommended Posts

Résumé de la refactorisation Eclipse
Résumé
Erreur Eclipse
résumé du ransack
Eclipse - Springboot