Recientemente realicé una refactorización de un proyecto de tamaño mediano en Java para volver y agregar pruebas unitarias. Cuando me di cuenta de lo difícil que era burlarse de los solteros y las estadísticas, finalmente "entendí" lo que he estado leyendo sobre ellos todo este tiempo. (Soy una de esas personas que necesita aprender de la experiencia. Oh, bueno).
Entonces, ahora que estoy usando Spring para crear los objetos y conectarlos, me estoy deshaciendo de las static
palabras clave izquierda y derecha. (Si pudiera querer burlarme de él, no es realmente estático en el mismo sentido que Math.abs (), ¿verdad?) La cuestión es que me había acostumbrado a usar static
para denotar que un método no confiaba en cualquier estado del objeto. Por ejemplo:
//Before
import com.thirdparty.ThirdPartyLibrary.Thingy;
public class ThirdPartyLibraryWrapper {
public static Thingy newThingy(InputType input) {
new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
}
}
//called as...
ThirdPartyLibraryWrapper.newThingy(input);
//After
public class ThirdPartyFactory {
public Thingy newThingy(InputType input) {
new Thingy.Builder().withInput(input).alwaysFrobnicate().build();
}
}
//called as...
thirdPartyFactoryInstance.newThingy(input);
Entonces, aquí es donde se pone sensible. Me gustaba la vieja manera porque la letra mayúscula me decía que, al igual que Math.sin (x), ThirdPartyLibraryWrapper.newThingy (x) hacía lo mismo de la misma manera cada vez. No hay estado de objeto para cambiar cómo hace el objeto lo que le pido que haga. Aquí hay algunas respuestas posibles que estoy considerando.
- Nadie más se siente así, así que hay algo mal conmigo. ¡Tal vez no he internalizado realmente la forma OO de hacer las cosas! Tal vez estoy escribiendo en Java pero pensando en FORTRAN o somesuch. (Lo cual sería impresionante ya que nunca he escrito FORTRAN).
- Tal vez estoy usando la estática como una especie de proxy para la inmutabilidad con el propósito de razonar sobre el código. Dicho esto, ¿qué pistas debo tener en mi código para que alguien venga a mantenerlo para saber qué tiene estado y qué no?
- ¿Quizás esto debería ser gratis si elijo buenas metáforas de objetos? por ejemplo
thingyWrapper
, no parece que tenga un estado independiente de la envoltura,Thingy
que puede ser mutable. Del mismo modo, unthingyFactory
sonido debería ser inmutable, pero podría tener diferentes estrategias que se eligen en la creación.
En mi opinión, lo que usted está diciendo (todas las funciones estáticas son nulipotentes) es una buena forma de escribir código en la mayoría de los casos, pero no creo que cuando observe una función estática deba suponer automáticamente que no tiene efectos secundarios. . La situación puede ser más compleja; tomemos, por ejemplo, la función
Class.forName(String)
que parece no tener estado pero que en realidad carga una clase en la memoria y eventualmente crea instancias de campos estáticos / ejecuta el inicializador estático; este es un ejemplo de función idempotente (las llamadas eventuales después de la primera no hacen ninguna diferencia) pero no es una función pura (no se puede decir que no tenga efectos secundarios). Esta también es una buena opción, pero puede haber casos en los que tres llamadas distintas a la misma función produzcan tres resultados diferentes; por ejemplo si llamasThread.currentThread()
en una aplicación multiproceso no hay garantía de que recibirá el mismo hilo cada vez.Una solución adecuada es documentar (Javadoc por ejemplo); Además, del nombre de la función y de lo que hace a veces se puede inferir que la función estática es una función pura. Por ejemplo, no hay razón para que alguien crea que
Assert.assertTrue(boolean)
desde JUnit cambiaría algún estado en alguna parte. Por otro lado, cuandoSystem.clearProperty(String)
se llama a una función como , es bastante obvio que habrá efectos secundarios.fuente
Puedes hacerlos estáticos. FxCop en el mundo de C # lo empujará a hacer cosas estáticas que no hagan variables miembro de referencia. Esto es lo correcto (generalmente).
Moverlos a instancias quizás no sea el enfoque correcto. En cambio, desacople las dependencias de los métodos estáticos de las clases que los usan. Puede probar los métodos estáticos de forma aislada y luego reemplazar la dependencia de los consumidores cuando necesiten probarse.
fuente