2010-02-09 8 views
11

Prefiero usar variables locales en lugar de múltiples llamadas al mismo método.Estilo de codificación Java, variables locales frente a llamadas al método repetido

/* 
* I prefer this 
*/ 
Vehicle vehicle = person.getVehicle() 
if (vehicle instanceof Car) { 
    Car car = (Car) vehicle; 
    car.openSunroof(); 
} else if (vehicle instanceof Bike) { 
    Bike bike = (Bike) vehicle; 
    bike.foldKickstand(); 
} 
/* 
* Rather than this 
*/ 
if (person.getVehicle() instanceof Car) { 
    Car car = (Car) person.getVehicle(); 
    car.openSunroof(); 
} else if (person.getVehicle() instanceof Bike) { 
    Bike bike = (Bike) person.getVehicle(); 
    bike.foldKickstand(); 
} 
  • creo que la primera forma en que se va a realizar un poquito más rápido
  • creo que la segunda manera viola el principio DRY
  • me parece la primera manera más legible y fácil de depurar (... OK insignificante porque podía pasar por encima)
  • yo no quiero tener que hacer frente a la posibilidad de cambio de estado de objeto

¿Cuál prefieres y por qué?

Respuesta

3

Sí, el primero es definitivamente mejor. Yo nunca iría por el segundo método. Pero debería pensar en usar polimorfismo más. Confiar en instanceof tan pesado no es bueno diseño de OO.

+2

Buen punto, eso podría hacerlo aún más limpio. Pero entonces podría estar buscando una interfaz común, como prepareForJourney(), que podría implementarse por separado en cada clase. Sin embargo, a menudo trabajamos con clases heredadas o de terceros que pueden no ser aptas para aplicar fácilmente una interfaz nueva, pero supongo que podrían incluirse y aplicar la interfaz al contenedor. – crowne

8

Prefiero la primera versión por todas las razones que ha mencionado. En particular (solo para deletrear su cuarto punto), significa que definitivamente obtendrá resultados consistentes ... podría obtener resultados horriblemente desagradables con la segunda versión si getVehicle() devolviera Car en la primera llamada, luego Bike en el segundo ...

El lado del rendimiento no me molesta (felizmente llamaré al List.size() repetidamente, por ejemplo) pero la legibilidad, la coherencia y la no repetición son mucho más importantes. Básicamente, el primer fragmento transmite la idea de "obtener un valor, luego usarlo" mucho más efectivamente que el segundo.

Así que sí, estoy contigo ... ¿alguien te recomienda el segundo formulario?

+1

Creo que Martin Fowler recomienda la segunda forma de facilitar la refabricación. (En mi opinión, refactorizar debería hacer que el código sea más fácil de seguir, no más difícil.) –

+0

@Jon, ¿harías lo mismo con una propiedad en C#? – finnw

+0

Vi algunos defensores de las llamadas al método getter en este hilo http://stackoverflow.com/questions/1923795/java-method-invocation-vs-using-a-variable – crowne

1

Estoy de acuerdo, pero también trato de reducir el uso de 'instanceof' también, en el nivel de diseño de clase.

1

Personalmente creo que el primero es más limpio. Sin embargo, siempre que el método llamado no sea algo de computación intensivo, no importa mucho.

Probablemente, el segundo es un poco más rápido (si usa Java 1.6) porque en el primer ejemplo hace una copia de la variable, mientras que la VM java probablemente incorporará la llamada a la función en ambos ejemplos. Por supuesto, la optimización nunca es un argumento con llamadas como esta. El compilador hace tantas optimizaciones que no deberíamos molestarnos (a menudo solo reducirá la velocidad porque no la conocemos lo suficientemente bien).

2

Normalmente no me gusta la introducción de variables adicionales ya que cada bit de estado agregado hace que un método sea más complejo. Pero incluso yo diría que está garantizado en su ejemplo ya que la variable reemplaza 4 repeticiones de código idéntico.

Pero la variable debería ser definitivamente final!

+1

+1 para 'final'. – uckelman

1

Como todos los que respondieron esta pregunta hasta ahora, definitivamente prefiero el primer estilo. Sin embargo, puede ser incluso más limpio:

Vehicle vehicle = person.getVehicle() 
if (vehicle instanceof Car) { 
    ((Car) vehicle).openSunroof(); 
} else if (vehicle instanceof Bike) { 
    ((Bike) vehicle).foldKickstand(); 
} 
1

Ambos ejemplos necesitan algo de trabajo. Intente llevar el comportamiento a un método abstracto (o protegido) en el Vehículo.Si se trata de un código que no puede modificar, utilice la composición para colocarlo dentro de una interfaz en su base de código, de modo que no tenga que contaminar el resto del código con el diseño deficiente de la biblioteca que está utilizando. Esto es definitivamente un olor a código. Consulte "Reemplazar condicionalmente por polimorfismo" en el libro Refactorización de Fowler.

Cuestiones relacionadas