É uma prática ruim ter uma interface para definir constantes?


40

Estou escrevendo um conjunto de classes de teste junit em Java. Existem várias constantes, por exemplo, strings que eu precisarei em diferentes classes de teste. Estou pensando em uma interface que os define e toda classe de teste o implementaria.

Os benefícios que vejo são:

  • acesso fácil a constantes: em MY_CONSTANTvez deThatClass.MY_CONSTANT
  • cada constante definida apenas uma vez

Essa abordagem é uma boa ou má prática? Sinto vontade de abusar um pouco do conceito de interfaces.

Você pode responder geralmente sobre interfaces / constantes, mas também sobre testes de unidade, se houver algo de especial nisso.


A resposta para "É uma prática ruim ter uma interface definindo X?", Sendo X qualquer coisa que não seja "assinatura de método", quase sempre é certamente "Sim".
T. Sar - Restabelece Monica

Respostas:


79

Joshua Bloch desaconselha isso em seu livro Effective Java :

O fato de uma classe usar algumas constantes internamente é um detalhe de implementação. A implementação de uma interface constante faz com que esse detalhe da implementação vaze para a API exportada das classes. Não tem importância para os usuários de uma classe que a classe implemente uma interface constante. De fato, pode até confundi-los. Pior, representa um comprometimento: se em uma versão futura a classe for modificada para não precisar mais usar as constantes, ainda deverá implementar a interface para garantir a compatibilidade binária.

Você pode obter o mesmo efeito com uma classe normal que define as constantes e, em seguida, use import static com.example.Constants.*;


13

No nosso caso, estamos fazendo isso porque os valores das constantes representam um contrato para os estados finais que uma implementação de serviço é necessária para fornecer. A inserção dessas constantes na interface especifica os estados finais como parte do contrato e, se alguma implementação da interface não as utilizasse, ela não faria seu trabalho.

Às vezes, constantes são detalhes de implementação. Às vezes eles não são. Como sempre, um engenheiro precisa usar seu cérebro para decidir o que fazer e não confiar em um padrão ou prática abrangente.


7

Não acho bom ter interfaces apenas para constantes.

Mas se uma interface que define comportamento (métodos que implementam classes devem implementar), tem constantes, tudo bem. Se "vazar os detalhes de algum implementador" na API, é porque é assim que deve ser. Também estão vazando que o implementador implementa métodos foo e bar.

Tomemos, por exemplo, a interface java.awt.Transparency. Possui constantes OPAQUE, BITMASK e TRANSLUCENT, mas também possui o método getTransparency ().

Se o designer colocar essas constantes lá, é porque ele pensou que seria estável o suficiente para fazer parte da interface, como getTransparency ().


2

Pense que é um ponto de vista mais popular em lugares onde o design por contrato é predominante.
Interfaces são contratos. Colocar constantes nas interfaces significa que toda classe que cumpre o contrato concorda com o valor / conceito identificado pela constante.


11
interfaces são contratos públicos. VALORES constantes são preocupações particulares, a interface pública deve, no máximo, expor seus nomes. É melhor deixar para uma classe abstrata.
jwenting

Os casos em questão: javax.naming.Context, javax.ims.Session, e centenas de tais interfaces ...
CMR

2
@jwenting Além disso, uma interface pública poderia "at most expose their names", sem expor os valores?
CMR

isso dependeria da linguagem de programação, eu acho. No caso de Java, não.
Jwenting

2

Uma empresa em que trabalhei fez uso pesado de 1 constantes importadas pela interface . Não sinto nenhum mal disso.

A pergunta que você deve se perguntar é: qual a importância do namespace para você? No caso de constantes, é realmente tudo o que uma classe age. Se você possui milhares de constantes, talvez não queira que todas estejam sempre disponíveis.

O bacana das interfaces é que ela oferece o benefício de trabalhar de qualquer maneira - traga todos os namespaces necessários ou nenhum deles (e acesse-os explicitamente com MyInterface.CONSTANT). Praticamente a mesma coisa que import static MyInterface.*, mas um pouco mais óbvio.


1: Se você não conhece o Java, não estou falando da importpalavra - chave, mas sim trazida porimplements MyConstantsInterface


1

Eu venho de um contexto que é principalmente influenciado principalmente pelo 'caminho Ada' e pelo 'caminho Net.' Eu diria que não, que provavelmente não é melhor declarar constantes nas interfaces. Tecnicamente, não é permitido em c #.

A razão pela qual digo não é que uma interface é uma forma de contrato que define comportamento, não estado ou estrutura. Uma constante implica algum tipo de estado (primitivo) ou um aspecto do estado (composto ou agregado).

Posso apreciar o desejo de disponibilizar padrões e valores predefinidos para todos que implementam a interface, mas talvez o estado padrão seja melhor descrito em um objeto ou modelo abstrato ou de valor, onde os padrões tenham pelo menos um contexto mínimo.

Para um guia mais técnico: download.oracle.com/javase/1.5.0/docs/guide/language/static-import.html


Adicionando mais links referentes à importação estática (1.5): 1. Wikipedia 2. Oracle Docs referenciando @Justinc
Abhijeet

11
So when should you use static import? Very sparingly! Only use it when you'd otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes. If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Referência do Oracle Docs
Abhijeet

1

Não, não é uma prática ruim geral.

O ponto é que constantes como qualquer outro artefato devem ser introduzidas sob as regras de visibilidade mínima e nível de abstração adequado.

Usar a sintaxe apenas porque você pode é o verdadeiro problema.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.