Convenção de nomenclatura de parâmetro de tipo genérico para Java (com vários caracteres)?

124

Em algumas interfaces que escrevi, gostaria de nomear parâmetros de tipo genérico com mais de um caractere para tornar o código mais legível.

Algo como....

Map<Key,Value>

Em vez disso ...

Map<K,V>

Mas quando se trata de métodos, os parâmetros de tipo se parecem com classes java, o que também é confuso.

public void put(Key key, Value value)

Parece que Key e Value são classes. Encontrei ou pensei em algumas anotações, mas nada como uma convenção da Sun ou uma prática recomendada geral.

Alternativas que adivinhei ou encontrei ...

Map<KEY,VALUE>
Map<TKey,TValue>
chaper29
fonte
9
Por que você deseja criar uma nova convenção?
Amir Afghani
13
@AmirAfghani Da pergunta: para tornar o código mais legível.
SantiBailors
Tecnicamente, o matiz diferente dos genéricos no IDE deve servir como um indicador do bom suficiente
Sudix

Respostas:

181

A Oracle recomenda o seguinte em Tutoriais Java> Genéricos> Tipos Genéricos :

Convenções de nomenclatura de parâmetros de tipo

Por convenção, os nomes dos parâmetros de tipo são letras maiúsculas e únicas. Isso contrasta nitidamente com as convenções de nomenclatura de variáveis que você já conhece e por um bom motivo: sem essa convenção, seria difícil diferenciar entre uma variável de tipo e um nome de classe ou interface comum.

Os nomes dos parâmetros de tipo mais usados ​​são:

  • Elemento E (usado extensivamente pelo Java Collections Framework)
  • K - Key
  • N - Número
  • Tipo T
  • V - Valor
  • S, U, V etc. - 2º, 3º, 4º tipos

Você verá esses nomes usados ​​em toda a API do Java SE e no restante desta lição.

Eu me ateria a isso para evitar a confusão entre os desenvolvedores e possíveis mantenedores.

BalusC
fonte
14
A nova estrutura de fluxo também usa Rpara resultado e Apara acumulador.
vandale
32
Blech, nomeação de letra única. Eu sigo essa convenção porque a convenção importa mais do que nomes descritivos, mas é triste que seja o melhor que eles possam ter.
warbaker 9/09/14
4
@warbaker: Acho uma boa maneira de distinguir tipos parametrizados de classes reais. Como você diria se, por exemplo, Elementin List<Element>é um tipo parametrizado ou uma classe?
precisa saber é o seguinte
1
Parece que não BiFunction<T, U, R>segue esta convenção. Se tivesse, seria BiFunction<T, S, R>.
22616 michaelsnowden
4
Por que se preocupar em distinguir tipos parametrizados de classes reais? Eles são classes. Não importa o quê, você precisa rolar para cima em algum lugar do arquivo para descobrir como eles são definidos. E será um tipo de importação ou parametrizado.
Vectorjohn
47

Acrescentar Type

Uma boa discussão pode ser encontrada nos comentários na página do DZone, Convenções de nomenclatura para tipos parametrizados .

Veja o comentário de Erwin Mueller. Sua sugestão faz todo o sentido óbvio para mim: acrescente a palavraType .

Chame uma maçã de maçã, um carro, um carro. O nome em questão é o nome de um tipo de dados, certo? (No OOP , uma classe define essencialmente um novo tipo de dados.) Então, chame-o de "Tipo".

O exemplo de Mueller, extraído do artigo da postagem original:

public interface ResourceAccessor < ResourceType , ArgumentType , ResultType > {
    public ResultType run ( ResourceType resource , ArgumentType argument );
}

Acrescentar T

Uma pergunta duplicada fornece esta resposta por Andy Thomas. Observe o trecho do guia de estilo do Google que sugere que um nome de tipo com vários caracteres termine com uma única maiúscula T.

Basil Bourque
fonte
3
Eu gosto desta resposta. Adicionar "Tipo" é tão claro e permite que você tenha nomes descritivos. Estou farto de pessoas dizendo: "faça porque é a convenção", sem outra justificativa. Se for uma má convenção, talvez precisemos de uma nova.
Tirou
16

O motivo pelo qual a convenção de nomenclatura oficial recomenda o uso de uma única letra é o seguinte:

Sem essa convenção, seria difícil dizer a diferença entre uma variável de tipo e um nome de classe ou interface comum.

Eu acho que com os IDEs modernos esse motivo não é mais válido como por exemplo. O IntelliJ Idea mostra parâmetros de tipo genérico com cores diferentes das classes regulares.

Código com tipo genérico, conforme exibido no IntelliJ Idea 2016.1 Código com tipo genérico, conforme exibido no IntelliJ Idea 2016.1

Por causa dessa distinção , uso nomes descritivos mais longos para meus tipos genéricos, com a mesma convenção que os tipos regulares. Evito adicionar prefixos e sufixos como T ou Type, pois os considero ruídos desnecessários e não são mais necessários para distinguir visualmente tipos genéricos.

Nota: Como não sou usuário do Eclipse ou do Netbeans, não sei se eles oferecem um recurso semelhante.

Vojtech Ruzicka
fonte
Eu não basearia as convenções de nomenclatura em torno dos recursos assumidos das ferramentas que cada pessoa já leu / modificou no mesmo arquivo. Pessoalmente, gosto de usar um editor de texto para minha codificação (Sublime Text), que não é um IDE. Hoje em dia, os editores de texto geralmente têm cores de sintaxe, mas não um entendimento profundo da estrutura de código subjacente que, penso, seria necessária para colorir corretamente os nomes das variáveis ​​de tipo. E baseando este argumento sobre a cor é inerentemente exclusivo para pessoas com baixa visão das cores (eu sou parte do 8% dos homens com daltonismo vermelho-verde)
joonas.fi
1
Bom argumento sobre pessoas com baixa visão de cores. Quanto a não usar IDEs - se as pessoas preferem usar editores de texto simples, tudo bem, mas eles sacrificam voluntariamente os recursos que os IDEs oferecem a eles em favor de uma ferramenta mais leve. Este pode ser apenas um desses recursos ausentes. No final, se um nome descritivo for usado em vez de uma única letra, você poderá dizer o significado com base no nome sem um IDE e sem o código de cores. O código de cores torna isso mais rápido.
Vojtech Ruzicka
16

Sim, você pode usar nomes com vários caracteres para variáveis ​​de tipo, desde que elas sejam claramente diferenciadas dos nomes de classe.

Isso difere da convenção sugerida pela Sun com a introdução de genéricos em 2004. No entanto:

  • Mais de uma convenção existe.
  • Os nomes com vários caracteres são consistentes com outros estilos Java, como o estilo do Google para Java .
  • Os nomes legíveis são (surpresa!) Mais legíveis.

Legibilidade

Em algumas interfaces que escrevi, gostaria de nomear o parâmetro de tipo genérico com mais de um caractere para tornar o código mais legível.

A legibilidade é boa.

Comparar:

    public final class EventProducer<L extends IEventListener<E>,E> 
            implements IEventProducer<L,E> {

para:

    public final class EventProducer<LISTENER extends IEventListener<EVENT>,EVENT> 
           implements IEventProducer<LISTENER, EVENT> {

ou, com a convenção de vários caracteres do Google:

    public final class EventProducer<ListenerT extends IEventListener<EventT>,EventT> 
           implements IEventProducer<ListenerT, EventT> {

    public final class EventProducer<ListenerT extends IEventListener<EventT>,EventT> 
           implements IEventProducer<ListenerT, EventT> {

Estilo do Google

O Google Java Style Guide permite nomes de uma letra e nomes de classes com vários caracteres que terminam em T.

5.2.8 Digite nomes de variáveis

Cada variável de tipo é nomeada em um dos dois estilos:

  • Uma única letra maiúscula, seguida opcionalmente por um único número (por exemplo, E, T, X, T2)

  • Um nome no formulário utilizado para aulas (ver Secção 5.2.2, nomes de classe ), seguido pela letra T (exemplos: RequestT, FooBarT).

Problemas

"Sem essa convenção, seria difícil dizer a diferença entre uma variável de tipo e uma classe ou nome de interface comum". - nos tutoriais da Oracle, "Tipos genéricos"

Nomes de caracteres únicos não são a única maneira de distinguir parâmetros de tipo de nomes de classe, como vimos acima.

Por que não apenas documentar o significado do parâmetro type no JavaDoc?

É verdade que os @paramelementos JavaDoc podem fornecer uma descrição mais longa. Mas também é verdade que os JavaDocs não são necessariamente visíveis. (Por exemplo, há um assistente de conteúdo no Eclipse que mostra os nomes dos parâmetros de tipo.)

Os nomes de parâmetros do tipo com vários caracteres não seguem a convenção da Oracle!

Muitas das convenções originais da Sun são seguidas quase universalmente na programação Java.

No entanto, esta convenção em particular não é.

A melhor escolha entre convenções concorrentes é uma questão de opinião. As consequências de escolher uma convenção diferente da Oracle neste caso são pequenas. Você e sua equipe podem escolher uma convenção que melhor atenda às suas necessidades.

Andy Thomas
fonte
15

Você pode usar o javadoc para, pelo menos, dar uma dica aos usuários de sua classe genérica. Ainda não gosto (concordo com @ chaper29), mas os documentos ajudam.

por exemplo,

/**
 * 
 * @param <R> - row
 * @param <C> - column
 * @param <E> - cell element
 */
public class GenericTable<R, C, E> {

}

A outra coisa que soube fazer é usar meu IDE para refatorar uma classe que viola a convenção. Em seguida, trabalhe no código e refatorar para letras únicas. Torna mais fácil para mim, de qualquer maneira, se muitos parâmetros de tipo forem usados.

Tom Carchrae
fonte
1
Eu diria que os comentários Javadoc para os parâmetros de tipo geralmente são obrigatórios.
migu