Recentemente, venho investigando uma programação mais "organizada" e aprendendo que devo programar para uma interface, não para uma implementação. Com isso em mente, seria melhor "esboçar" um projeto nas interfaces antes de escrever a implementação sempre que possível?
E se esse for o caso, no caso de usar bibliotecas de terceiros (por exemplo, Lidgren), eu também devo envolvê-las nas interfaces e resolvê-las através de contêineres IOC, ou é correto expô-las às interfaces?
c#
design
interfaces
third-party-libraries
inversion-of-control
Dan Pantry
fonte
fonte
Respostas:
Infelizmente, você verá que isso geralmente se resume a preferências pessoais.
O que você descreveu até agora, no entanto, parece bom. De fato, se você quiser (e eu o recomendo), use a seguinte abordagem:
Você está tentando escrever um código mais "organizado". Seguir o TDD irá ajudá-lo com isso.
Alguns pontos extras:
fonte
Sim, você deve codificar contra interfaces, em vez de implementações conhecidas, e sim, você deve construir interfaces primeiro, em vez de fazê-las emergir de seu próprio código.
As razões para ambas as recomendações são basicamente as mesmas: a programação de computadores trata principalmente de fatores humanos. Muitos acham isso surpreendente, mas consideram: existe um número quase infinito de maneiras diferentes de resolver o mesmo problema de computação que funciona igualmente bem. Quase todos eles são completamente impossíveis de entender para quem não os escreveu (ou de fato para o autor pouco tempo depois).
Daqui resulta que uma boa engenharia de software trata principalmente de como alcançar o efeito desejado (computação correta com eficiência razoável) de uma maneira que permita que o código fonte seja trabalhado posteriormente. Interfaces e APIs são uma parte crucial dessa disciplina: permitem que você pense sobre um problema em um nível de descrição por vez. Isso é muito mais fácil do que pensar em regras de consistência de negócios e em implementações de listas vinculadas ao mesmo tempo, e, portanto, impor essa separação de preocupações à força é melhor do que permitir que o programador cliente use seu código da maneira que desejar.
É difícil de acreditar para muitos programadores de cowboys, convencidos de que entendem tudo o que escrevem, são muito melhores do que os pensadores comuns e podem lidar com toda a complexidade que causa problemas aos programadores "menores". Não estar ciente dos próprios limites cognitivos é um fenômeno extremamente comum - é por isso que as melhores práticas em organização de códigos são tão importantes (e muitas vezes ignoradas).
Para repetir, interfaces e barreiras de API são bastante boas , mesmo quando você coopera apenas consigo mesmo. Quanto às bibliotecas externas, se elas trouxerem uma API bem pensada, não vejo problema em usá-la, desde que você não espere ter que trocar essa biblioteca por outra. Caso contrário, um invólucro ou camada anticorrupção pode ser uma ótima ideia.
fonte
IBlah
implementados porBlah
ouBlah
implementados porBlahImpl
. Não gosto de ambos, e costumo usarBlah
implementado porOralBlah
,WrittenBlah
ouASLBlah
. Mas, como sempre, é mais importante estar em conformidade com a base de código e as expectativas existentes do que com qualquer padrão geral.Em vez de apenas programar servilmente para interfaces, por que não olhar para TDD (Development Driven Development / Design)?
Muitas pessoas pensam no TDD como uma prática de teste, mas, na verdade, é uma abordagem de design em que você permite que os testes exponham como o seu código será usado por meio de testes (inicialmente por testes de unidade, mas também por testes de integração).
A programação para interfaces é uma arma importante no seu conjunto de ferramentas, mas, como a maioria das coisas, nem sempre é a solução / técnica / prática apropriada, pois nem sempre é necessária. Você deve programar para interfaces onde precisar.
O uso do TDD forçará você a explorar onde essas interfaces são importantes e onde, francamente, não importa. E no final, você deve ter um bom conjunto de testes de unidade em toda a sua base de código.
Quanto ao uso de bibliotecas de terceiros, eu recomendo agrupá-las em suas próprias abstrações, quando apropriado; e não deixe que os clientes da sua API "saibam" sobre eles.
Boa sorte!
[editar: viu a resposta do megaflight - concordo completamente]
fonte
Eu acho que é um exagero. Se o usuário da sua API não precisar ser forçado a implementar / usar algo de uma certa maneira, eu o deixaria de fora. Interfaces são contratos, se eu não preciso, por que me dar um?
Eu acho que as pessoas usam demais interfaces. Você está adicionando uma camada de complexidade que não é necessária na maioria dos casos.
fonte
Programar contra um contrato é quase sempre uma boa ideia. Esse contrato não precisa ser uma interface, mas pode ser cumprido por uma classe. Na minha opinião, as interfaces tornaram-se um pouco usadas demais com o DI devido a preocupações com testes de unidade e estruturas de simulação.
Pessoalmente, prefiro trazer apenas interfaces quando é provável que eu tenha ou tenha mais de uma implementação de contrato. As interfaces são ótimas para repositórios nos quais desejo abstrair o acesso a dados, mas provavelmente menos ainda para minha lógica comercial padrão, que provavelmente é relativamente inflexível.
Agora, não ter uma interface pode causar problemas com o teste de unidade, especialmente para puristas. Mas estou interessado em zombar das dependências externas dos meus programas, não de suas dependências internas. Quero que meus testes realizem a validação do código, não ecoem a estrutura do código.
fonte