Advertir sobre los métodos de terceros que están prohibidos

9

Nota: Esta pregunta se refiere al código escrito en Java o C #.

Estoy gestionando un par de grandes proyectos en los que hemos descubierto problemas (no necesariamente errores) con algunos métodos de terceros / SDK y hemos escrito nuestras propias extensiones que deberían usarse en su lugar. Queremos que los desarrolladores recuerden que no se recomienda usar esos métodos para este proyecto.

Si hubiéramos estado utilizando nuestras propias bibliotecas, podríamos eliminar fácilmente ese método o marcarlo como obsoleto / en desuso, pero no podemos hacerlo para las bibliotecas que no escribimos.

Como ejemplo, utilizamos una biblioteca que nos proporciona dos sobrecargas:

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

Queremos que los desarrolladores usen siempre el primero y obtengan el precio en dólares estadounidenses de nuestros propios sistemas de tasa de cambio estándar. Y sería bueno que el IDE (Eclipse / Visual Studio) advirtiera a los desarrolladores cuando usen el primero. Una advertencia del compilador también será suficiente.

En este momento, tal como está, tenemos que confiar en los revisores de código para detectar dichos errores y, como pueden ver, ese no es un enfoque confiable.

Una posible forma en que estoy preparado es escribir mi propia verificación de estilo de verificación ( http://checkstyle.sourceforge.net/writingchecks.html ). Pero me preguntaba si había algo simple que pudiera usar. ¿Alguien sabe de maneras de lograr una advertencia IDE / compilador del tipo que he descrito?

Las soluciones que no son IDE / compilador son bienvenidas.

Apoorv Khurasia
fuente
1
¿Por qué no puede cambiar la fuente a las bibliotecas de terceros? ¿Lo tienes , supongo? (Si no, ese es el verdadero problema en el que debe concentrarse. Nunca haga eso.)
Mason Wheeler
3
@MasonWheeler Lamentablemente, en realidad no podemos. Es un binario compilado (.dll, .jar) que usamos. Además, hay dificultades para ese enfoque, ya que podemos salir más tarde, perder el apoyo (que es muy crítico para nosotros), etc.
Apoorv Khurasia
44
@MasonWheeler: el acceso al código fuente de una biblioteca de terceros es algo que a menudo no tiene la libertad de elegir. Hay muchas bibliotecas de código cerrado en el mercado donde no existe una alternativa útil de código abierto.
Doc Brown
¿Puede heredar las clases en su biblioteca y agregar una anulación a los métodos que no desea que llamen y que estén marcados como obsoletos?
CaffGeek
@DocBrown: No dije código abierto. Dije fuente disponible. Hay muchas bibliotecas propietarias que le proporcionarán la fuente (bajo una licencia propietaria) cuando la compre. Tenemos una política en el trabajo para nunca usar una biblioteca de terceros sin fuente disponible, y nunca hemos encontrado una situación en la que tengamos que hacerlo.
Mason Wheeler

Respuestas:

7

Con una herramienta como NDepend / JavaDepend , puede escribir consultas CQL personalizadas para generar advertencias para estos casos muy específicos.

Usted dijo en la pregunta que quería que IDE / Compiler advirtiera a los desarrolladores. Creo que porque NDepend / JDepend se integran estrechamente con el IDE, esto puede resolver su problema.

MattDavey
fuente
3
Esa es una buena llamada. Y, podría armar fácilmente un esquema con NDepend (nunca utilizado JavaDepend) donde se generaron advertencias / alertas por violar los registros o incluso donde los registros fueron rechazados, dependiendo de las otras herramientas involucradas (control de origen, compilación).
Erik Dietrich
Esto suena prometedor. Voy a intentar esto mañana y te lo haré saber. Gracias Matt
Apoorv Khurasia
Parece que han cambiado el nombre de su producto de JavaDepend a JArchitect, pero el programa todavía parece bastante interesante.
Dalin Seivewright
4

El "enfoque de la lista blanca": escriba una biblioteca de contenedor en la biblioteca con esencialmente las mismas firmas de interfaz que la propia biblioteca, pero omita las funciones prohibidas. El reiniciador debe delegar cada llamada de método a la llamada de biblioteca correspondiente. Luego, deje que sus desarrolladores solo usen / link a ese contenedor en lugar de la lib original. El contenedor también puede ser un buen lugar para las extensiones de su biblioteca.

Por supuesto, eso puede ser poco práctico si la lib tiene una API muy grande con varios cientos de funciones. Luego, desea implementar un "enfoque de lista negra" como la solución de "estilo de verificación" que sugirió.

Doc Brown
fuente
Si. Es una gran biblioteca. Pero aún peor, tenemos muchas bibliotecas de este tipo (en C #, proyectos Java). También estoy pensando en una revisión de hormigas después de la compilación.
Apoorv Khurasia
2
Este fue mi primer pensamiento también, pero al leer la pregunta del OP por segunda vez parece que está buscando 'advertencias' en lugar de una arquitectura más restrictiva. Creo que este es un problema más de análisis estático que escribir más código ...
MattDavey
@ MattDavey Eso es cierto.
Apoorv Khurasia
Hay programas generador de envoltorios ( por ejemplo , sourceforge.net/projects/wrappergen ) que hacen la parte tediosa por usted. Entonces es solo un método de eliminación o anotación para hacer a mano.
Ross Patterson
Los envoltorios de @RossPatterson no son solo una inversión de capital única. Pueden convertirse en una pesadilla de mantenimiento en algunos casos.
Apoorv Khurasia
2

Una de las ventajas de Reflection de Java es que puede cambiar las propiedades del método en tiempo de ejecución. Uno de los usos es hacer público un método privado, para poder usarlo de todos modos. Podría funcionar al revés, haciendo que los métodos no deseados sean privados, en tiempo de ejecución. Aunque no se verá en la compilación, se verá tan pronto como se pruebe el proyecto.

Este artículo muestra cómo modificar propiedades de métodos en tiempo de ejecución. Aquí está la parte interesante:

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
fuente
1
Gracias. Primero voy a probar la solución de MattDavey porque me permite hacer análisis estáticos. Dicho esto, si todos los enfoques estáticos fallan, probaré su solución.
Apoorv Khurasia
1
Eso no funcionará, creo. Para el código compilado, la última vez que se verifican las reglas de visibilidad es en el momento de la carga, cuando se verifican los códigos de bytes. Los cambios posteriores que utilizan las API reflexivas solo afectarán a otras llamadas reflexivas.
Stephen C
0

Queremos que los desarrolladores recuerden que no se recomienda usar esos métodos para este proyecto.

Como ya tenía que crear métodos de reemplazo en algunos casos. Crearía una clase de contenedor para toda la biblioteca y solo usaría su clase de contenedor.

Si la biblioteca se actualiza, deberá actualizar su código de todos modos. La clase de contenedor es lo suficientemente fácil de actualizar.

Evita que los desarrolladores usen el método incorrecto, aunque ... Me atrevo a decir que un desarrollador debería poder recordar qué métodos no debe usar.

Ramhound
fuente
3
no, no es razonable esperar que un desarrollador recuerde que simplemente "no debe usar" métodos perfectamente lógicos en una biblioteca que está usando. Uno o dos, tal vez, pero como regla general los seres humanos simplemente no pueden recordar ese tipo de cosas de manera confiable. No se puede confiar en que los pilotos altamente entrenados y absolutamente motivados recuerden todos los detalles de cómo despegar el avión de forma segura, ¡por eso hay listas de verificación en la cabina!
Michael Kohne
Eso es exactamente lo que quiero. Use esa función y el IDE genera una advertencia.
Apoorv Khurasia
@MichaelKohne: cuando tuve un problema similar al del autor, no tuve problemas para recordar qué métodos debería utilizar. La biblioteca en cuestión era fácilmente 100 métodos diferentes.
Ramhound