Mi Neurona Favorita

Analizando

Posts Tagged ‘eclipse

Refactoring en Eclipse. (9) Self Encapsulate Field

with one comment

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Self Encapsulate Field

Para encapsular el acceso a un atributo de una clase hay que crear los métodos acceso y modificación (get y set) y sustituir cada uso que se haga del atributo por el correspondiente método. En Eclipse podemos hacerlo más rápidamente de la siguiente forma:

  1. Hacer click derecho sobre el atributo a encapsular, Refactor > Encapsulate Field…
  2. En el cuadro de diálogo, seleccionar “use setter and getter”. Eliminar el método set o usar el modificador de acceso a private para evitar su modificación.

Ejemplo antes de refactorizar:

public class Test {
  private int low, high;

  boolean includes(final int arg) {
    return arg >= low && arg <= high;
  }
}

Tras refactorizar, quedaría:

public class Test {
  private int low, high;

  boolean includes(final int arg) {
    return arg >= getLow() && arg <= getHigh();
  }
  
  private int getLow() {
    return low;
  }

  private int getHigh() {
    return high;
  }
}

Written by Recacha

30 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Refactoring en Eclipse. (8) Extract Class

with one comment

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Extract Class

Si tenemos una clase con demasiadas responsabilidades y queremos extraer algunas de ellas a una nueva clase, podemos extraerlas con ayuda de Eclipse. Lo haremos en 3 pasos, y en cada uno de ellos actuaremos según las necesidades de cada caso:

  1. Extraer atributos a una nueva clase
    1. En cualquier punto de la clase hacer click derecho > Refactor > Extract Class…
    2. En la ventana que aparece, le damos un nombre a la nueva clase, seleccionamos los atributos a extraer y nombraremos también la referencia que creará en la clase original del tipo de la nueva clase.
  2. Mover los métodos necesarios a la nueva clase, aplicando el refactoring “Extract Method”: SHIFT + ALT + V (o click derecho > Refactor > Move…)
  3. Eliminamos los getters y setters de los atributos movidos en el paso 1 de la clase original.

Ejemplo antes de refactorizar (sombreados los atributos y métodos que se van a mover a la nueva clase):

public class Person {
  private String _name;
  private String _officeAreaCode;
  private String _officeNumber;

  public String getTelephoneNumber() {
    return ("(" + _officeAreaCode + ") " + _officeNumber);
  }

  // GETTERS AND SETTERS

  public String getName() {
    return _name;
  }

  public String getOfficeAreaCode() {
    return _officeAreaCode;
  }

  public void setOfficeAreaCode(final String arg) {
    _officeAreaCode = arg;
  }

  public String getOfficeNumber() {
    return _officeNumber;
  }

  public void setOfficeNumber(final String arg) {
    _officeNumber = arg;
  }
}

Creamos la nueva clase TelephoneNumber con los atributos _officeAreaCode y _officeNumber (sombreados los cambios en la clase original):

public class Person {
  private String _name;
  private TelephoneNumber _telephoneNumber = new TelephoneNumber();

  public String getTelephoneNumber() {
    return ("(" + _telephoneNumber.get_officeAreaCode() + ") " + _telephoneNumber.get_officeNumber());
  }

  // GETTERS AND SETTERS

  public String getName() {
    return _name;
  }

  public String getOfficeAreaCode() {
    return _officeAreaCode;
  }

  public void setOfficeAreaCode(final String arg) {
    _officeAreaCode = arg;
  }

  public String getOfficeNumber() {
    return _officeNumber;
  }

  public void setOfficeNumber(final String arg) {
    _officeNumber = arg;
  }
}

public class TelephoneNumber {
  private String _officeAreaCode;
  private String _officeNumber;

  // GETTERS AND SETTERS

  public String get_officeAreaCode() {
    return _officeAreaCode;
  }

  public void set_officeAreaCode(final String _officeAreaCode) {
    this._officeAreaCode = _officeAreaCode;
  }

  public String get_officeNumber() {
    return _officeNumber;
  }

  public void set_officeNumber(final String _officeNumber) {
    this._officeNumber = _officeNumber;
  }
}

Por último movemos el método getTelephoneNumber() a la nueva clase y eliminamos de Person los getters y setters de los atributos movidos:

public class Person {
  private String _name;
  private TelephoneNumber _telephoneNumber = new TelephoneNumber();

  public String getTelephoneNumber() {
    return _telephoneNumber.getTelephoneNumber();
  }

  // GETTERS AND SETTERS

  public String getName() {
    return _name;
  }
}

public class TelephoneNumber {
  private String _officeAreaCode;
  private String _officeNumber;

  public String getTelephoneNumber() {
    return ("(" + get_officeAreaCode() + ") " + get_officeNumber());
  }

  // GETTERS AND SETTERS

  public String get_officeAreaCode() {
    return _officeAreaCode;
  }

  public void set_officeAreaCode(final String _officeAreaCode) {
    this._officeAreaCode = _officeAreaCode;
  }

  public String get_officeNumber() {
    return _officeNumber;
  }

  public void set_officeNumber(final String _officeNumber) {
    this._officeNumber = _officeNumber;
  }
}

Written by Recacha

28 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Refactoring en Eclipse. (7) Move Method

with 3 comments

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Move Method

Para aplicar esta refactorización en Eclipse, consistente en mover un método a una clase más apropiada, lo haremos en 2 pasos:

  1. Encapsular el acceso a los atributos de la clase que se usen en el método (usando get y set). Como veremos más adelante, se corresponde con el refactoring “Encapsulate Field”.
    1. Doble click sobre el atributo a encapsular.
    2. Click derecho > Refactor > Encapsulate Field…
    3. En la ventana, seleccionar el modificador de acceso más adecuado para el get y set, según dónde se encuentre la clase a la que se moverá el método.
  2. Mover el método
    1. Doble click en el nombre del método a mover.
    2. SHIFT + ALT + V (o click derecho > Refactor > Move…)
    3. Si se desea dejar el método original delegando en el nuevo, marcar el check “Keep original method as delegate…”. Eclipse cambiará el modificador de acceso del método si fuese necesario.

Ejemplo antes de refactorizar (sombreados los atributos que se van a encapsular en el primer paso):

public class Account {
  private AccountType _type;
  private int _daysOverdrawn;

  double overdraftCharge() {
    if (_type.isPremium()) {
      double result = 10;
      if (_daysOverdrawn > 7) {
        result += (_daysOverdrawn - 7) * 0.85;
      }
      return result;
    } else {
      return _daysOverdrawn * 1.75;
    }
  }

  double bankCharge() {
    double result = 4.5;
    if (_daysOverdrawn > 0) {
      result += overdraftCharge();
    }
    return result;
  }
}

Tras encapsular los atributos _type y _daysOverdrawn:

public class Account {
  private AccountType _type;
  private int _daysOverdrawn;

  double overdraftCharge() {
    if (get_type().isPremium()) {
      double result = 10;
      if (get_daysOverdrawn() > 7) {
        result += (get_daysOverdrawn() - 7) * 0.85;
      }
      return result;
    } else {
      return get_daysOverdrawn() * 1.75;
    }
  }

  double bankCharge() {
    double result = 4.5;
    if (get_daysOverdrawn() > 0) {
      result += overdraftCharge();
    }
    return result;
  }

  public AccountType get_type() {
    return _type;
  }

  public void set_type(AccountType _type) {
    this._type = _type;
  }

  public int get_daysOverdrawn() {
    return _daysOverdrawn;
  }

  public void set_daysOverdrawn(int _daysOverdrawn) {
    this._daysOverdrawn = _daysOverdrawn;
  }
}

Por último movemos el método overdraftCharge() a la clase AccountType:

public class Account {
  private AccountType _type;
  private int _daysOverdrawn;

  double bankCharge() {
    double result = 4.5;
    if (get_daysOverdrawn() > 0) {
      result += overdraftCharge();
    }
    return result;
  }

  public AccountType get_type() {
    return _type;
  }

  public void set_type(AccountType _type) {
    this._type = _type;
  }

  public int get_daysOverdrawn() {
    return _daysOverdrawn;
  }

  public void set_daysOverdrawn(int _daysOverdrawn) {
    this._daysOverdrawn = _daysOverdrawn;
  }
}

public class AccountType {
  [...]
  double overdraftCharge() {
    if (get_type().isPremium()) {
      double result = 10;
      if (get_daysOverdrawn() > 7) {
        result += (get_daysOverdrawn() - 7) * 0.85;
      }
      return result;
    } else {
      return get_daysOverdrawn() * 1.75;
    }
  }
}

Written by Recacha

26 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Refactoring en Eclipse. (6) Remove Assignments to Parameters

with one comment

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Remove Assignments to Parameters

Es una mala práctica asignar valores a los parámetros de entrada de un método, porque el código resultante puede llevar a confusión. Para evitar esto, es aconsejable marcar siempre los parámetros de entrada del método como final. Para aplicar esta refactorización bastará configurar Eclipse para que lo haga automáticamente de la siguiente forma:

  1. Entramos en Preferences > Java > Editors > Save Actions
  2. Marcar “Perform the selected actions on save” y “Additional actions”.
  3. Pulsar el botón “Configure…” y entrar en la pestaña “Code Style”. Abajo, en el apartado “Variable declarations”, marcar “Use modifier final where possible” y marcar “Parameter”.

Si estamos refactorizando un código existente, cuando guardemos la primera vez un cambio, Eclipse solo marcará como final los parámetros de entrada que NO sean reasignados dentro del método. Para el resto, se pueden seguir estos pasos:

  1. Añadir final a los parámetros de entrada que no lo tengan.
  2. Crear una variable temporal y asignarle el parámetro de entrada.
  3. Sustituir todos los usos del parámetro de entrada dentro del método por la nueva variable.

Ejemplo antes de refactorizar:

public void discount(int inputVal, int quantity, int yearToDate) {
  if (inputVal > 50) {
    inputVal -= 2;
  }
  // do something
}

Añadir final a todos los parámetros de entrada, crear la variable result y refactorizar:

public void discount(final int inputVal, final int quantity, final int yearToDate) {
  int result = inputVal;
  if (result > 50) {
    result -= 2;
  }
  // do something
}

Written by Recacha

24 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Refactoring en Eclipse. (5) Introduce Explaining Variable

with one comment

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Introduce Explaining Variable

Si tenemos expresiones complejas, puede resultar interesante crear una variable temporal con un nombre explicativo, lo que favorecerá la legibilidad del código. Para aplicar este refactoring en Eclipse, seguiremos los siguientes pasos:

  1. Seleccionar la expresión a sustituir.
  2. SHIFT + ALT + L (o bien, click derecho > Refactor > Extract Local Variable…)
  3. Dar un nombre a la nueva variable y marcar ambos checks, para que sustituya todas las apariciones de la expresión y declare la variable como final.

Ejemplo antes de refactorizar:

public void test() {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
      (browser.toUpperCase().indexOf("IE") > -1) &&
      wasInitialized() && resize > 0 ) {
    // do something
  }
}

Refactorizamos las expresiones del if:

public void test() {
  final boolean isMacOS = platform.toUpperCase().indexOf("MAC") > -1;
  final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
  final boolean wasResized = resize > 0;

  if (isMacOS && isIEBrowser && wasInitialized() && wasResized ) {
    // do something
  }
}

Written by Recacha

22 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Refactoring en Eclipse. (4) Replace Temp with Query

with one comment

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Replace Temp with Query

Partimos de una expresión cuyo resultado almacenamos en una variable temporal; con esta refactorización se pretende extraer dicha expresión a un método. Para aplicarlo en Eclipse, seguiremos los siguientes pasos:

  1. Poner la variable a reemplazar como final. Si no está siendo reasignada con otro valor no aparecerá ningún error de compilación, por lo que podremos continuar.
  2. Aplicar Extract Method a la expresión (Refactor > Extract Method)
  3. Aplicar Inline Temp a la variable (Refactor > Inline)

Ejemplo antes de refactorizar (nótese que basePrice se ha marcado como final para comprobar que no está siendo reasignada):

public double test() {
  final double basePrice = _quantity * _itemPrice;
  if (basePrice > 1000) {
    return basePrice * 0.95;
  } else {
    return basePrice * 0.98;
  }
}

Aplicamos Extract Method a la expresión _quantity * _itemPrice:

public double test() {
  final double basePrice = basePrice();
  if (basePrice > 1000) {
    return basePrice * 0.95;
  } else {
    return basePrice * 0.98;
  }
}

private double basePrice() {
  return _quantity * _itemPrice;
}

Por último, aplicamos Inline Temp a la variable temporal basePrice:

public double test() {
  if (basePrice() > 1000) {
    return basePrice() * 0.95;
  } else {
    return basePrice() * 0.98;
  }
}

private double basePrice() {
  return _quantity * _itemPrice;
}

Written by Recacha

20 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Refactoring en Eclipse. (3) Inline Temp

with 2 comments

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Inline Temp

Si una variable temporal solo se usa para almacenar el resultado de una llamada a un método, podemos sustituirla por la propia llamada y eliminar la variable. Para aplicar este refactoring en Eclipse, seguiremos los siguientes pasos:

  1. Marcar la variable como final para asegurarnos que no se está reasignando más adelante. Si no hay errores de compilación, continuamos.
  2. Seleccionar la variable a sustituir.
  3. SHIFT + ALT + I (o bien, click derecho > Refactor > Inline…)

Ejemplo antes de refactorizar:

public boolean test() {
  double basePrice = anOrder.basePrice();
  return (basePrice > 1000);
}

Seleccionamos la variable basePrice y refactorizamos con Eclipse, quedando así:

public boolean test() {
  return (anOrder.basePrice() > 1000);
}

Written by Recacha

18 agosto 2012 at 1:00

Publicado en Refactoring

Tagged with , ,