Nomeação de interface em Java [fechada]

324

A maioria das linguagens OO prefixa seus nomes de interface com I maiúsculo, por que o Java não faz isso? Qual foi a justificativa para não seguir esta convenção?

Para demonstrar o que quero dizer, se eu quisesse ter uma interface de usuário e uma implementação de usuário, teria duas opções em Java:

  1. Classe = Usuário, Interface = UserInterface
  2. Classe = UserImpl, Interface = Usuário

Onde na maioria dos idiomas:

Classe = Usuário, Interface = IUser

Agora, você pode argumentar que sempre pode escolher um nome mais descritivo para a implementação do usuário e o problema desaparece, mas o Java está adotando uma abordagem POJO para as coisas e a maioria dos contêineres do IOC usa o DynamicProxies extensivamente. Essas duas coisas juntas significam que você terá muitas interfaces com uma única implementação do POJO.

Então, acho que minha pergunta se resume a: "Vale a pena seguir a convenção de nomenclatura de interface mais ampla, especialmente à luz de onde o Java Frameworks parece estar indo?"

Allain Lalonde
fonte
61
"Onde na maioria dos idiomas"? Quais idiomas além dos .Net?
Wds 12/02/09
2
Comunidades de idiomas diferentes têm convenções de nomes diferentes, e isso ocorre há muito, muito tempo. Descobrir como as convenções de nomenclatura se originaram às vezes é essencialmente uma pesquisa folclórica.
18730 David Thornley
4
O Eclipse é um erro discrepante significativo que usa Java com a nomeação no estilo IFoo. wiki.eclipse.org/Naming_Conventions
David Leonard
2
Se você dar uma olhada em nomes de interfaces no Android SDK (Java também), você vai ver que eles usaram convenção de ter palavra interface no final de um nome de interface, como NetworkInterface, DialogInterface, etc.
sandalone
21
Como essa questão pode ser "fechada como não construtiva" quando é tão popular e de interesse para tantas pessoas?
INOR

Respostas:

329

Prefiro não usar um prefixo nas interfaces:

  • O prefixo prejudica a legibilidade.

  • Usar interfaces em clientes é a melhor maneira padrão de programar, portanto, os nomes das interfaces devem ser o mais curtos e agradáveis ​​possível. As classes de implementação devem ser mais feias para desencorajar seu uso.

  • Ao mudar de uma classe abstrata para uma interface, uma convenção de codificação com prefixo I implica renomear todas as ocorrências da classe - nada bom!

starblue
fonte
12
Concordo plenamente. Mais uma chave para digitar se você usar o preenchimento automático. Lotes de arquivos começando com um I.
Kalecser
85
Qualquer IDE decente facilita a alteração do código da maneira que você descreve. Além disso, ao mudar de uma classe abstrata para uma interface, tenho certeza de que seus clientes precisarão recompilar de qualquer maneira.
23610 Allain Lalonde
63
Super tarde aqui, mas: Não importa em tudo se um IDE torna a mudança de nome de algo fácil. Código usando uma instância de algum tipo nunca deve se importar se esse tipo é uma interface ou uma classe ou o quê. Como tal, expor esse detalhe no nome do tipo é inútil e prejudicial à compreensão. O tipo e o contrato que ele expõe são o que importa!
ColinD
11
Além disso, se você estiver seguindo o caminho do IFoo, não deveria ser o CFoo para a implementação e, é claro, em caso de falha, um método lançaria um EFoo.
Robin
57
"O prefixo prejudica a legibilidade" é puramente subjetivo. Como a maioria das convenções de nomenclatura. É mais importante que sua equipe chegue a um acordo sobre o que fazer para que a base de código seja consistente.
dreadwail
121

Existe realmente uma diferença entre:

class User implements IUser

e

class UserImpl implements User

se estamos falando apenas de convenções de nomenclatura?

Pessoalmente, prefiro NÃO preceder a interface, Ipois quero codificá-la e considero isso mais importante em termos da convenção de nomenclatura. Se você chamar a interface IUser, todo consumidor dessa classe precisará saber qual é IUser. Se você chamar a classe UserImpl, apenas a classe e seu contêiner de DI saberão sobre a Implpeça e os consumidores saberão que estão trabalhando com a User.

Por outro lado, os momentos em que fui forçado a usar Implporque um nome melhor não se apresenta foram poucos e distantes, porque a implementação é nomeada de acordo com a implementação, porque é onde é importante, por exemplo

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO
tddmonkey
fonte
Eu acho que você gostaria de saber que é um DAO, pois descreve a funcionalidade geral sem a necessidade de abrir a classe. Se eu estou olhando através dos arquivos de classe em um projeto é fácil ver todos os DAOs procurando * DAO
Patrick
6
O DAO é um padrão conhecido para acesso ao banco de dados, portanto, ter o padrão no nome facilita saber o que a classe faz apenas observando seu nome. PS Seria melhor seguir a notação camelo estrita ( "AccountDao"), como em mina.apache.org/changes-between-2x-and-1x.html
Esko Luontola
4
@ Marcador, não é como ter um I para indicar uma interface. O DAO informa que a classe ou a interface é um objeto para acessar dados da conta, que é o que o objeto faz. Ter um I diz-lhe a sua interface, que não tem nada a ver com o próprio objeto, mas semântica da linguagem
tddmonkey
Conforme você o apresenta, seu prefixo vs sufixo.
Andrei Rînea 24/11/10
3
@Andrei: Não, é semântica ("DAO") vs. decoração desnecessária de um artefato de linguagem ("I" como na interface; um fato que é mencionado no código de qualquer maneira "interface IFoo ...")
Dirk
75

Pode haver vários motivos pelos quais o Java geralmente não usa a convenção IUser.

  1. Parte da abordagem orientada a objetos é que você não precisa saber se o cliente está usando uma interface ou uma classe de implementação. Portanto, mesmo List é uma interface e String é uma classe real, um método pode ser passado para os dois - não faz sentido distinguir visualmente as interfaces.

  2. Em geral, na verdade, preferimos o uso de interfaces no código do cliente (prefira List ao ArrayList, por exemplo). Portanto, não faz sentido destacar as interfaces como exceções.

  3. A convenção de nomenclatura Java prefere nomes mais longos com significados reais aos prefixos no estilo húngaro. Portanto, esse código será o mais legível possível: uma Lista representa uma lista e um Usuário representa um usuário - não um IUser.

Avi
fonte
72

Há também outra convenção, usada por muitos projetos de código aberto, incluindo o Spring.

interface User {
}

class DefaultUser implements User {
}

class AnotherClassOfUser implements User {
}

Pessoalmente, não gosto do prefixo "I" pela simples razão de que é uma convenção opcional. Então, se eu adotar isso, IIOPConnection significa uma interface para IOPConnection? E se a classe não tiver o prefixo "I", sei que não é uma interface ... a resposta aqui é não, porque as convenções nem sempre são seguidas e o policiamento delas criará mais trabalho que a própria convenção salva.

ng.
fonte
Eu gosto disso, pois também ajuda você a usar interfaces para dependências externas, em vez de acoplar as classes.
22610 Matt Briggs
47

Como outro pôster disse, normalmente é preferível ter interfaces que definem recursos e não tipos. Eu tendem a não "implementar" algo como um "Usuário", e é por isso que "IUser" geralmente não é realmente necessário da maneira descrita aqui. Costumo ver as classes como substantivos e as interfaces como adjetivos:

class Number implements Comparable{...}  
class MyThread implements Runnable{...}
class SessionData implements Serializable{....}

Às vezes, um adjetivo não faz sentido, mas eu ainda usaria interfaces para modelar comportamento, ações, recursos, propriedades, etc ... não tipos.

Além disso, se você realmente criar um único usuário e chamá-lo de usuário, qual é o sentido de também ter uma interface IUser? E se você tiver alguns tipos diferentes de usuários que precisam implementar uma interface comum, o que acrescenta um "I" à interface o poupa na escolha dos nomes das implementações?

Penso que um exemplo mais realista seria que alguns tipos de usuários precisam poder fazer login em uma API específica. Poderíamos definir uma interface de Login e, em seguida, ter uma classe pai "Usuário" com subclasses SuperUser, DefaultUser, AdminUser, AdministrativeContact, etc, algumas das quais implementarão ou não a interface de Login (Loginable?) Conforme necessário.

nairbv
fonte
Eu acho que os exemplos que você fornece para dar suporte a "interfaces como adjetivos" são distorcidos, uma vez que essas interfaces devem se parecer mais com mix-ins (ou características). Assim, as interfaces são bons para ambos os adjectivos e substantivos - mas provavelmente não para indefinite transitive verbs 8 ^ P
Stevel
Isso pode ser alterado nos últimos anos. O oracle docu. permite interfaces como tipos: [link] docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html
karlihnos
38

Bob Lee disse uma vez em uma apresentação:

qual é o objetivo de uma interface se você tiver apenas uma implementação.

então, você começa com uma implementação, ou seja, sem uma interface. mais tarde, você decide, bem, há uma necessidade de uma interface aqui, para converter sua classe em uma interface.

então fica óbvio: sua classe original foi chamada de usuário. sua interface agora é chamada de usuário. talvez você tenha um UserProdImpl e um UserTestImpl. se você projetou bem o seu aplicativo, todas as classes (exceto as que instanciam o Usuário) permanecerão inalteradas e não perceberão que de repente elas passam por uma interface.

para que fique claro -> Interface Implementação do usuário UserImpl.

Andreas Petersson
fonte
18
Usar interfaces ajuda o Test Driven Development. Corremos vários problemas sem o Modelo de Domínio e os testes porque decidimos NÃO usar interfaces. Um amigo meu certa vez citou: "Tudo é uma interface, você vai economizar a longo prazo".
21129 hooknc
4
Zombaria e fácil suporte a proxy. Tenho certeza de que existem outros motivos para fornecer interfaces também.
MetroidFan2002 13/02/09
3
Como disse recentemente a um colega, não custa nada introduzir uma interface agora, mas pode economizar muito tempo mais tarde.
Tddmonkey 13/02/09
2
Se você puder ter outras implementações em um futuro quase médio, uma interface seria uma vantagem.
585 Stef Stef
3
Não gosto do argumento "talvez precise de outro impl no futuro". Eu prefiro uma abordagem YAGNI: não planeje coisas que ainda não aconteceram.
11309 David
24

Em C # é

public class AdminForumUser : UserBase, IUser

Java diria

public class AdminForumUser extends User implements ForumUserInterface

Por causa disso, não acho que as convenções sejam tão importantes em java para interfaces, pois há uma diferença explícita entre herança e implementação de interface. Eu diria que basta escolher qualquer convenção de nomenclatura que desejar, desde que seja consistente e use algo para mostrar às pessoas que essas são interfaces. Não fazia java há alguns anos, mas todas as interfaces só estavam em seu próprio diretório, e essa era a convenção. Nunca realmente tive problemas com isso.

Matt Briggs
fonte
22
Talvez eu sou mau programador Java, mas eu prefiro o estilo C #, significa todas as interfaces começar com 'I' prefixo :)
DAVs
7
Não tenho certeza de onde você e outras pessoas estão recebendo essa suposta convenção. Não é evidente nas bibliotecas Java ...
ChiefTwoPencils
6

Na minha experiência, a convenção "I" se aplica a interfaces que se destinam a fornecer um contrato para uma classe, particularmente quando a interface em si não é uma noção abstrata da classe.

Por exemplo, no seu caso, eu esperaria apenas ver IUserse o único usuário que você pretende ter é User. Se você planeja ter diferentes tipos de usuários - NoviceUser, ExpertUseretc. -, esperaria ver uma Userinterface (e, talvez, uma AbstractUserclasse que implemente alguma funcionalidade comum, como get/setName()).

Eu também esperaria que as interfaces que definem recursos - Comparable, Iterableetc. - sejam nomeadas assim, e não como IComparableou IIterable.

David Koelle
fonte
Se o único usuário que você pretende ter é Usuário, por que não usar Usuário em vez da interface?
Carighan
3
Em algumas arquiteturas de cliente / servidor, o lado do cliente precisa conhecer as interfaces sem precisar das implementações de servidor pesado.
David Koelle
5

Seguindo bons princípios de OO, seu código deve (na medida do possível / possível) depender de abstrações em vez de classes concretas. Por exemplo, geralmente é melhor escrever um método como este:

public void doSomething(Collection someStuff) {
    ...
}

do que isso:

public void doSomething(Vector someStuff) {
    ...
}

Se você seguir essa ideia, afirmo que seu código ficará mais legível se você fornecer nomes de interfaces como "Usuário" e "Conta do banco" (por exemplo), em vez de "IUser", "UserInterface" ou outras variações.

Os únicos bits de código que devem se preocupar com as classes concretas reais são os locais onde as classes concretas são construídas. Todo o resto deve ser escrito usando as interfaces.

Se você fizer isso, os nomes de classe concretos "feios", como "UserImpl", deverão ser ocultados com segurança do restante do código, o que pode ser usado com alegria usando os nomes de interface "agradáveis".

KarstenF
fonte
Mas por que se preocupar em criar uma interface correspondente para todas as classes do seu programa quando você só precisa de interfaces para uma ou duas coisas?
usar o seguinte código
3

= v = O prefixo "I" também é usado na estrutura do Wicket, onde me acostumei rapidamente. Em geral, saúdo qualquer convenção que reduza nomes de classes Java complicados. É um aborrecimento, porém, que tudo esteja em ordem alfabética em "I" nos diretórios e no Javadoc.

A prática de codificação do wicket é semelhante ao Swing, pois muitas instâncias de controle / widget são construídas como classes internas anônimas com declarações de método em linha. Irritantemente, difere 180 ° do Swing, pois o Swing usa um prefixo ("J") para as classes de implementação.

O sufixo "Impl" é uma abreviação masculina e não se internacionaliza bem. Se ao menos tivéssemos escolhido "Imp", seria mais bonito (e mais curto). "Impl" é usado para o COI, especialmente o Spring, então estamos meio que presos a ele por enquanto. No entanto, fica um pouco esquizo após três convenções diferentes em três partes diferentes de uma base de código.

Jym Dyer
fonte
0

Essa é uma convenção de nomes mais ampla, em algum sentido real? Eu sou mais do lado de C ++, e não gosto muito de Java e descendentes. Quantas comunidades de idiomas usam a convenção I?

Se você possui uma convenção de nomenclatura padrão de loja independente do idioma, use-a. Caso contrário, siga a convenção de nomenclatura de idiomas.

David Thornley
fonte