A menudo me enfrento con clases auxiliares o de utilidad en Java o cualquier tipo de lenguaje. Entonces me preguntaba si esto es algún tipo de Anti Pattern y la existencia de este tipo de clases es solo una falta de fallas en el diseño y la arquitectura de un Software.
A menudo, estas clases se limitan utilizando solo métodos estáticos, que hacen muchas cosas. Pero sobre todo depende del contexto y tiene estado.
Mi pregunta es, ¿cuál es su opinión sobre este tipo de clases auxiliares / util estáticas porque la ventaja es, por supuesto, la invocación rápida usando solo el nombre de la clase?
¿Y a qué tipo de abstracción evitarías usar este tipo de clases?
En mi opinión, la palabra clave "estática" debería permitirse dentro de la declaración de una clase (Java) y no para los métodos. En mi opinión, usarlo de esta manera podría ser una buena alternativa y un medio para poder combinar Procuedural- y OO-Paradigms en Java y evitar el mal uso de la palabra clave.
Adiciones debido a las respuestas:
Al principio, creo que es completamente legal poder combinar diferentes paradigmas e incluso usar lenguajes de script interpretados en tiempo de ejecución dentro de código compilado de máquina o vm.
Mi experiencia es que durante el proceso de desarrollo de un proyecto, este tipo de ayudantes y utilidades, o como se llame, crecen y crecen y se usan en cada rincón olvidado de la base de código, que originalmente fue diseñada para ser modular y flexible. Y debido a la falta de tiempo para hacer refactorizaciones o pensar en el diseño nuevamente, solo lo empeora mucho con el tiempo.
Creo que static
debería eliminarse de Java. Especialmente ahora donde es posible usar elementos de lenguaje funcional aún más sofisticados.
fuente
Respuestas:
Bueno, Java carece de funciones gratuitas, por lo que se ve obligado a colocarlas como funciones estáticas en alguna clase pro forma. Una solución necesaria nunca es un antipatrón, aunque puede carecer de elegancia.
A continuación, no hay nada de malo con las funciones gratuitas. En realidad, el uso de funciones gratuitas reduce el acoplamiento, ya que solo tienen acceso a la interfaz pública en lugar de todos los detalles sangrientos.
Por supuesto, el uso de funciones libres / estáticas no alivia de ninguna manera los peligros del estado compartido mutable, especialmente global.
fuente
this
, y requieren que algo sea instanciado adecuadamenteLa utilidad estática o las funciones auxiliares no son un antipatrón si cumplen con algunas pautas:
Deben estar libres de efectos secundarios.
Se utilizan para el comportamiento específico de la aplicación que no pertenece a la clase o clases en las que operan estas funciones
No requieren ningún estado compartido
Casos de uso común:
Por ejemplo, en una aplicación en la que trabajé, los usuarios mantienen entradas de diario para sus actividades. Pueden especificar una fecha de seguimiento y descargar un recordatorio de evento. Creamos una clase de utilidad estática para tomar una entrada de diario y devolver el texto sin formato para un archivo .ics.
No requería ningún estado compartido. No mutó ningún estado, y crear un evento iCal ciertamente fue específico de la aplicación y no pertenecía a la clase de entrada de diario.
Si las funciones estáticas o las clases de utilidad tienen efectos secundarios o requieren un estado compartido, recomendaría reevaluar este código, ya que introduce un acoplamiento que puede ser difícil de burlar para las pruebas unitarias.
fuente
Dependerá de su enfoque. Muchas aplicaciones se escriben con una mentalidad más funcional, en oposición a la clásica (incluyendo gran parte del conjunto de sitios en los que se encuentra).
Con esta mentalidad, habrá muchos métodos de utilidad en las clases de trabajo que se pueden agrupar como métodos estáticos. Se alimentan / usan más cerca de objetos simples que solo contienen datos y se transmiten.
Es un enfoque válido y puede funcionar muy bien, especialmente a escala.
fuente
Agent.Save(obj)
vsagentInstance.Save(obj)
. Con este último tienes la posibilidad de inyectaragentInstance
en el código de uso. En consecuencia, puede inyectar cualquier clase secundaria deAgent
lo que permite la reutilización del código de uso con diferentes "tipos" deAgent
sin recompilar. Esto es de bajo acoplamiento .Personalmente, creo que la única parte importante de estas clases de ayuda es que se hagan privadas. Además de eso, son estrictamente una buena idea (aplicada con moderación).
La forma en que pienso sobre esto, es si al implementar una clase (o función), algo como esto es útil y aclara esa implementación, ¿cómo podría ser malo? Y A MENUDO es crítico definir tales clases de ayuda privadas para permitir la integración y el uso de otros algoritmos que dependen de que los datos estén en una forma particular.
Si etiquetarlo como 'ayudante' es una pequeña cuestión de gusto personal, pero connota que ayuda en la implementación y no es de interés / uso para un público más amplio. Si eso es lo que tiene sentido, ¡adelante!
fuente
java.lang.Math
.La prevalencia de las
static
clases auxiliares se basa en un concepto erróneo. El hecho de que llamemos a las clases con solostatic
métodos "clases de utilidad" no significa que no esté permitido escribir comportamientos comunes en POJO.static
Las clases auxiliares son antipatrón por tres razones:El acceso estático a estos métodos auxiliares oculta las dependencias . Si estas "clases de utilidad" fueran POJOs, podría inyectarlas int a una clase dependiente como parámetros de construcción, lo que haría obvia la dependencia para cualquier usuario de una clase dependiente.
El acceso estático a estos métodos auxiliares provoca un acoplamiento estrecho . Esto significa que el código que usa los métodos auxiliares es difícil de reutilizar y (como efecto secundario) difícil de probar.
Especialmente si mantienen el estado, estas son meramente variables globales . Y con suerte nadie argumenta que las variables globales son buenas ...
Las clases auxiliares estáticas son parte del patrón anti código STUPID .
El OP escribió:
Las construcciones con estado estático son estados globales.
Si de causa. Y casi todas las aplicaciones necesitan algún tipo de estado global .
¡Pero estado global ! = Variable global .
Puede crear un estado global con técnicas OO mediante la inyección de dependencia. Pero no puede evitar el estado global con estructuras estáticas con estado que son variables globales en la parte inferior.
fuente
Func<Result, Args>
objetos, que se instancian en otros lugares.