Vi este hilo
Si una clase de "Utilidades" es mala, ¿dónde pongo mi código genérico?
y pensé ¿por qué son malvadas las clases de servicios públicos?
Digamos que tengo un modelo de dominio que tiene decenas de clases de profundidad. Necesito poder xml-ify instancias. ¿Hago un método toXml en el padre? ¿Hago una clase auxiliar MyDomainXmlUtility.toXml? Este es un caso en el que la necesidad empresarial abarca todo el modelo de dominio: ¿realmente pertenece como método de instancia? ¿Qué pasa si hay un montón de métodos auxiliares en la funcionalidad xml de la aplicación?
design-patterns
software-design
hvgotcodes
fuente
fuente
Respuestas:
Las clases de utilidad no son exactamente malas, pero pueden violar los principios que componen un buen diseño orientado a objetos. En un buen diseño orientado a objetos, la mayoría de las clases deberían representar una sola cosa y todos sus atributos y operaciones. Si está operando en una cosa, ese método probablemente debería ser miembro de esa cosa.
Sin embargo, hay ocasiones en las que puede usar clases de utilidades para agrupar varios métodos; un ejemplo es la
java.util.Collections
clase que proporciona una serie de utilidades que se pueden usar en cualquier colección de Java. Estos no son específicos de un tipo particular de colección, sino que implementan algoritmos que se pueden usar en cualquier colección.Realmente, lo que debe hacer es pensar en su diseño y determinar dónde tiene más sentido colocar los métodos. Por lo general, es como operaciones dentro de una clase. Sin embargo, a veces, es una clase de utilidad. Sin embargo, cuando utilice una clase de utilidad, no se limite a incluir métodos aleatorios en ella, sino que organice los métodos por propósito y funcionalidad.
fuente
Creo que el consenso general es que las clases de servicios públicos no son malas per se . Solo necesita usarlos con prudencia:
Diseñe los métodos de utilidad estática para que sean generales y reutilizables. Asegúrese de que sean apátridas; es decir, sin variables estáticas.
Si tiene muchos métodos de utilidad, divídalos en clases de manera que sea más fácil para los desarrolladores encontrarlos.
No use clases de utilidad donde los métodos estáticos o de instancia en una clase de dominio serían una mejor solución. Por ejemplo, considere si los métodos de una clase base abstracta o una clase auxiliar de la que se pueden crear instancias serían una mejor solución.
Para Java 8 en adelante, los "métodos predeterminados" en una interfaz pueden ser una mejor opción que las clases de utilidad. (Consulte Interfaz con métodos predeterminados frente a la clase abstracta en Java 8, por ejemplo).
La otra forma de ver esta Pregunta es observar que en la Pregunta citada, "Si las clases de utilidad son" malas "" es un argumento de paja. Es como si yo preguntara:
En la pregunta anterior, en realidad no estoy diciendo que los cerdos puedan volar ... o que estoy de acuerdo con la proposición de que podrían volar.
Las declaraciones típicas de "xyz es malvado" son recursos retóricos que tienen la intención de hacerte pensar planteando un punto de vista extremo. Rara vez (si es que alguna vez) se intentan como declaraciones de hechos literales.
fuente
Las clases de servicios públicos son problemáticas porque no agrupan las responsabilidades con los datos que las respaldan.
Sin embargo, son extremadamente útiles y los construyo todo el tiempo como estructuras permanentes o como peldaños durante una refactorización más completa.
Desde la perspectiva del Código Limpio , las clases de servicios públicos violan la Responsabilidad Única y el Principio Abierto-Cerrado. Tienen muchas razones para cambiar y, por diseño, no son extensibles. Realmente solo deberían existir durante la refactorización como cruft intermedio.
fuente
class
se utilice la palabra clave. Grazna como un espacio de nombres, camina como un espacio de nombres, es uno ...x.equals(y)
porque 1) el hecho de que esto realmente no debería modificar ningún estado no se transmite (y no puedo confiar en que no conozca la implementación) 2) Nunca tuve la intención de ponerx
un " posición favorecida "o" sobre la que se "actuó" en comparación cony
3) No quiero considerar las "identidades" de sus valoresx
oy
simplemente me interesan.Supongo que empieza a volverse malvado cuando
1) Se vuelve demasiado grande (solo agrúpelos en categorías significativas en este caso).
2) Existen métodos que no deberían ser estáticos
Pero mientras no se cumplan estas condiciones, creo que son muy útiles.
fuente
Widget.compareTo(Widget widget)
frente a lo estáticoWidgetUtils.compare(Widget widgetOne, Widget widgetTwo)
. La comparación es un ejemplo de algo que no debería hacerse de forma estática.Regla de oro
Puede ver este problema desde dos perspectivas:
*Util
métodos generales son a menudo una sugerencia de un mal diseño de código o una convención de nomenclatura lenta.Ejemplo 1. Uso correcto de
util
clases / módulos. Ejemplo de biblioteca externaSupongamos que está escribiendo una aplicación que administra préstamos y tarjetas de crédito. Los datos de estos módulos se exponen a través de servicios web en
json
formato. En teoría, puede convertir objetos manualmente en cadenas que estarán dentrojson
, pero eso reinventaría la rueda. La solución correcta sería incluir en ambos módulos una biblioteca externa utilizada para convertir objetos Java al formato deseado. (en la imagen de ejemplo he mostrado gson )Ejemplo 2. Uso correcto de
util
clases / módulos. Escribir el tuyoutil
sin excusas a otros miembros del equipoComo caso de uso, supongamos que necesitamos realizar algunos cálculos en dos módulos de aplicación, pero ambos necesitan saber cuándo hay días festivos en Polonia. En teoría, puede realizar estos cálculos dentro de los módulos, pero sería mejor extraer esta funcionalidad en un módulo separado.
Aquí hay un detalle pequeño, pero importante. La clase / módulo que ha escrito no se llama
HolidayUtil
, peroPolishHolidayCalculator
. Funcionalmente es unautil
clase, pero hemos logrado evitar la palabra genérica.fuente
Las clases de servicios públicos son malas porque significan que eras demasiado vago para pensar en un nombre mejor para la clase :)
Dicho esto, soy un vago. A veces solo necesitas hacer el trabajo y tu mente está en blanco ... ahí es cuando las clases de "Utilidad" comienzan a aparecer.
fuente
Mirando hacia atrás en esta pregunta ahora, diría que los métodos de extensión de C # destruyen por completo la necesidad de clases de utilidad. Pero no todos los lenguajes tienen una construcción tan genial.
También tiene JavaScript, donde puede agregar una nueva función directamente al objeto existente.
Pero no estoy seguro de que realmente haya una forma elegante de resolver este problema en un lenguaje más antiguo como C ++ ...
Un buen código OO es un poco difícil de escribir y es difícil de encontrar, ya que escribir Good OO requiere mucho más tiempo / conocimiento que escribir un código funcional decente.
Y cuando tienes un presupuesto limitado, tu jefe no siempre está feliz de ver que has pasado todo el día escribiendo un montón de clases ...
fuente
No estoy del todo de acuerdo con que las clases de servicios públicos sean malas.
Si bien una clase de utilidad puede violar los principios de OO de alguna manera, no siempre son malos.
Por ejemplo, imagina que quieres una función que limpie una cadena de valores coincidentes de todas las subcadenas
x
.stl c ++ (a partir de ahora) no es compatible directamente con esto.
Podría crear una extensión polimórfica de
std::string
.Pero el problema es, ¿realmente quieres que CADA cadena que uses en tu proyecto sea tu clase de cadena extendida?
Hay momentos en los que OO realmente no tiene sentido, y este es uno de ellos. Queremos que nuestro programa sea compatible con otros programas, así que nos quedaremos
std::string
y crearemos una claseStringUtil_
(o algo).Yo diría que es mejor si te quedas con una utilidad por clase. Yo diría que es una tontería tener una utilidad para todas las clases o muchas utilidades para una clase.
fuente
Es muy fácil calificar algo como una utilidad simplemente porque el diseñador no pudo pensar en un lugar apropiado para colocar el código. A menudo hay pocas "utilidades" verdaderas.
Como regla general, generalmente guardo el código en el paquete donde se usa por primera vez, y luego solo lo refactorizo a un lugar más genérico si descubro que más tarde realmente se necesita en otro lugar. La única excepción es si ya tengo un paquete que realiza una funcionalidad similar / relacionada, y el código encaja mejor allí.
fuente
Las clases de utilidad que contienen métodos estáticos sin estado pueden resultar útiles. Suelen ser muy fáciles de realizar pruebas unitarias.
fuente
Con Java 8 puedes usar métodos estáticos en interfaces ... problema resuelto.
fuente
La mayoría de las clases de Util son malas porque:
Hay algunas analogías entre bibliotecas estáticas y dinámicas.
fuente
Cuando no puedo agregar un método a una clase (digamos,
Account
está bloqueado contra cambios por Desarrolladores Jr.), simplemente agrego algunos métodos estáticos a mi clase de Utilidades así:fuente
Account
archivo. O mejor, opte por sistemas de control de fuente sin bloqueo.Account
archivo estaba bloqueado de manera que los desarrolladores Jr. no pueden realizar cambios en él. Como desarrollador Jr., para sortearlo, hizo lo anterior. Dicho esto, es mejor obtener acceso de escritura al archivo y hacerlo correctamente.Las clases de utilidad no siempre son malas. Pero solo deben contener los métodos que son comunes en una amplia gama de funciones. Si hay métodos que solo se pueden utilizar entre un número limitado de clases, considere la posibilidad de crear una clase abstracta como un padre común y coloque los métodos en ella.
fuente