2011-03-24 7 views
8

Me gustaría poder comparar dos versiones de una clase/biblioteca para determinar si ha habido algún cambio que pueda romper el código que lo llama. Por ejemplo considerar algunas Foo clase que tiene un método en la versión A:Herramienta para buscar incompatabilities en las firmas/campos de métodos

public String readWidget(Object widget, Object helper); 

y en la versión B el método se convierte en:

public String readWidget(Object widget); //removed unnecessary helper object 

o algo similar en el caso de un campo:

version a: public static Object sharedFoo; 
version b: static Object sharedFoo; //moved to package private for version b 

Me gustaría tener una herramienta que marque estos cambios como posibles incompatibilidades (pero idealmente no al revés, es decir, aumentando la visibilidad de un método). Ahora sé que puedo hacerlo a través de reflexiones o analizando el resultado de javap, sin embargo, parece que debería haber una herramienta existente (preferiblemente no comercial). Así que quería ver si alguien puede recomendar algo antes de cometer el error de rodar el mío/reinventar la rueda innecesariamente.

Respuesta

2

Guava usa JDiff para reportar version changes, ¿lo puedes encontrar también útil?

+0

No estoy seguro de que esto sea exactamente lo que estoy buscando, pero está bastante cerca. También he estado mirando japitools. –

3

Puede que no entienda la pregunta, pero ¿no es el compilador la herramienta exacta que resolvería este problema?

Vuelva a compilar las clases que utilizan Foo en contra de la nueva versión de Foo se iluminará muy rápidamente si hay incompatibilidades.

+1

Su afirmación es cierta, sin embargo, estas son clases que deben proporcionarse a recursos externos, de modo que si se rompe su compilador se quejará, y no quiero que eso les sorprenda. La idea es no romper su compatibilidad, básicamente asegurando que haya suficiente tiempo para que las cosas se desaconsejen antes de romper la compatibilidad. En otras palabras, me gustaría hacer un análisis preventivo antes de que llegue al punto de los errores del compilador. –

2

Aquí está la respuesta que no quería, pero yo creo que es una respuesta válida:

  1. Escribir un conjunto de pruebas unitarias que invocan cada método único de la API (que ya tiene esto, ¿verdad?: -)).
  2. Cuando realizas un cambio en la API, recompila la nueva versión de tu API pero no las pruebas de la unidad.
  3. Ejecuta el conjunto de pruebas "obsoleto" de unidad contra la API "nueva". Este conjunto de pruebas rancio convertirse en un canario, imitando la situación de que los clientes de su API estarían en.

El problema primera con sólo volver a compilar todo el código del cliente es que podría no ser posible. Es posible que el código no le pertenezca a usted; podría ser un código personalizado que uno de sus clientes haya escrito y no esté disponible para usted.

El segundo problema con solo volver a compilar el código de cliente es que a veces, incluso no obtendrá un error de compilación porque no es necesario cambiar el código de llamada. Me encontré con un problema como este una vez. Tenía un método de API como este:

public void doSomething(){ 
} 

con código que vinculó. Quería cambiarlo a esto:

public boolean doSomething() { 
} 

Así lo hice y volví a compilar. No hubo errores, porque el código que llamó a la primera versión de doSomething() se volvió a vincular de forma silenciosa a la nueva versión (descartando el valor de retorno, que es válido en Java).Poco sabía, sin embargo, que hizo cambiar el bytecode de la clase externa cuando volví a compilar. Comenzamos a obtener errores donde se actualizaba la API pero no se recompilaba el código que la utilizaba.

Por lo tanto, en lugar de buscar errores, debería haber estado buscando en qué archivos externos se modificó su código de bytes. En ese punto, diría que solo deberías usar pruebas unitarias para este fin, ya que deberías escribirlas de todos modos.

Cuestiones relacionadas