Pergunta

Eu sou novo para uma equipe trabalhando em um bastante grande projecto, com lotes de componentes e dependências. Para cada componente, há um pacote interfaces onde as interfaces expostas para esse componente são colocados. Será esta uma boa prática?

A minha prática usual tem sido sempre interfaces e implementações de ir no mesmo pacote.

Foi útil?

Solução

Colocar a interface ea implementação é lugar comum, e não parece ser um problema.

Tomemos por exemplo a API Java - a maioria das classes tem ambas as interfaces e suas implementações incluídos no mesmo pacote.

Tomemos por exemplo o java.util pacote:

Ele contém as interfaces, como Set, Map, List, ao mesmo tempo, tendo as implementações, tais como HashSet, HashMap e ArrayList.

Além disso, os Javadocs são projetados para funcionar bem nessas condições, pois separa a documentação no Interfaces e Classes vistas ao exibir o conteúdo do pacote.

Tendo pacotes somente para interfaces pode realmente ser um pouco excessivo, a menos que haja um enorme número de interfaces. Mas separando as interfaces em seus próprios pacotes apenas por uma questão de fazê-lo soa como má prática.

Se diferenciar o nome de uma interface de uma aplicação é necessária, pode-se ter uma convenção de nomenclatura para fazer as interfaces mais fáceis de identificar:

  • Prefixo do nome da interface com um I. Esta abordagem é adoptada com as interfaces na framework .NET. Seria muito fácil dizer que IList é uma interface para uma lista.

  • Use o sufixo -able. Esta abordagem é visto muitas vezes na API Java, tais como Comparable, Iterable e Serializable para citar alguns.

Outras dicas

Para qualquer idioma, colocá-los juntos no mesmo pacote é bom. O importante é o que está exposta ao mundo exterior, e como ele olha de fora. Ninguém vai saber ou se importar se a implementação está no mesmo pacote ou não.

Vamos olhar neste caso particular.

Se você tem todas as coisas públicas em um pacote, e coisas particulares em outro pacote que não é exposto publicamente, o cliente da biblioteca vê um pacote. Se você mover as coisas privadas para o pacote com as coisas expostas publicamente, mas não expô-los de dentro do pacote, o cliente vê exatamente a mesma coisa.

Assim, este tem o cheiro de uma regra sem uma boa razão:. Está fazendo uma decisão baseada em algo sendo visível publicamente, sem essa decisão ter qualquer efeito sobre o que é visível publicamente

Dito isto, se, em qualquer caso particular, parece uma boa idéia para dividir a interface e implementação para pacotes separados, vá em frente e fazer isso. Razões para fazer isso que vêm à mente são de que o pacote é enorme, ou você tem uma implementação alternativa você pode querer link em vez do padrão.

Em muitos quadros, como OSGi, você quase tem que. Eu acho que isso promove acoplamento looser, para o pacote em vez do nível jar.

Um argumento para colocar as interfaces em diferentes pacotes é que é mais fácil criar frascos 'API' que podem ser distribuídos aos consumidores do seu produto ou serviço. É perfeitamente possível fazer isso com interfaces e implementações juntos, mas simples de roteiro se eles estão em diferentes pacotes.

Sim, é uma prática muito boa, porque permite que você publique a interface sem publicar sua implementação específica. Dito isto, se você não tem nenhuma necessidade de publicar interfaces externas, não há nenhum problema com a colocação das definições de interface no mesmo pacote como a implementação.

O livro Prática de Engenharia de Software: um estudo de caso Abordagem advogados para colocar as interfaces em projetos separados / pacotes.

O PCMEF + arquitetura que o livro fala sobre tem os seguintes princípios:

  1. Downward Princípio Dependência (DDP)
  2. Notificação Upward Princípio (UNP)
  3. Neighbor Princípio Comunicação (NCP)
  4. explícita Princípio Association (EAP)
  5. Ciclo de Eliminação Princípio (CEP)
  6. Classe Naming Princípio (CNP)
  7. Acquaintance Package Princípio (APP)

A descrição do princípio # 3 e # 7 explicar por que é uma boa idéia:

O Vizinho Princípio Comunicação exige que um pacote só pode comunicar-se diretamente com seu pacote vizinho. Este princípio assegura que o sistema não se desintegrar a uma rede incompressível de intercomunicantes objetos. Para reforçar este princípio, passagem de mensagens entre não-vizinha objetos usos delegação (Seção 9.1.5.1). No cenários mais complexos, pacote conhecido (Seção 9.1.8.2) podem ser utilizado para interfaces de grupo para auxiliar na colaboração que engata pacotes distantes.

O Acquaintance Package Princípio é a consequência do Vizinho Princípio de comunicação. O pacote conhecido consiste interfaces de um objecto que se passa, em vez de objectos de betão, em argumentos para chamadas de método. As interfaces podem ser implementadas em qualquer pacote PCMEF. Isso efetivamente permite a comunicação entre pacotes não-vizinha enquanto centralizando o gerenciamento de dependência para um pacote de conhecimento único. A necessidade de pacote de conhecimento era explicado na Seção 9.1.8.2 e é discutido novamente no próximo em PCMEF contexto.

Veja este link: http://comp.mq.edu. au / livros / PSE / about_book / Ch9.pdf

Fazemos isso onde eu trabalho (ou seja: interface de colocar em um pacote e implementação em outro). Ea principal vantagem sairmos desta situação é que podemos facilmente trocar entre implementações

Eu não tenho muita experiência em Java, mas eu gosto de fazer isso como uma boa prática em C # /. NET porque permite a expansão futura onde os conjuntos com as classes concretas que implementam as interfaces não pode ser distribuído por todo o caminho para o cliente, porque eles estão em proxy por uma fábrica de intermediário ou através do fio em um cenário de serviço web.

Estou fazendo isso em um projeto e ele está funcionando bem para mim por causa dessas razões:

  • interfaces e implementações Separadamente embalados são para um caso de uso diferente do que para os vários tipos de mapa ou Set. Não há nenhuma razão para ter um pacote apenas para árvores (java.util.tree.Map, java.util.tree.Set). É apenas uma estrutura de dados padrão, para colocá-lo em conjunto com as outras estruturas de dados. No entanto, se você está lidando com um jogo de quebra-cabeça que tem uma interface de depuração muito simples e uma interface de produção bastante, como parte de seu front-end que você pode ter um com.your.app.skin.debug e uma com.your.app .skin.pretty. Eu não iria colocar estes no mesmo pacote, porque eles fazem coisas diferentes e eu sei que iria recorrer a alguns SmurfNamingConvention (DebugAttackSurface, DebugDefenceSurface, PrettyAttackSurface etc) para criar algum espaço para nome informal para os dois se fossem no mesmo pacote.

  • A minha solução para o problema de encontrar as interfaces relacionadas e implementações que estão em pacotes separados é adotar uma configuração de nomeação para meus pacotes. Por exemplo. Eu posso ter todos os meus interfaces em com.your.app.skin.framework, e sei que outros pacotes no mesmo nível da árvore de pacotes são implementações. A desvantagem é que este é uma convenção não convencional. Honestamente, eu vou ver como é bom esta convenção é em 6 meses:)

  • Eu não usar esta técnica religiosamente. Há interfaces que só fazem sentido em uma implementação particular. Eu não furá-los no pacote framework. Existem alguns pacotes onde não parece que eu estou indo para criar 40 classes de implementação diferentes, então eu não me incomodo.

  • Meu aplicativo usa guice e tem muitas interfaces.

As questões de concepção do programa geralmente envolvem vantagens e desvantagens e não há um tamanho único para todos resposta. Como por que você nunca usar esta técnica em um pequeno programa 200-line? Faz sentido para mim, dadas as minhas outras opções de arquitetura, para o meu problema específico. :)

Eu normalmente colocado Interfaces com a implementação no entanto eu posso tipo de ver por que você pode querer mantê-los separados. Digamos, por exemplo, alguém queria aulas reimplementar com base em suas interfaces, que seria necessário um frasco / lib / etc com sua implementação, em vez de apenas as interfaces. Com eles separar você poderia apenas dizer "Aqui está minha implementação dessa interface" e ser feito com ele. Como eu disse, não o que eu faço, mas eu posso tipo de ver por que alguns podem querer.

Coloque-os em pacotes que refletem seus projetos. É muito bem e comum colocar interfaces e implementações em conjunto, se eles são parte de um mesmo projeto, mas se você estiver escrevendo uma API, em seguida, outra pessoa seria provavelmente escolher um nome de pacote relevantes para o seu projeto.

Em geral, se é para o mesmo projeto, eu não vejo nenhum benefício em manter as interfaces em um pacote separado de seus impls. Se ele está ficando confuso, pode haver outras questões pacote de nomeação, independentemente do arranjo de interface.

Eu prefiro-los no mesmo pacote. Sente inútil criar um pacote especificamente para interfaces. Isto é especialmente redundante para equipes que simplesmente amam seus prefixos e sufixos de interface (por exemplo, o "I" e "Impl" para Java).

Se há uma necessidade de publicar um conjunto de interfaces como API pública, faz mais sentido mantê-los em um projeto inteiramente separada e criar dependências do projeto em seu lugar. Mas tudo se resume a preferência e conveniência da situação suponho.

Eu acho que é importante notar que para o quadro OSGi, é mais agradável que eles estão em diferentes pacotes para que você possa facilmente exportar um pacote completo ao esconder os pacotes de implementação.

Há uma série de boas razões para colocar as interfaces em um pacote separado de implementação. Por exemplo, você pode querer recipiente uso que os apoios Dependency Injection para fio até a implementação necessária (s) em tempo de execução, caso em que apenas a interface precisa estar presente em tempo de compilação e a implementação pode ser fornecido em tempo de execução. Alternativamente, você pode querer fornecer várias implementações (por exemplo, usando simulada implementações para testes ) ou várias versões de uma implementação em particular no tempo de execução (por exemplo para o teste a / B, etc.). Para estes tipos de casos de uso é mais conveniente para empacotar interface e implementação separadamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top