¿Los métodos init () son un código de olor?

13

¿Hay algún propósito para declarar un método init() para un tipo?

No estoy preguntando si deberíamos preferimos init() over un constructor o cómo evitar declarar init() .

Estoy preguntando si hay una razón fundamental para detrás de declarar un método init() (viendo lo común que es) o si es un olor de código y debería evitarse.

El idioma init() es bastante común, pero aún no he visto ningún beneficio real.

Estoy hablando de tipos que fomentan la inicialización a través de un método:

class Demo {
    public void init() {
        //...
    }
}

¿Cuándo será esto útil en el código de producción?

Siento que puede ser un olor de código ya que sugiere que el constructor no inicializa completamente el objeto, lo que resulta en un objeto parcialmente creado. El objeto no debería existir si su estado no está establecido.

Esto me hace creer que puede ser parte de algún tipo de técnica utilizada para acelerar la producción, en el sentido de las aplicaciones empresariales. Es la única razón lógica por la que puedo pensar en tener tal lenguaje, pero no estoy seguro de cómo sería beneficioso si es así.

    
pregunta Vince Emigh 31.10.2016 - 07:24

9 respuestas

32

Sí, es un olor de código. Un olor a código no es algo que necesariamente siempre necesita ser eliminado. Es algo que te hace echar un segundo vistazo.

Aquí tienes un objeto en dos estados fundamentalmente diferentes: pre-init y post-init. Esos estados tienen diferentes responsabilidades, diferentes métodos que pueden llamarse y diferentes comportamientos. Son efectivamente dos clases diferentes.

Si físicamente los creas en dos clases separadas, eliminarás de forma estática toda una clase de posibles errores, al costo de que tu modelo no coincida con el "modelo del mundo real" tan estrechamente. Por lo general, nombras el primero Config o Setup o algo así.

La próxima vez, intente refactorizar los modismos construct-init en modelos de dos clases y vea cómo resultan para usted.

    
respondido por el Karl Bielefeldt 31.10.2016 - 14:05
13

Depende.

Un método init es un olor de código cuando no es necesario separar la inicialización del objeto del constructor. A veces hay casos en los que tiene sentido separar estos pasos.

Una rápida búsqueda en Google me consiguió este ejemplo. Puedo imaginar fácilmente más casos en los que el código ejecutado durante la asignación de objetos (el constructor) podría separarse de la inicialización. Quizás tenga un sistema nivelado y la asignación / construcción tenga lugar en el nivel X, pero la inicialización solo en el nivel Y, porque solo Y puede proporcionar los parámetros necesarios. Tal vez el "init" es costoso y debe ejecutarse solo para un subconjunto de los objetos asignados, y la determinación de ese subconjunto solo se puede hacer en el nivel Y. O si desea reemplazar el método "virtual" (virtual) en un derivado clase que no se puede hacer con un constructor. Tal vez el nivel X le proporciona objetos asignados de un árbol de herencia, pero el nivel Y no es consciente de la derivación concreta, solo acerca de la interfaz común (donde init puede estar definido).

Por supuesto, para mi experiencia, estos casos son solo un pequeño porcentaje del caso estándar donde toda la inicialización se puede hacer directamente en el constructor, y cada vez que vea un método init por separado, podría ser una buena idea cuestionar su necesidad.

    
respondido por el Doc Brown 31.10.2016 - 07:42
5

Mi experiencia se divide en dos grupos:

  1. Código donde se requiere init (). Esto puede ocurrir cuando una superclase o marco impide que el constructor de su clase obtenga todas sus dependencias durante la construcción.
  2. Código donde se usa init () pero podría haberse evitado.

En mi experiencia personal, he visto solo algunos ejemplos de (1) pero muchos más ejemplos de (2). En consecuencia, generalmente asumo que un init () es un olor de código, pero no siempre es así. A veces no puedes evitarlo.

He encontrado que el uso del Builder Pattern puede ayudar a eliminar la necesidad / deseo de tener un init (). / p>     

respondido por el Ivan 31.10.2016 - 14:11
1

Un escenario típico cuando un método Init es útil es cuando tiene un archivo de configuración que desea cambiar y que se tenga en cuenta el cambio sin reiniciar la aplicación. Esto, por supuesto, no significa que un método Init deba llamarse por separado desde un constructor. Podría llamar a un método Init desde un constructor, y luego llamarlo más tarde cuando / si los parámetros de configuración cambian.

Para resumir: en cuanto a la mayoría de los dilemas que existen, si este es un olor a código o no, depende de la situación y las circunstancias.

    
respondido por el Vladimir Stokic 31.10.2016 - 11:36
1

Depende de cómo los uses.

Utilizo ese patrón en lenguajes de recolección de basura como Java / C # cuando no quiero seguir reasignando un objeto en el montón (como cuando estoy haciendo un videojuego y necesito mantener el rendimiento alto, los recolectores de basura matan el rendimiento ). Utilizo el constructor para realizar otras asignaciones de almacenamiento dinámico que necesita, y init para crear el estado útil básico justo antes de cada vez que quiera reutilizarlo. Esto está relacionado con el concepto de grupos de objetos.

También es útil si tiene varios constructores que comparten un subconjunto común de instrucciones de inicialización, pero en ese caso init será privado. De esa manera puedo minimizar cada constructor tanto como sea posible, por lo que cada uno solo contiene sus instrucciones únicas y una única llamada a init para hacer el resto.

En general, sin embargo, es un olor de código.

    
respondido por el Cody 31.10.2016 - 23:45
1
Los métodos de

init() pueden tener bastante sentido cuando tiene objetos que necesitan recursos externos (como, por ejemplo, una conexión de red) que otros objetos utilizan simultáneamente. Es posible que no desee / necesite acaparar el recurso durante la vida útil del objeto. En tales situaciones, es posible que no desee asignar el recurso en el constructor cuando es probable que la asignación de recursos falle.

Especialmente en la programación incorporada, desea tener una huella de memoria determinista, por lo que es una práctica común (¿buena?) llamar a sus constructores antes, quizás incluso estáticos, y solo inicializar más tarde cuando se cumplen ciertas condiciones.

Aparte de estos casos, creo que todo debería ir a un constructor.

    
respondido por el tofro 31.10.2016 - 10:18
0

Generalmente prefiero un constructor que recibe todos los argumentos necesarios para una instancia funcional. Eso deja en claro todas las dependencias de ese objeto.

Por otro lado, uso un marco de configuración simple que requiere un constructor público sin parámetros, e interfaces para inyectar dependencias y valores de configuración. Una vez hecho esto, el marco de configuración llama al método init del objeto: ahora que recibió todas las cosas que tengo para usted, haga los últimos pasos para prepararse para el trabajo. Pero tenga en cuenta: es el marco de configuración que llama automáticamente al método init, por lo que no olvidará llamarlo.

    
respondido por el Bernhard Hiller 31.10.2016 - 09:28
0

No hay olor de código si el método init () está integrado semánticamente en el ciclo de vida del estado del objeto.

Si necesita llamar a init () para poner el objeto en un estado consistente, es un olor de código.

Existen varias razones técnicas para que exista tal estructura:

  1. gancho de la estructura
  2. restablecer el objeto al estado inicial (evitar redundancia)
  3. posibilidad de anular durante las pruebas
respondido por el oopexpert 31.10.2016 - 23:15
-4

El nombre init puede a veces ser opaco. Tomemos un coche y un motor. Para arrancar el automóvil (solo encender, escuchar la radio) desea verificar que todos los sistemas estén listos para funcionar.

Así que construyes un motor, una puerta, una rueda, etc. tu pantalla muestra engine = off.

No es necesario comenzar a monitorear el motor, etc., ya que son costosos. Luego, cuando gire la llave para encender, llame a engine- > comienzo. Comienza a ejecutar todos los procesos caros.

Ahora ves engine = on. Y comienza el proceso de encendido.

El automóvil no se enciende sin el motor disponible.

Puedes reemplazar el motor con tu cálculo complejo. Como una celda de Excel. No todas las celdas tienen que estar activas con todos los controladores de eventos todo el tiempo. Cuando te enfocas en una celda puedes comenzarla. Aumentar el rendimiento de esa manera.

    
respondido por el Luc Franken 31.10.2016 - 08:18

Lea otras preguntas en las etiquetas