Às vezes, crio classes 'Util' que servem principalmente para armazenar métodos e valores que realmente não parecem pertencer a outro lugar. Mas toda vez que crio uma dessas classes, penso "uh-oh, vou me arrepender disso mais tarde ...", porque li em algum lugar que é ruim.
Mas, por outro lado, parece haver dois casos convincentes (pelo menos para mim) para eles:
- segredos de implementação que são usados em várias classes dentro de um pacote
- fornecendo funcionalidade útil para aumentar uma classe, sem sobrecarregar sua interface
Estou a caminho da destruição? O que você diz !! Devo refatorar?
Util
nos nomes das suas aulas. Problema resolvido.SomethingUtil
é um pouco preguiçoso e apenas obscurece o verdadeiro objetivo da classe - o mesmo com as classes nomeadasSomethingManager
ouSomethingService
. Se essa classe tiver uma única responsabilidade, deve ser fácil dar um nome significativo. Se não, esse é o problema real para lidar com ...Util
, embora, obviamente, eu não esperava que isso iria ficar fixado em eo resto da questão ignorada ...Respostas:
O design moderno do OO aceita que nem tudo é um objeto. Algumas coisas são comportamentos ou fórmulas e outras não têm estado. É bom modelar essas coisas como funções puras para obter o benefício desse design.
Java e C # (e outros) exigem que você crie uma classe util e pule esse aro para fazê-lo. Irritante, mas não o fim do mundo; e não é realmente problemático do ponto de vista do design.
fonte
Nunca diga nunca"
Eu não acho que seja necessariamente ruim, só é ruim se você fizer mal e abusar.
Todos nós precisamos de ferramentas e utilitários
Para começar, todos nós usamos algumas bibliotecas que às vezes são consideradas quase onipresentes e obrigatórias. Por exemplo, no mundo Java, no Google Guava ou em alguns Apache Commons ( Apache Commons Lang , Apache Commons Collections , etc ...).
Portanto, claramente há uma necessidade disso.
Evite erros de palavras duras, duplicação e introdução de erros
Se você pensar sobre estes são praticamente apenas um grande monte dessas
Util
classes que você descrever, exceto que alguém passou por grandes distâncias para obtê-los (relativamente) bem, e eles têm sido tempo - testado e fortemente olho-enrolado por outros.Então, eu diria que a primeira regra prática quando sentir vontade de escrever uma
Util
classe é verificar se elaUtil
realmente não existe.O único contra-argumento que eu vi para isso é quando você deseja limitar suas dependências porque:
Mas ambos podem ser resolvidos re-empacotando a lib usando o ProGuard ou equivalente, ou desmontando-a (para usuários do Maven , o maven-shade-plugin oferece alguns padrões de filtragem para integrar isso como parte de sua compilação).
Portanto, se estiver em uma biblioteca e corresponder ao seu caso de uso, e nenhum benchmark indicar o contrário, use-o. Se variar um pouco do que você, estenda-o (se possível) ou estenda-o ou, em último caso, reescreva-o.
Convenções de nomenclatura
No entanto, até agora nesta resposta eu os chamei de
Util
s como você. Não os nomeie assim.Dê-lhes nomes significativos. Tome o Google Guava como um (muito, muito) bom exemplo do que fazer e imagine que o
com.google.guava
namespace seja realmente a suautil
raiz.Ligue para o seu pacote
util
, na pior das hipóteses, mas não para as aulas. Se lida comString
objetos e manipulação de construções de strings, chame-o deStrings
nãoStringUtils
(desculpe, Apache Commons Lang - eu ainda gosto e uso você!). Se fizer algo específico, escolha um nome de classe específico (comoSplitter
ouJoiner
).Teste de unidade
Se você precisar recorrer à gravação desses utilitários, faça um teste de unidade. O bom dos utilitários é que eles geralmente são componentes independentes, que recebem entradas específicas e retornam saídas específicas. Esse é o conceito. Portanto, não há desculpa para não testá-los unitariamente.
Além disso, o teste de unidade permitirá definir e documentar o contrato da API. Se os testes forem interrompidos, você alterou algo da maneira errada ou significa que está tentando alterar o contrato da sua API (ou que seus testes originais eram uma porcaria - aprenda com ele e não faça isso de novo) .
Design da API
As decisões de design que você tomará para essas APIs o seguirão por muito tempo, possivelmente. Portanto, embora não gaste horas escrevendo um
Splitter
clone, tenha cuidado com a maneira como aborda o problema.Faça a si mesmo algumas perguntas:
Você deseja que esses utilitários cubram uma grande variedade de casos de uso, sejam robustos, estáveis, bem documentados, seguindo o princípio da menor surpresa e sejam independentes. Idealmente, cada subpacote de seus utils, ou todo o seu pacote de utilitários, deve ser exportado para um pacote para facilitar a reutilização.
Como sempre, aprenda com os gigantes aqui:
util
Pacote de Java (que contém a biblioteca de coleções) e seu equivalente .Net ,Sim, muitos deles enfatizam coleções e estruturas de dados, mas não me diga que não é onde ou para quê você costuma implementar a maioria de seus utilitários, direta ou indiretamente.
fonte
If deals with String objects and manipulation of string constructs, call it Strings, not StringUtils
StringsCollectionTypeHere
se você quiser uma implementação concreta. Ou um nome mais específico, se essas sequências tiverem um significado específico no contexto do seu aplicativo. Nesse caso específico, o Guava usaStrings
para seus auxiliares relacionados a cadeias, em oposição aoStringUtils
Commons Lang. Acho perfeitamente aceitável, apenas significa para mim que as classes manipulamString
objetos ou são uma classe de propósito geral para gerenciar Strings.NameUtils
coisas me incomodam sem fim, porque se estiver sob um nome de pacote claramente rotulado, eu já saberia que é uma classe de utilidade (e, se não, descobriria rapidamente olhando a API). É tão chato para mim como pessoas declarando coisas comoSomethingInterface
,ISomething
ouSomethingImpl
. Eu estava bem com esses artefatos ao codificar em C e não usar IDEs. Hoje eu geralmente não precisaria de tais coisas.As classes Util não são coesas e geralmente apresentam um design ruim porque uma classe precisa ter um único motivo para mudar (Princípio de Responsabilidade Única).
No entanto, eu já vi "util" classes no muito Java API, como:
Math
,Collections
eArrays
.Essas são, de fato, classes de utilidade, mas todos os seus métodos estão relacionados a um único tema, um possui operações matemáticas, um possui métodos para manipular coleções e outro para manipular matrizes.
Tente não ter métodos totalmente não relacionados em uma classe de utilitário. Se for esse o caso, é provável que você também possa colocá-los onde eles realmente pertencem.
Se deve ter util aulas, em seguida, testá-los para ser separados por tema como Java de
Math
,Collections
eArrays
. Pelo menos, mostra alguma intenção de design, mesmo quando são apenas namespaces.Eu, por exemplo, sempre evito classes de utilidade e nunca tive a necessidade de criar uma.
fonte
Math
ouArrays
mostra pelo menos alguma intenção de design.É perfeitamente aceitável ter classes util , embora eu prefira o termo
ClassNameHelper
. O .NET BCL ainda possui classes auxiliares. A coisa mais importante a lembrar é documentar completamente o objetivo das classes, bem como cada método auxiliar individual, e torná-lo um código sustentável de alta qualidade.E não se deixe levar pelas aulas de ajuda.
fonte
Eu uso uma abordagem em duas camadas. Uma classe "Globals" em um pacote "util" (pasta). Para que algo entre na classe "Globals" ou no pacote "util", deve ser:
Exemplos que passam nesses testes:
Aqui está um exemplo de um método auxiliar muito pequeno, completamente independente do restante do aplicativo:
Olhando para isso, vejo um bug que 21 deve ser "21", 22 deve ser "22", etc., mas isso não vem ao caso.
Se um desses métodos auxiliares crescer ou se tornar complicado, ele deverá ser movido para sua própria classe no pacote util. Se duas ou mais classes auxiliares no pacote util estiverem relacionadas, elas deverão ser movidas para o próprio pacote. Se um método constante ou auxiliar estiver relacionado a uma parte específica do seu aplicativo, ele deverá ser movido para lá.
Você deve ser capaz de justificar por que não existe um lugar melhor para tudo o que você coloca em uma classe Globals ou pacote de utilitários e deve limpá-lo periodicamente usando os testes acima. Caso contrário, você está apenas criando uma bagunça.
fonte