Eu vi esse tópico
Se uma classe "Utilities" for má, onde coloco meu código genérico?
e pensei por que as classes utilitárias são más?
Digamos que eu tenha um modelo de domínio com dezenas de classes de profundidade. Eu preciso ser capaz de xml-ify instâncias. Devo fazer um método toXml no pai? Devo criar uma classe auxiliar MyDomainXmlUtility.toXml? Este é um caso em que a necessidade do negócio abrange todo o modelo de domínio - ele realmente pertence a um método de instância? E se houver vários métodos auxiliares na funcionalidade xml do aplicativo?
design-patterns
software-design
hvgotcodes
fonte
fonte
Respostas:
As classes utilitárias não são exatamente más, mas podem violar os princípios que compõem um bom design orientado a objetos. Em um bom projeto orientado a objetos, a maioria das classes deve representar uma única coisa e todos os seus atributos e operações. Se você está operando em algo, esse método provavelmente deve ser um membro dessa coisa.
No entanto, há momentos em que você pode usar classes de utilitários para agrupar vários métodos - um exemplo é a
java.util.Collections
classe que fornece vários utilitários que podem ser usados em qualquer coleção Java. Eles não são específicos para um tipo particular de coleção, mas implementam algoritmos que podem ser usados em qualquer coleção.Na verdade, o que você precisa fazer é pensar sobre seu projeto e determinar onde faz mais sentido colocar os métodos. Normalmente, é como operações dentro de uma classe. No entanto, às vezes, é de fato uma classe de utilitário. Quando você usa uma classe de utilitário, no entanto, não apenas lance métodos aleatórios nela; em vez disso, organize os métodos por propósito e funcionalidade.
fonte
Acho que o consenso geral é que as classes utilitárias não são más per se . Você só precisa usá-los criteriosamente:
Projete os métodos de utilitário estáticos para serem gerais e reutilizáveis. Certifique-se de que eles não têm estado; ou seja, sem variáveis estáticas.
Se você tiver muitos métodos utilitários, particione-os em classes de forma que seja fácil para os desenvolvedores localizá-los.
Não use classes utilitárias onde métodos estáticos ou de instância em uma classe de domínio seriam uma solução melhor. Por exemplo, considere se os métodos em uma classe base abstrata ou em uma classe auxiliar instanciável seriam uma solução melhor.
Para o Java 8 em diante, "métodos padrão" em uma interface podem ser uma opção melhor do que classes de utilitário. (Consulte Interface com métodos padrão vs classe abstrata em Java 8, por exemplo.)
A outra maneira de examinar esta questão é observar que na questão citada, "Se as classes de utilidade são" más "" é um argumento de espantalho. É como eu perguntando:
Na pergunta acima, não estou realmente dizendo que os porcos podem voar ... ou que concordo com a proposição de que eles podem voar.
Afirmações típicas do tipo "xyz é mau" são artifícios retóricos com o objetivo de fazer você pensar, colocando um ponto de vista extremo. Eles raramente (ou nunca) pretendem ser declarações de fatos literais.
fonte
As classes de utilitários são problemáticas porque falham em agrupar responsabilidades com os dados que as suportam.
No entanto, eles são extremamente úteis e eu os construo o tempo todo como estruturas permanentes ou como etapas durante uma refatoração mais completa.
De uma perspectiva de Código Limpo , as classes de utilitários violam a Responsabilidade Única e o Princípio Aberto-Fechado. Eles têm muitos motivos para mudar e não são extensíveis por design. Eles realmente deveriam existir apenas durante a refatoração como fragmentos intermediários.
fonte
class
palavra-chave seja usada. Ele grasna como um namespace, anda como um namespace - é um ...x.equals(y)
porque 1) o fato de que isso realmente não deveria modificar nenhum estado não é transmitido (e eu não posso confiar nisso sem saber a implementação) 2) Eu nunca tive a intenção de incluirx
um " posição favorecida "ou" atuada "em comparação comy
3) Não quero considerar as" identidades "dex
ou,y
estou apenas interessado em seus valores.Acho que começa a se tornar mal quando
1) Fica muito grande (apenas agrupe-os em categorias significativas neste caso).
2) Métodos que não devem ser métodos estáticos estão presentes
Mas, enquanto essas condições não forem atendidas, acho que são muito úteis.
fonte
Widget.compareTo(Widget widget)
versus o estáticoWidgetUtils.compare(Widget widgetOne, Widget widgetTwo)
. A comparação é um exemplo de algo que não deve ser feito estaticamente.Regra de ouro
Você pode olhar para este problema de duas perspectivas:
*Util
Métodos geralmente são uma sugestão de projeto de código incorreto ou convenção de nomenclatura preguiçosa.Exemplo 1. Uso correto de
util
classes / módulos. Exemplo de biblioteca externaVamos supor que você esteja escrevendo um aplicativo que gerencia empréstimos e cartões de crédito. Os dados desses módulos são expostos por meio de serviços da web em
json
formato. Em teoria, você pode converter objetos manualmente em cordas que estarão dentrojson
, mas isso reinventaria a roda. A solução correta seria incluir em ambos os módulos a biblioteca externa usada para converter objetos java no formato desejado. (na imagem de exemplo que mostrei gson )Exemplo 2. Uso correto de
util
classes / módulos. Escrever o seu próprioutil
sem desculpas para outros membros da equipeComo caso de uso, suponha que precisamos realizar alguns cálculos em dois módulos do aplicativo, mas ambos precisam saber quando há feriados na Polônia. Em teoria, você pode fazer esses cálculos dentro dos módulos, mas seria melhor extrair essa funcionalidade para separar o módulo.
Aqui estão alguns detalhes pequenos, mas importantes. A classe / módulo que você escreveu não é chamado
HolidayUtil
, masPolishHolidayCalculator
. Funcionalmente é umautil
classe, mas conseguimos evitar a palavra genérica.fonte
Aulas de utilitários são ruins porque significam que você estava com preguiça de pensar em um nome melhor para a classe :)
Dito isso, sou preguiçoso. Às vezes, você só precisa fazer o trabalho e sua mente fica em branco ... é aí que as aulas de "Utilidades" começam a surgir.
fonte
Olhando para esta questão agora, eu diria que os métodos de extensão C # destroem completamente a necessidade de classes de utilitário. Mas nem todas as linguagens têm essa construção genial.
Você também tem JavaScript, onde pode simplesmente adicionar uma nova função diretamente ao objeto existente.
Mas não tenho certeza se realmente existe uma maneira elegante de resolver esse problema em uma linguagem mais antiga como C ++ ...
Um bom código OO é meio difícil de escrever e é difícil de encontrar, pois escrever um bom OO requer muito mais tempo / conhecimento do que escrever um código funcional decente.
E quando você está com um orçamento apertado, seu chefe nem sempre fica feliz em ver que você passou o dia inteiro escrevendo um monte de aulas ...
fonte
Não concordo inteiramente que as classes utilitárias sejam más.
Embora uma classe de utilitário possa violar os princípios OO de algumas maneiras, nem sempre são ruins.
Por exemplo, imagine que você deseja uma função que limpará uma string de todas as substrings correspondentes ao valor
x
.stl c ++ (a partir de agora) não suporta isso diretamente.
Você pode criar uma extensão polimórfica de
std::string
.Mas o problema é: você realmente deseja que CADA string que usar em seu projeto seja sua classe de string estendida?
Há momentos em que OO realmente não faz sentido, e este é um deles. Queremos que nosso programa seja compatível com outros programas, então vamos nos ater a
std::string
e criar uma classeStringUtil_
(ou algo assim).Eu diria que é melhor se você ficar com um utilitário por aula. Eu diria que é bobagem ter um utilitário para todas as classes ou muitos utils para uma classe.
fonte
É muito fácil marcar algo como utilitário simplesmente porque o designer não conseguiu pensar em um local apropriado para colocar o código. Freqüentemente, existem poucos "utilitários" verdadeiros.
Como regra geral, geralmente mantenho o código no pacote em que é usado pela primeira vez e só refatoro para um local mais genérico se descobrir que mais tarde ele realmente é necessário em outro lugar. A única exceção é se eu já tiver um pacote que executa funcionalidade semelhante / relacionada e o código se encaixa melhor nele.
fonte
As classes utilitárias que contêm métodos estáticos sem estado podem ser úteis. Geralmente, esses testes são muito fáceis de realizar.
fonte
Com o Java 8 você pode usar métodos estáticos em interfaces ... problema resolvido.
fonte
A maioria das classes Util são ruins porque:
Existem algumas analogias com bibliotecas estáticas e dinâmicas.
fonte
Quando não consigo adicionar um método a uma classe (digamos,
Account
está bloqueado contra alterações de desenvolvedores Jr.), apenas adiciono alguns métodos estáticos à minha classe Utilities, como:fonte
Account
arquivo. Ou melhor, vá com sistemas de controle de origem sem travamento.Account
arquivo foi bloqueado de forma que os desenvolvedores Jr. não podem fazer alterações nele. Como um Desenvolvedor Jr., para contornar isso, ele fez como acima. Dito isso, ainda é melhor obter acesso de gravação ao arquivo e fazê-lo corretamente.As classes utilitárias nem sempre são más. Mas eles devem conter apenas os métodos comuns em uma ampla gama de funcionalidades. Se houver métodos que só podem ser usados em um número limitado de classes, considere a criação de uma classe abstrata como um pai comum e coloque os métodos nela.
fonte