Avisar sobre métodos de terceiros proibidos

9

Nota: Esta pergunta refere-se ao código escrito em Java ou C #.

Estou gerenciando alguns projetos grandes em que descobrimos problemas (não necessariamente bugs) com alguns métodos de terceiros / SDK e criamos nossas próprias extensões que devem ser usadas. Queremos que os desenvolvedores lembrem que o uso desses métodos não é recomendado para este projeto.

Se estivéssemos usando nossas próprias bibliotecas, poderíamos facilmente remover esse método ou marcá-lo como obsoleto / obsoleto, mas não podemos fazê-lo para bibliotecas que não escrevemos.

Como exemplo, usamos uma biblioteca que nos fornece duas sobrecargas:

acme.calculate(int quantity_, double priceInUsDollars_);
acme.calculate(int quantity_, string currencyCode_, double priceInCurrency_);

Queremos que os desenvolvedores sempre usem o primeiro e obtenham o preço em dólares dos nossos próprios sistemas de taxa de câmbio padrão. E seria bom que o IDE (Eclipse / Visual Studio) avise os desenvolvedores quando eles usarem o primeiro. Um aviso do compilador também será suficiente.

No momento, como está, temos que confiar nos revisores de código para detectar esses erros e, como você pode ver, essa não é uma abordagem confiável.

Uma maneira possível de me preparar é escrever minha própria verificação de estilo de cheque ( http://checkstyle.sourceforge.net/writingchecks.html ). Mas eu queria saber se havia algo simples que eu poderia usar. Alguém sabe maneiras de obter um aviso de IDE / compilador do tipo que descrevi?

Soluções que não sejam de IDE / compilador são bem-vindas.

Apoorv Khurasia
fonte
1
Por que você não pode alterar a fonte para as bibliotecas de terceiros? Você tem , eu presumo? (Se não, esse é o verdadeiro problema que você precisa se concentrar em Nunca faça isso..)
Mason Wheeler
3
@MasonWheeler Infelizmente, na verdade não podemos. É um binário compilado (.dll, .jar) que usamos. Além disso, há armadilhas para essa abordagem como nós pode sair mais recente, perca o apoio (que é muito importante para nós), etc ..
Apoorv Khurasia
4
@MasonWheeler: o acesso ao código fonte de uma biblioteca de terceiros é algo que você geralmente não tem a liberdade de escolher. Existem muitas bibliotecas de código fechado no mercado em que não existe alternativa útil de código aberto.
Doc Brown
Você pode herdar as classes na biblioteca deles e adicionar uma substituição aos métodos que você não deseja que eles chamem que está marcado como obsoleto?
CaffGeek
@ DocBrown: Eu não disse open-source. Eu disse fonte disponível. Existem muitas bibliotecas proprietárias que fornecerão a fonte (sob uma licença proprietária) quando você a comprar. Temos uma política em funcionamento para nunca usar nenhuma biblioteca de terceiros sem fonte disponível e nunca encontramos uma situação em que precisávamos.
Mason Wheeler

Respostas:

7

Usando uma ferramenta como NDepend / JavaDepend , você pode escrever consultas CQL personalizadas para gerar avisos para esses casos muito específicos.

Você disse na pergunta que queria que o IDE / Compiler avisasse os desenvolvedores. Eu acho que porque o NDepend / JDepend se integra estreitamente ao IDE, isso pode resolver seu problema.

MattDavey
fonte
3
Essa é uma boa ligação. Além disso, você pode facilmente configurar um esquema com o NDepend (nunca usado o JavaDepend) em que avisos / alertas foram gerados em violações de check-ins ou mesmo onde os check-ins foram rejeitados, dependendo das outras ferramentas envolvidas (controle de origem, construção).
Erik Dietrich
Isso parece promissor. Vou tentar isso amanhã e avisar. Obrigado Matt.
Apoorv Khurasia
Parece que eles mudaram o nome do produto de JavaDepend para JArchitect, mas o programa ainda parece bastante interessante.
Dalin Seivewright
4

A "abordagem da lista branca": escreva uma biblioteca de wrapper na biblioteca com essencialmente as mesmas assinaturas de interface que a própria lib, mas deixe de fora as funções proibidas. O wrapper deve delegar cada chamada de método na chamada de biblioteca correspondente. Então deixe seus desenvolvedores usarem / vincularem somente a esse wrapper em vez da lib original. O wrapper também pode ser um bom local para as extensões da sua biblioteca.

É claro que isso pode se tornar impraticável se a lib tiver uma API muito grande com várias centenas de funções. Então você deseja implementar uma "abordagem de lista negra" como a solução "estilo de verificação" sugerida.

Doc Brown
fonte
Sim. É uma biblioteca enorme. Pior ainda, temos muitas dessas bibliotecas (em projetos em C #, Java). Também estou pensando em uma verificação de formigas pós-compilação.
Apoorv Khurasia
2
Este foi o meu primeiro pensamento também, mas ao ler a pergunta do OP pela segunda vez, parece que ele está procurando por 'avisos' em vez de uma arquitetura mais restritiva. Acho que este é um problema mais de uma análise estática do que escrever mais código ...
MattDavey
@MattDavey Isso é verdade.
Apoorv Khurasia
Existem programas geradores de wrapper ( por exemplo , sourceforge.net/projects/wrappergen ) que fazem a parte tediosa para você. Depois, são apenas algumas exclusões ou anotações de métodos a serem feitas manualmente.
Ross Patterson
Os invólucros @RossPatterson não são apenas um investimento de capital único. Eles podem se tornar um pesadelo de manutenção em alguns casos.
Apoorv Khurasia
2

Uma das vantagens do Reflection do Java é que você pode alterar as propriedades do método em tempo de execução. Um dos usos é tornar público um método privado, para poder usá-lo de qualquer maneira. Poderia muito bem funcionar ao contrário, com você tornando métodos indesejados privados, em tempo de execução. Embora não seja visto na compilação, será visto assim que o projeto for testado.

Este artigo mostra como modificar propriedades de métodos em tempo de execução. Aqui está a parte interessante:

Class theClass = MyClass.class;
Class[] paramTypes = { Integer.TYPE, String.class };
Method method = theClass.getDeclaredMethod("myMethodName", paramTypes);
method.setAccessible(false); // this makes the metod private
System.out.println("Making method  myMethodName(int,String) private");
XGouchet
fonte
1
Obrigado. Vou tentar a solução de MattDavey primeiro porque ela me permite fazer análises estáticas. Dito isto, se todas as abordagens estáticas falharem, tentarei sua solução.
Apoorv Khurasia
1
Isso não vai funcionar, eu acho. Para código compilado, a última vez que as regras de visibilidade são verificadas é no tempo de carregamento, quando os códigos de bytes são verificados. Alterações subsequentes usando as APIs reflexivas afetarão apenas outras chamadas reflexivas.
Stephen C
0

Queremos que os desenvolvedores lembrem que o uso desses métodos não é recomendado para este projeto.

Como você já tinha que criar métodos de substituição em alguns casos. Eu criaria uma classe de wrapper para toda a biblioteca e usaria apenas sua classe de wrapper.

Se a biblioteca for atualizada, você precisará atualizar seu código de qualquer maneira. A classe do wrapper é fácil de atualizar.

Isso evita que os desenvolvedores usem o método errado, embora ... ouso dizer que um desenvolvedor deve ser capaz de lembrar quais métodos ele não deve usar.

Ramhound
fonte
3
não, não é razoável esperar que um desenvolvedor se lembre de que ele simplesmente “não deveria usar” métodos perfeitamente lógicos em uma biblioteca que está usando. Um ou dois, talvez, mas como regra geral os seres humanos simplesmente não conseguem se lembrar desse tipo de coisa de maneira confiável. Caramba, pilotos altamente treinados e absolutamente motivados não podem confiar em todos os detalhes de como tirar o avião do solo com segurança - é por isso que existem listas de verificação da cabine!
22412 Michael Kohne
É exatamente o que eu quero. Use essa função e o IDE gera um aviso.
Apoorv Khurasia
@ MichaelKohne - Quando tive um problema semelhante ao autor, não tive problema em lembrar quais métodos eu deveria usar. A biblioteca em questão era facilmente 100 métodos diferentes.
precisa saber é o seguinte