2011-07-16 11 views
22

Basta con leer esto en el sitio dev:Rendimiento Android - 'Evitar interna getters/setters'

Avoid Internal Getters/Setters

En lenguas nativas como C++ es una práctica común utilizar captadores (por ejemplo, i = getCount()) en lugar de acceder al campo directamente (i = mCount). Este es un hábito excelente para C++, ya que el compilador generalmente puede alinear el acceso, y si necesita restringir o depurar el acceso al campo, puede agregar el código en cualquier momento.

En Android, esta es una mala idea. Las llamadas a métodos virtuales son costosas, mucho más que las búsquedas de campo de instancias. Es razonable seguir prácticas comunes de programación orientada a objetos y tener getters y setters en la interfaz pública, pero dentro de una clase siempre se debe acceder directamente a los campos.

Sin un JIT, el acceso directo al campo es aproximadamente 3 veces más rápido que invocar un getter trivial. Con el JIT (donde el acceso directo en el campo es tan barato como acceder a un local), el acceso directo al campo es aproximadamente 7 veces más rápido que invocar un getter trivial. Esto es cierto en Froyo, pero mejorará en el futuro cuando el JIT incorpore métodos getter.

Así que está diciendo que usaría el acceso de campo dentro de la clase:

public class MyObject { 

    public Object innerObject; // This would be private if I was using a getter 

    public void doSomeStuff(){ 
      if(innerObject){  // Within class access like this 
       // .... 
      } 
    } 

    public Object getInnerObject(){ // This would be removed if I was using field access 
     return innerObject; 
    } 
} 

Pero ¿qué pasa con el acceso de otro objeto:?

public class SecondObject { 

     public void doSecondSomething(){ 
       MyObject ob = new MyObject(); 
       Object inner; 

       //This is my question basically (from an Android performance perspective) 
       inner = ob.getInnerObject(); 
       // OR 
       inner = b.innerObject 

     } 

} 
+0

Solo para señalar esto, recuerde que Dalvik no es JVM y esta práctica no debe tomarse como una forma general de hacer en el desarrollo normal de Java. – Esko

+1

Su cita lo dice todo, ¿verdad? ** Es razonable seguir prácticas comunes de programación orientada a objetos y tener getters y setters en la interfaz pública **. Además: no vayas por exceso de diseño. Simplemente use el getter a menos que haga una gran cantidad de llamadas. o tiene un problema de velocidad. – Nanne

Respuesta

27

El impacto en el rendimiento de la utilización de captadores y definidores internos también se aplica a captadores y definidores externos.

Sin embargo, en el caso externo los getters y setters tienen beneficios significativos en otras áreas; p.ej. preservando la encapsulación, reduciendo el acoplamiento dañino, haciendo que su código sea más fácil de mantener, y así sucesivamente. Por lo tanto, generalmente se considera como mejor práctica utilizar getters y setters a pesar del impacto en el rendimiento que esto pueda ocasionar.

El golpe de rendimiento es un resultado de las limitaciones de la generación actual de compiladores JIT de Android anteriores. Esta situación seguramente mejorará ha mejorado con Gingerbread. (Referencia - https://stackoverflow.com/a/4930538/139985 ... y tenga en cuenta quién escribió esa respuesta!)

En general, es una mala idea "ajustar" su código para una plataforma inferior, especialmente si hay una posibilidad razonable de que una mejor esté a la vista.

+0

Espera, ¿el JIT de Android no hace llamadas de función triviales en línea? Me refiero a que es una de LAS optimizaciones básicas para cualquier JIT - seguro que tiene que asegurarse de que la clase no se sobrescribió y demás, pero eso es 99/100 fácil. Difícil de creer. – Voo

+1

@Voo: razones comerciales pueden hacer que sea necesario entregar algo con una segunda tasa ahora que esperar 6 meses hasta que sea la 1ra. Lo mismo sucedió con Java y Javascript (y Windows Vista, y ...). Es solo "difícil de creer" si ignoras la historia. –

+0

Ship It! @StephenC es bueno para la actualización – Blundell

3
// this is faster 
inner = b.innerObject 

// but this won't hurt performance much because 
// it's assumed that it will be rare 
inner = ob.getInnerObject(); 
4

Aunque b.innerObject es más rápido, a medida que avanza la tecnología (mejor CPU, JIT, etc.) la diferencia entre el dos opciones se hacen más pequeñas

El único punto donde puede importar es cuando se realiza en ciclos intensivos que se ejecutan todo el tiempo. Por ejemplo, en el método onDraw de un juego, cuando recorre cientos de objetos.

3

Tenga en cuenta que esas consideraciones de rendimiento son relevantes solo si se accede al miembro en cuestión miles de veces por segundo.

Un buen ejemplo donde el acceso directo puede ser una buena idea es la scenegraph de un juego (libgdx)

public abstract class Actor { 
    public Group parent; 
    public final String name; 
    public boolean touchable = true; 

    public float x; 
    public float y; 
    public float width; 
    public float height; 
    public float originX; 
    public float originY; 
    public float scaleX = 1; 
    public float scaleY = 1; 
    public float rotation; 
    public final Color color = new Color(1, 1, 1, 1); 
2

Getters y Setters siempre tienen una sobrecarga, ya que son llamadas a funciones. Cuando está en el mismo objeto, puede optimizar su código al no usarlo, ya que sabe para qué se utiliza y no necesita abstraerlo/encapsularlo de su propio objeto.

Creo que también hay que mirarlo desde una perspectiva diferente:

  1. a no quieren tener un captador/definidor romper las prácticas comunes Oops? No querrá tener referencias directas si está creando objetos/módulos que otros usarán.

  2. Realmente no desea utilizar getters/setters demasiadas veces como al final, a menos que el sh! * Sea optimizado fuera de las llamadas de función tendrá sobrecarga.

Usted realmente necesita para optimizar de forma percase, si yo estoy construyendo dos módulos donde algunos componentes son accesibles únicamente por sí podría hacer un campo estático demás que se adherirá a getters/setters

+1

"Getters y Setters siempre tienen una sobrecarga, ya que son llamadas a funciones" no es cierto en ningún JIT moderno - en Hotspot que estaría en línea, excepto en algunos casos raros (es decir, el colocador realmente se sobrescribe en subclase Y el jit no puede asegurar una de la identidad del objeto - o dicho de otra manera, casi nunca) – Voo

2

En cuanto a rendimiento, no hay diferencia en el acceso a this.field o that.field.

La sensación de que un campo de instancia es más accesible para el objeto que la aloja es solo una ilusión de sintaxis.

OO sabio, en serio, ¿cuán compleja puede ser una aplicación para Android? Muchos de los mantras de OO provienen de la construcción de aplicaciones de monstruos. ¿Cuál es el problema si su pequeña aplicación usa objetos como estructuras?

E incluso en una gran aplicación, mientras esté en casa, y todo el código fuente que accede a un campo está disponible para la refactorización, no hay ningún problema en exponer los campos.

0

Para el registro, otro problema con setter y getter (en Java) es que son dolorosamente feo de usar.

Digamos que el siguiente ejercicio, tenemos que modificar una información privilegiada campo de un campo de un objeto

en Java es:

object.getField().getSubField().setField3("hello"); // ugly 

Mientras que en C# el mismo código es (incluso con la encapsulación)

object.Field.SubField.Field3="hello"; // fine 

por lo tanto, utilizando el campo público en Java (o androide) es mucho más limpio:

object.field.subfield.field3="hello"; // fine too 
+1

ah, pero este es el antipatrón TrainWreck, solo hable con su vecino más cercano y tenga el código 'object.setField3 (" hello "); 'http://c2.com/cgi/wiki?TrainWreck – Blundell

+1

Encuentro que el paradigma getter/setter está muy por encima de la venta. El 99% del tiempo son simplemente pass-through a la variable miembro. Si planea implementar ambos, simplemente omita el getter/setter y haga que la variable sea pública. Los ingenieros citan constantemente una buena encapsulación (o más específicamente, aislamiento) como el principal beneficio de getter/setter. El código queda ligado a la sintaxis de su getter/setter que es idéntico a la vinculación a la variable miembro de la clase. Entonces no hay ganancia. La ganancia es si cambia la implementación en el futuro o sobrecargas de clases derivadas. Cuando eso ocurra, haga getter/setter – user1959190

+0

@ user1959190 Exactamente. Sin embargo, no estoy de acuerdo con el comentario sobre los ingenieros. Un verdadero ingeniero se centra en eficiencias y resultados. De hecho, un ingeniero experimentado hace trampas mucho. Sin embargo, hay tantos programadores que no son ingenieros, sino que están más cerca de los científicos. Utilizo setter y getter porque es el estándar y el trabajo en equipo. Sin embargo, me avergüenzo porque es inútil en el 99% del tiempo, y cuando es útil, oculta la implementación y es realmente peligroso. – magallanes

Cuestiones relacionadas