Tiendo a declarar como estáticos todos los métodos de una clase cuando esa clase no requiere realizar un seguimiento de los estados internos. Por ejemplo, si necesito transformar A en B y no confío en algún estado interno C que puede variar, creo una transformación estática. Si hay un estado interno C que quiero poder ajustar, agrego un constructor para configurar C y no uso una transformación estática.
Leí varias recomendaciones (incluso en StackOverflow) para NO abusar de los métodos estáticos, pero aún no entiendo qué es lo que está mal con la regla general anterior.
¿Es un enfoque razonable o no?
Un objeto sin ningún estado interno es algo sospechoso.
Normalmente, los objetos encapsulan el estado y el comportamiento. Un objeto que solo encapsula el comportamiento es extraño. A veces es un ejemplo de peso ligero o mosca .
Otras veces, el diseño procedimental se realiza en un lenguaje de objetos.
fuente
En realidad, esto es solo una continuación de la gran respuesta de John Millikin.
Aunque puede ser seguro hacer que los métodos sin estado (que son prácticamente funciones) sean estáticos, a veces puede conducir a un acoplamiento que es difícil de modificar. Considere que tiene un método estático como tal:
Que llamas como:
Lo cual está muy bien, y es muy conveniente, hasta que se encuentra con un caso en el que tiene que modificar el comportamiento del método estático y descubre que está estrechamente vinculado a él
StaticClassVersionOne
. Posiblemente podría modificar el código y estaría bien, pero si hubiera otras personas que llamaran dependiendo del comportamiento anterior, deberán contabilizarse en el cuerpo del método. En algunos casos, el cuerpo del método puede volverse bastante feo o imposible de mantener si trata de equilibrar todos estos comportamientos. Si divide los métodos, es posible que deba modificar el código en varios lugares para tenerlo en cuenta o realizar llamadas a nuevas clases.Pero considere si ha creado una interfaz para proporcionar el método y se la ha dado a las personas que llaman, ahora, cuando el comportamiento debe cambiar, se puede crear una nueva clase para implementar la interfaz, que es más limpia, más fácil de probar y más fácil de mantener. y eso, en cambio, se le da a quienes llaman. En este escenario, las clases que llaman no necesitan ser modificadas o incluso recompiladas, y los cambios están localizados.
Puede que sea una situación probable o no, pero creo que vale la pena considerarla.
fuente
La otra opción es agregarlos como métodos no estáticos en el objeto de origen:
es decir, cambiando:
dentro
sin embargo, en muchas situaciones esto no es posible (por ejemplo, generación de código de clase regular desde XSD / WSDL / etc.), o hará que la clase sea muy larga, y los métodos de transformación a menudo pueden ser un verdadero dolor para los objetos complejos y solo los desea en su propia clase separada. Así que sí, tengo métodos estáticos en clases de utilidad.
fuente
Las clases estáticas están bien siempre que se utilicen en los lugares correctos.
A saber: métodos que son métodos "hoja" (no modifican el estado, simplemente transforman la entrada de alguna manera). Buenos ejemplos de esto son cosas como Path.Combine. Este tipo de cosas son útiles y hacen que la sintaxis sea más tersa.
Los problemas que tengo con la estática son numerosos:
En primer lugar, si tiene clases estáticas, las dependencias están ocultas. Considera lo siguiente:
Mirando TextureManager, no puede decir qué pasos de inicialización deben llevarse a cabo mirando un constructor. Debe profundizar en la clase para encontrar sus dependencias e inicializar las cosas en el orden correcto. En este caso, necesita que ResourceLoader se inicialice antes de ejecutarse. Ahora amplíe esta pesadilla de dependencia y probablemente pueda adivinar lo que sucederá. Imagínese tratando de mantener el código donde no hay un orden explícito de inicialización. Compare esto con la inyección de dependencias con instancias; en ese caso, el código ni siquiera se compilará si las dependencias no se cumplen.
Además, si usa estática que modifica el estado, es como un castillo de naipes. Nunca se sabe quién tiene acceso a qué, y el diseño tiende a parecerse a un monstruo espagueti.
Finalmente, e igualmente importante, el uso de estática vincula un programa a una implementación específica. El código estático es la antítesis del diseño para la prueba. Probar código plagado de estática es una pesadilla. Una llamada estática nunca se puede intercambiar por un doble de prueba (a menos que use marcos de prueba diseñados específicamente para simular tipos estáticos), por lo que un sistema estático hace que todo lo que lo usa sea una prueba de integración instantánea.
En resumen, las estáticas están bien para algunas cosas y para herramientas pequeñas o código desechable no desaconsejaría su uso. Sin embargo, más allá de eso, son una maldita pesadilla para el mantenimiento, el buen diseño y la facilidad de prueba.
Aquí hay un buen artículo sobre los problemas: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/
fuente
La razón por la que se le advierte de los métodos estáticos es que su uso pierde una de las ventajas de los objetos. Los objetos están destinados a la encapsulación de datos. Esto evita que se produzcan efectos secundarios inesperados, lo que evita errores. Los métodos estáticos no tienen datos encapsulados *, por lo que no obtienen este beneficio.
Dicho esto, si no tiene uso de datos internos, están bien de usar y son un poco más rápidos de ejecutar. Sin embargo, asegúrese de no tocar datos globales en ellos.
fuente
Ese parece ser un enfoque razonable. La razón por la que no desea utilizar demasiadas clases / métodos estáticos es que termina alejándose de la programación orientada a objetos y más hacia el ámbito de la programación estructurada.
En su caso en el que simplemente está transformando A en B, diga que todo lo que estamos haciendo es transformar el texto para pasar de
Entonces, un método estático tendría sentido.
Sin embargo, si está invocando estos métodos estáticos en un objeto con frecuencia y tiende a ser único para muchas llamadas (por ejemplo, la forma en que lo usa depende de la entrada), o es parte del comportamiento inherente del objeto, lo haría Sea prudente convertirlo en parte del objeto y mantener un estado del mismo. Una forma de hacerlo sería implementarlo como una interfaz.
Editar: Un buen ejemplo del gran uso de métodos estáticos son los métodos de ayuda html en Asp.Net MVC o Ruby. Crean elementos html que no están vinculados al comportamiento de un objeto y, por lo tanto, son estáticos.
Edición 2: se cambió la programación funcional a la programación estructurada (por alguna razón me confundí), apoyo a Torsten por señalar eso.
fuente
Recientemente refactoricé una aplicación para eliminar / modificar algunas clases que se habían implementado inicialmente como clases estáticas. Con el tiempo, estas clases adquirieron mucho y la gente siguió etiquetando las nuevas funciones como estáticas, ya que nunca hubo una instancia flotando.
Entonces, mi respuesta es que las clases estáticas no son inherentemente malas, pero podría ser más fácil comenzar a crear instancias ahora y luego tener que refactorizarlas más tarde.
fuente
Lo consideraría un olor a diseño. Si se encuentra utilizando principalmente métodos estáticos, probablemente no tenga un diseño de OO muy bueno. No es necesariamente malo, pero como con todos los olores, me haría detenerme y reevaluar. Sugiere que es posible que pueda hacer un mejor diseño de OO, o que tal vez debería ir en la otra dirección y evitar OO por completo para este problema.
fuente
Solía ir y venir entre una clase con un montón de métodos estáticos y un singleton. Ambos resuelven el problema, pero el singleton se puede reemplazar mucho más fácilmente con más de uno. (Los programadores siempre parecen tan seguros de que solo habrá 1 de algo y me equivoqué las veces suficiente para renunciar por completo a los métodos estáticos, excepto en algunos casos muy limitados).
De todos modos, el singleton te da la posibilidad de pasar algo más tarde a la fábrica para obtener una instancia diferente y eso cambia el comportamiento de todo tu programa sin refactorizar. Cambiar una clase global de métodos estáticos en algo con diferentes datos de "respaldo" o un comportamiento ligeramente diferente (clase secundaria) es un gran dolor de cabeza.
Y los métodos estáticos no tienen una ventaja similar.
Entonces sí, son malos.
fuente
Siempre que no entre en juego el estado interno, está bien. Tenga en cuenta que, por lo general, se espera que los métodos estáticos sean seguros para subprocesos, por lo que si usa estructuras de datos auxiliares, utilícelas de manera segura para subprocesos.
fuente
Si sabe que nunca necesitará utilizar el estado interno de C, está bien. Sin embargo, si eso alguna vez cambia en el futuro, deberá hacer que el método no sea estático. Si, para empezar, no es estático, puede simplemente ignorar el estado interno si no lo necesita.
fuente
Si es un método de utilidad, es bueno hacerlo estático. Guava y Apache Commons se basan en este principio.
Mi opinión al respecto es puramente pragmática. Si es el código de su aplicación, los métodos estáticos generalmente no son lo mejor que puede tener. Los métodos estáticos tienen serias limitaciones de prueba unitaria; no se pueden burlar fácilmente: no se puede inyectar una funcionalidad estática simulada en otra prueba. Por lo general, tampoco puede inyectar funcionalidad en un método estático.
Entonces, en la lógica de mi aplicación, generalmente tengo pequeñas llamadas a métodos de utilidad estática. Es decir
uno de los beneficios es que no pruebo tales métodos :-)
fuente
Bueno, por supuesto que no existe una fórmula mágica. Las clases estáticas están bien para pequeñas utilidades / ayudantes. Pero el uso de métodos estáticos para la programación lógica empresarial es ciertamente malo. Considere el siguiente código
Ves una llamada de método estático a
ItemsProcessor.SplitItem(newItem);
It huele porqueBusinessService
aislándolo deItemsProcessor
(la mayoría de las herramientas de prueba no simulan clases estáticas) y hace que las pruebas unitarias sean imposibles. Sin pruebas unitarias == baja calidadfuente
Los métodos estáticos son generalmente una mala elección incluso para código sin estado. En su lugar, cree una clase singleton con estos métodos que se instancia una vez y se inyecta en las clases que desean usar los métodos. Estas clases son más fáciles de burlar y probar. Están mucho más orientados a objetos. Puede envolverlos con un proxy cuando sea necesario. Las estáticas hacen que OO sea mucho más difícil y no veo ninguna razón para usarlas en casi todos los casos. No al 100%, pero casi todos.
fuente