Como o autor desta pergunta de 2012 e de 2013 , eu tenho uma biblioteca de terceiros que preciso agrupar para testar corretamente meu aplicativo. A resposta principal indica:
Você sempre deseja agrupar tipos e métodos de terceiros atrás de uma interface. Isso pode ser entediante e doloroso. Às vezes, você pode escrever um gerador de código ou usar uma ferramenta para fazer isso.
No meu caso, a biblioteca é para um modelo de objeto e, consequentemente, possui um número maior de classes e métodos que precisariam ser agrupados para que essa estratégia fosse bem-sucedida. Além de apenas "tedioso e doloroso", isso se torna uma barreira difícil para os testes.
Nos 4 anos desde essa pergunta, estou ciente de que as estruturas de isolamento percorreram um longo caminho. Minha pergunta é: existe agora uma maneira mais simples de obter o efeito de agrupamento completo de bibliotecas de terceiros? Como posso aliviar a dor desse processo e reduzir o esforço manual?
Minha pergunta não é uma duplicata das perguntas às quais vinculei inicialmente, já que a minha pergunta é sobre reduzir o esforço manual de empacotamento. Essas outras perguntas apenas perguntam se a embalagem faz sentido, e não como o esforço pode ser pequeno.
fonte
Respostas:
Supondo que você não esteja procurando uma estrutura de zombaria, porque é ultra-onipresente e fácil de encontrar , há algumas coisas que vale a pena observar com antecedência:
Nem sempre é melhor agrupar uma biblioteca de terceiros. Se seu aplicativo é intrinsecamente dependente de uma biblioteca, ou se é literalmente construído em torno de uma ou duas bibliotecas principais, não perca seu tempo finalizando. Se as bibliotecas mudarem, seu aplicativo precisará mudar de qualquer maneira.
Isso é especialmente verdadeiro em relação aos limites que são estáveis, intrínsecos ao seu aplicativo ou que não podem ser facilmente ridicularizados. Se essas condições forem atendidas, o acondicionamento e a zombaria serão complicados e tediosos. Nesse caso, eu evitaria os dois: não envolva nem zombe; basta escrever testes de integração. (Se o teste automatizado é uma meta.)
Em princípio, uma ferramenta só pode reduzir o padrão. Porém, não há algoritmo automatizado para pegar uma interface complexa e simplificá-la - muito menos pegar a interface X e adaptá-la às suas necessidades. (Somente você conhece esse algoritmo!) Portanto, embora haja indubitavelmente ferramentas que podem gerar invólucros finos, sugiro que elas ainda não sejam onipresentes porque, no final, você ainda precisa apenas codificar de forma inteligente e, portanto, manualmente, contra a interface, mesmo que oculta atrás de um invólucro.
Dito isto, existem táticas que você pode usar em vários idiomas para evitar se referir diretamente a uma classe. E, em alguns casos, você pode "fingir" uma interface ou um invólucro fino que não existe realmente. Em C #, por exemplo, eu usaria uma das duas rotas:
Você pode evitar o esforço de agrupar completamente uma classe complexa com este pequeno combo:
Se você puder evitar o armazenamento desses objetos como membros, por meio de uma abordagem mais "funcional" ou armazenando-os em um dicionário (ou qualquer outro ), essa abordagem terá o benefício de verificar o tipo em tempo de compilação sem que suas principais entidades de negócios precisem saber exatamente com que classe eles estão trabalhando.
Tudo o que é necessário é que, em tempo de compilação, a classe retornada por sua fábrica realmente possua os métodos que seu objeto de negócios está usando.
Isso ocorre da mesma maneira que o uso de digitação implícita , mas envolve outra desvantagem: você perde verificações do tipo de compilação e ganha a capacidade de adicionar anonimamente dependências externas como membros da classe e injetar suas dependências.
Com essas duas táticas, quando chega a hora de zombar
ExternalPDFLibraryDocument
, como afirmei anteriormente, você tem algum trabalho a fazer - mas é um trabalho que você precisaria fazer de qualquer maneira . E, com essa construção, você evitou definir tediosamente centenas de pequenas e finas classes de embalagens. Você simplesmente usou a biblioteca sem olhar diretamente para ela - na maior parte.Com tudo isso dito, há três grandes razões pelas quais eu consideraria explicitamente encerrar uma biblioteca de terceiros - nenhuma das quais sugeriria o uso de uma ferramenta ou estrutura:
Se eu não tiver alguma preocupação de nível nessas três áreas, você não fará nenhum esforço significativo para concluí-lo. E, se você tiver alguma preocupação nas três áreas, um invólucro fino gerado automaticamente não ajudará.
Se você decidiu encerrar uma biblioteca, o uso mais eficiente e eficaz do seu tempo é criar seu aplicativo na interface desejada ; não contra uma API existente.
Em outras palavras, preste atenção ao conselho clássico: adie todas as decisões que puder. Crie o "núcleo" do seu aplicativo primeiro. Codifique contra interfaces que eventualmente farão o que você deseja, que acabará sendo cumprido por "coisas periféricas" que ainda não existem. Preencha as lacunas conforme necessário.
Esse esforço pode não parecer economizado em tempo; mas se achar que precisa de um invólucro, essa é a maneira mais eficiente de fazê-lo com segurança.
Pense desta maneira.
Você precisa codificar nessa biblioteca em algum canto escuro do seu código - mesmo que esteja finalizado. Se você zomba da biblioteca durante o teste, há um esforço manual inevitável por lá - mesmo que seja finalizado. Mas isso não significa que você precise reconhecer diretamente essa biblioteca pelo nome em toda a maior parte do seu aplicativo.
TLDR
Se vale a pena agrupar a biblioteca, use táticas para evitar referências diretas e difundidas à sua biblioteca de terceiros, mas não use atalhos para gerar wrappers finos. Construa sua lógica de negócios primeiro, seja deliberado sobre suas interfaces e eleve seus adaptadores organicamente, conforme necessário.
E, se for o caso, não tenha medo de testes de integração. Eles são um pouco mais confusos, mas ainda oferecem evidências de código funcional e ainda podem ser feitos com facilidade para manter as regressões afastadas.
fonte
Não teste de unidade esse código. Escreva testes de integração. Em alguns casos, o teste de unidade, a zombaria, é tedioso e doloroso. Abandone os testes de unidade e escreva testes de integração que realmente fazem chamadas de fornecedor.
Observe que esses testes devem ser executados após a implantação como uma atividade automatizada pós-implantação. Eles não são executados como parte de testes de unidade ou como parte do processo de construção.
Às vezes, um teste de integração é mais adequado do que um teste de unidade em certas partes do seu aplicativo. Os aros pelos quais se deve passar para tornar o código "testável" às vezes podem ser prejudiciais.
fonte
Pelo que entendi, esta discussão se concentra em oportunidades para a automação da criação de wrapper, em vez de agrupar as diretrizes de idéia e implementação. Vou tentar abstrair da idéia, pois já existe muita coisa aqui.
Vejo que estamos brincando com as tecnologias .NET; portanto, temos poderosos recursos de reflexão em nossas mãos. Você pode considerar:
Acredito que essa automação possa constituir um ponto base, mas não uma solução final. A refatoração manual de código será necessária ... ou, na pior das hipóteses, uma reformulação conforme eu concordo completamente com o que a svidgen escreveu:
fonte
Siga estas diretrizes ao criar bibliotecas de wrapper:
fonte