[BOAS PRATICAS] Constantes nas interfaces?

24 respostas
mausexdd
class MinhaClasse(){
  static final int a = 1;
  static final char = 2;
  /*mais algumas constantes*/
}

É uma boa pratica de programação declarar minhas constantes nas interfaces?
Quando implementa-la na classe elas já estaram disponíveis.

Ex:

public interface MinhaClasse{
  static final int a = 1;
  static final char = 2;
  /*mais algumas constantes*/
}

public MinhaClasseImpl implements MinhaClasse{

}

Isso se enquadra em alguma boa prática ou seria só por preferencia pessoal?

24 Respostas

darksteel3000

Amigo, o bom mesmo é você criar uma classe de constantes e colocar as constantes todas do sistema lá ( organizado, claro hehe ).

mausexdd

É que ai eu perco o escopo do projeto pois são constantes muito especificas que devem ter sua visualização restrita. Pensei que ao invés de declara-las dentro da classe para dizer… Constante você pertence a essa classe OK? Implementando uma interface que tenha esse valores e também a declaração dos métodos, assim eu estaria tirando proveito um possível polimorfismo etc…

douglaskd

darksteel3000:
Amigo, o bom mesmo é você criar uma classe de constantes e colocar as constantes todas do sistema lá ( organizado, claro hehe ).

eu acho…que isso ai era usado antigamente.

o que acha de usar o mesmo padrão do Swing ?

mausexdd

eu acho…que isso ai era usado antigamente.

o que acha de usar o mesmo padrão do Swing ?

E como ficaria isto?

Rodrigo_Sasaki

Eu acho que se fizer sentido não tem problema, como na API de Calendar.

Agora fazer uma interface só pra ter constantes soltas, aí não.

R

Têm gente que acha que definir constantes na interface não é uma boa prática,e que o certo é definir um Enum.

x111

Tudo depende!

  1. Sua interface é utilizada por mais de uma classe? Se não pq utilizar a interface então!
  2. Caso a resposta a pergunta 1 seja verdadeira, Todas as classes que implementarem a interface irão utilizar essas constantes?
  3. Para que serão usadas essas constantes? Para cálculos matemáticos? Para blocos condicionais? Se for para blocos condicionais é melhor utilizar enum.
douglaskd

mousexd

o Joshua Bloch (Engenheiro que programou boa parte do java, diz isso sobre Constantes):

"If the constants are strongly tied to an existing class or interface, you should add them to the class or interface. For example, all of the boxed numerical primitive classes, such as Integer and Double, export MIN_VALUE and MAX_VALUE constants. If the constants are best viewed as members of an enumerated type, you should export them with an enum type. Otherwise, you should export the constants with a noninstantiable utility class." Exemplo:
// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

agora se isso cabe a todo sistema fica dificil dizer...

gomesrod

Isso costuma ser considerado uma espécie de abuso da especificação. Alguém viu que era possível fazer e começou a usar para o mal :evil:

Tem pelo menos dois motivos para ser uma má prática:

(1)
Muitas vezes a finalidade das constantes é participar de algum detalhe na implementação.
As constantes na interface passam a fazer parte da API pública de todas as classes que implementam a interface.
Consequentemente, todas as suas classes vão expor na API pública TODAS as constantes da interface, mesmo aquelas que são detalhe de implementação, e mesmo aquelas que sequer são usadas e não tem nada a ver com aquela classe específica.

(2)
Olhando o código fica difícil identificar de onde vem aquele valor.

A solução correta, se você estiver escrevendo o código do zero, é usar Enums.
Se não tiver como, por algum motivo muito forte, use uma (ou mais) classe(s) de constantes de modo que sejam usadas no código de forma clara (ex: Calendar.DAY_OF_MONTH)

E

mausexdd:
class MinhaClasse(){ static final int a = 1; static final char = 2; /*mais algumas constantes*/ }

É uma boa pratica de programação declarar minhas constantes nas interfaces pois quando implementa-la na classe elas já estaram disponiveis…

Não é boa prática coisa nenhuma. Não é porque isso existe em algumas APIs antigas do JDK (que foram criadas antes da inclusão das enums na linguagem) que você vai fazer exatamente como era feito no milênio passado :frowning:

sergiotaborda

O que o douglaskd citou do Bloch é a lei relativamente a estas coisas.
antigamente quando não havia enums era uma prática comum colocar as constances na interface. Por isso que o swing usa isso bastante assim como Calendar.
Mas hoje em dia são usados enums ou classes Utils (que não são instanciáveis nem herdáveis)

Ou seja, colocar as constantes em lugar que pode ser herdado é má prática.

gomesrod
douglaskd:
// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}
Esse foi um bom exemplo de quando as constantes devem ser usadas. Aqui elas efetivamente se referem a valores, por isso não cabe o Enum. E foi feito de forma muito correta: Primeiro, dessa maneira que foi implementado, na hora de chamar fica muito claro de onde vem:
PhysicalConstants.AVOGADROS_NUMBER

// e não 
AVOGADROS_NUMBER
//solto no código
E segundo, elas não vão fazer parte da API pública da classe que as utiliza. Por exemplo, uma classe utilitaria que tem o método:
BigDecimal calcularMassaDoAtomo(Atomo a) {
    ///.....
}
vai usar a constante de Avogadro em um determinado momento do cálculo, mas não precisa necessariamente exportar a constante para seus clientes!

[EDIT]
Esse método usando a constante de avogadro eu chutei, mas agora que entrou um físico no tópico (sergiotaborda) eu fiquei com medo de ele me dar bronca por estar falando besteira hehe

mausexdd

Obrigado a todos que responderam.

Eu fiz esta pergunta pois como estou realizando muitos cálculos de posicionamento geográfico algumas constantes precisaram ser declaradas na classe. Como:

// equatorial radius
	private static final Double EQUATORIAL_RADIUS = 6378137D;

	// polar radius
	private static final Double POLAR_RADIUS = 6356752.314D;

	private static final Double MAJOR_SEMI_AXIS = 6378137D;

	// scale factor
	private static final Double SCALE_FACTOR = 0.9996D;

	// eccentricity
	private static final Double CALCULATED_ECCENTRICITY = Math.sqrt( 1D - Math.pow( POLAR_RADIUS / EQUATORIAL_RADIUS, 2D ) );

	private static final Double CALCULATED_E1SQ = CALCULATED_ECCENTRICITY * CALCULATED_ECCENTRICITY / ( 1D - CALCULATED_ECCENTRICITY * CALCULATED_ECCENTRICITY );
	
	private static final Double ECCENTRICITY = 0.081819191;

Porém algumas outras classes com constantes menos especificas também foram criadas e como a linguagem disponibiliza o recurso eu questionei sobre ser correto ou errado.

Vou ponderar o meio termo nas minhas escolhas, acredito que não tem certo ou errado e varia de caso a caso. Obrigado a todos foi muito esclarecedor.

x111

mausexdd:
Obrigado a todos que responderam.

Eu fiz esta pergunta pois como estou realizando muitos cálculos de posicionamento geográfico algumas constantes precisaram ser declaradas na classe. Como:

// equatorial radius
	private static final Double EQUATORIAL_RADIUS = 6378137D;

	// polar radius
	private static final Double POLAR_RADIUS = 6356752.314D;

	private static final Double MAJOR_SEMI_AXIS = 6378137D;

	// scale factor
	private static final Double SCALE_FACTOR = 0.9996D;

	// eccentricity
	private static final Double CALCULATED_ECCENTRICITY = Math.sqrt( 1D - Math.pow( POLAR_RADIUS / EQUATORIAL_RADIUS, 2D ) );

	private static final Double CALCULATED_E1SQ = CALCULATED_ECCENTRICITY * CALCULATED_ECCENTRICITY / ( 1D - CALCULATED_ECCENTRICITY * CALCULATED_ECCENTRICITY );
	
	private static final Double ECCENTRICITY = 0.081819191;

Porém algumas outras classes com constantes menos especificas também foram criadas e como a linguagem disponibiliza o recurso eu questionei sobre ser correto ou errado.

Vou ponderar o meio termo nas minhas escolhas, acredito que não tem certo ou errado e varia de caso a caso. Obrigado a todos foi muito esclarecedor.

Bom nesse caso, faz sentido ser constantes. Mas acredito que elas devam ter um classe especifica só par elas (similar a Math) . Essa classe de constantes seria utilizada por todas as outras classes.

A meu ver uma constantes só deveria ir para uma interface se e somente se todas as as interfaces utilizarem essa constante! Um exemplo poderia ser o número minimo de elementos de alguma coisa. Todas as classes que implementam a interface devem criar algo que disponibilize esse numero de elementos mínimos.

mausexdd

x@ndy Bom nesse caso, faz sentido ser constantes. Mas acredito que elas devam ter um classe especifica só par elas (similar a Math) . Essa classe de constantes seria utilizada por todas as outras classes.

A meu ver uma constantes só deveria ir para uma interface se e somente se todas as as interfaces utilizarem essa constante! Um exemplo poderia ser o número minimo de elementos de alguma coisa. Todas as classes que implementam a interface devem criar algo que disponibilize esse numero de elementos mínimos.

Obrigado pela dica.

E

x@ndy:

A meu ver uma constantes só deveria ir para uma interface se e somente se todas as as interfaces utilizarem essa constante! Um exemplo poderia ser o número minimo de elementos de alguma coisa. Todas as classes que implementam a interface devem criar algo que disponibilize esse numero de elementos mínimos.

Constante não deve ir coisa nenhuma para interface.
Na verdade, isso foi uma decisão infeliz de projeto quando a primeira versão do Java foi criada - em vez de eles terem enums logo de cara, que é o lugar certo para constantes, eles puseram isso em interfaces apenas para poderem entregar logo o compilador da linguagem.
(Foi também por causa disso que a parte de “generics” entrou só no Java 5, quase 10 anos depois de a linguagem ter sido criada - se eles tivessem mais alguns meses para o desenvolvimento, já teríamos “generics” no Java desde a versão 1, porque era uma coisa que o Gosling queria mas tiveram de podar na primeira versão).
Você pode entender isso melhor quando descobrir que apenas em Java existe essa bizarrice de declarar constantes em interfaces.

E

E se o problema é que você precisa sempre escrever algo como “Math.PI” em vez de simplesmente “PI” (ou seja, constantes declaradas como variáveis públicas estáticas de uma classe qualquer, que está lá apenas para recolher as constantes), foi criado na versão 5 do Java o recurso de “import static” que dispensa você ficar escrevendo “Math.PI” a torto e a direito.

import static java.lang.Math.*;
import static java.lang.System;
...
out.printf ("%.2f", PI);
// Sem o import static seria System.out.printf ("%.2f", Math.PI);
x111

entanglement:
x@ndy:

A meu ver uma constantes só deveria ir para uma interface se e somente se todas as as interfaces utilizarem essa constante! Um exemplo poderia ser o número minimo de elementos de alguma coisa. Todas as classes que implementam a interface devem criar algo que disponibilize esse numero de elementos mínimos.

Constante não deve ir coisa nenhuma para interface.
Na verdade, isso foi uma decisão infeliz de projeto quando a primeira versão do Java foi criada - em vez de eles terem enums logo de cara, que é o lugar certo para constantes, eles puseram isso em interfaces apenas para poderem entregar logo o compilador da linguagem.
(Foi também por causa disso que a parte de “generics” entrou só no Java 5, quase 10 anos depois de a linguagem ter sido criada - se eles tivessem mais alguns meses para o desenvolvimento, já teríamos “generics” no Java desde a versão 1, porque era uma coisa que o Gosling queria mas tiveram de podar na primeira versão).
Você pode entender isso melhor quando descobrir que apenas em Java existe essa bizarrice de declarar constantes em interfaces.

Blz, então me explique como eu faço se tenho algo que deva ser implementado e que o tamanho máximo digamos tenha que ser 252 (obviamente é uma constante e não um enum)
e a implementação dos métodos seguem um contrato porém podem ter diferentes implementações?

Esse é um caso clássico de uma interface, no qual é necessário ter uma constante! Como eu resolvo isso? Explique também qual é o problema do uso de uma constante com uma interface nesse caso?

O mal uso de alguma coisa não quer dizer que aquilo não deva ser utilizado!

x111

Uma coisa que tem que se deixar clara é o que uma constante e o que é uma enumeração.

Constantes são números únicos, como valores matemáticos (PI é um exemplo) ou físicas (Numero de Avogadro) ou então o número de dias de uma semana ou de horas num dia. Isso são constantes, não mudam. Em um sistema eu posso definir valores que são constantes, conforme o tipo da aplicação que estou desenvolvendo. Constantes são basicamente utilizadas para cálculos envolvendo outros números.

Já enumerações são conjuntos de valores utilizados em sistemas para classificação. Por exemplo: eu posso ter uma enumeração com os dias da Semana que poderia ser Semana.SEGUNDA, Semana.TERCA, etc. Enumerações são basicamente utilizadas para classificação de alguma coisa e são muito utilizada em logicas condicionais! No java enumerações são classes e também podem ter métodos e executar ações porém isso normalmente não acontece em outras linguagens como c e pascal.

O problema com java é que, como nas versões anteriores não se tinha a implementação de Enumerações, o pessoal fazia o uso de constantes no seu lugar e claro que isso acarretou em diversos problemas. Com a implementação das enumerações pela linguagem o uso de constantes como enumeração foi considerado uma má pratica porém como o povo exagera, quer abolir todas as constantes e esse não é o caso! Constantes devem ser utilizadas quando isso for apropriado e isso ocorre basicamente quando ela representa um valor numérico, porém elas não devem ser utilizadas quando enumerações são mais adequadas.

sergiotaborda

mausexdd:
Obrigado a todos que responderam.

Eu fiz esta pergunta pois como estou realizando muitos cálculos de posicionamento geográfico algumas constantes precisaram ser declaradas na classe. Como:

// equatorial radius
	private static final Double EQUATORIAL_RADIUS = 6378137D;

	// polar radius
	private static final Double POLAR_RADIUS = 6356752.314D;

	private static final Double MAJOR_SEMI_AXIS = 6378137D;

	// scale factor
	private static final Double SCALE_FACTOR = 0.9996D;

	// eccentricity
	private static final Double CALCULATED_ECCENTRICITY = Math.sqrt( 1D - Math.pow( POLAR_RADIUS / EQUATORIAL_RADIUS, 2D ) );

	private static final Double CALCULATED_E1SQ = CALCULATED_ECCENTRICITY * CALCULATED_ECCENTRICITY / ( 1D - CALCULATED_ECCENTRICITY * CALCULATED_ECCENTRICITY );
	
	private static final Double ECCENTRICITY = 0.081819191;

Porém algumas outras classes com constantes menos especificas também foram criadas e como a linguagem disponibiliza o recurso eu questionei sobre ser correto ou errado.

Vou ponderar o meio termo nas minhas escolhas, acredito que não tem certo ou errado e varia de caso a caso. Obrigado a todos foi muito esclarecedor.

Ou seja, vai ignorar o que dissemos e as regras do Block e continuar usando interface … :x

Crie um GeoConstants que não é uma interface, é uma classe final , com construtor private. Isto é a solução correta (equivalente a Math.PI).
Não é uma questão de opinião nem 'poderar o meio termo". Só existe o certo e o errado. E esta tecnica já era certa antes do java 5 ( como o Math.PI demonsra) , o problema é que não era um padrão conhecido. Agora é. Então use!

F

Aproveitando o bonde do tópico, uma dúvida:

Configurações referentes a aplicação como IP, login e senha de serviços, e por ae vai nessa linha, seria recomendado o uso de um Properties ou Constantes ?

Abraços

douglaskd

fabioccunha:
Aproveitando o bonde do tópico, uma dúvida:

Configurações referentes a aplicação como IP, login e senha de serviços, e por ae vai nessa linha, seria recomendado o uso de um Properties ou Constantes ?

Abraços

constantes seria a maneira mais errada de se fazer isso, um software deve ser preparado para ter suporte, e um software que o Analista de Suporte tem que abrir um ENUM pra alterar o IP não é nada ideal.

antigamente essas coisas eram configuradas no .ini, hoje acho que um xml ou properties

x111

fabioccunha:
Aproveitando o bonde do tópico, uma dúvida:
Configurações referentes a aplicação como IP, login e senha de serviços, e por ae vai nessa linha, seria recomendado o uso de um Properties ou Constantes ?
Abraços
Properties é o mais apropriado com certeza

F

Feito aqui já.
Obrigado pessoal =)

Criado 22 de fevereiro de 2013
Ultima resposta 27 de fev. de 2013
Respostas 24
Participantes 10