En una base de código heredada, ¿cómo puedo averiguar rápidamente qué se está utilizando y qué no?

21

Me han pedido que evalúe lo que parece ser una base de código heredada sustancial, como precursor para tomar un contrato que mantenga esa base de código.

Esta no es la primera vez que he estado en esta situación. En el presente caso, el código es para un sitio de juegos multijugador de alto perfil y bastante carga, que admite al menos varios miles de jugadores en línea a la vez. Como muchos de estos sitios son, este es una mezcla de tecnologías de front-end y back-end.

La estructura del sitio vista desde adentro hacia afuera es un desastre. Hay carpetas con el sufijo "_OLD" y "_DELETE" en todo el lugar. Muchas de las carpetas parecen no tener ningún propósito o tienen nombres muy crípticos. Podría haber cualquier cantidad de scripts antiguos y no utilizados, incluso en carpetas de aspecto legítimo. No solo eso, sino que indudablemente hay muchas secciones de código desaparecidas incluso en scripts que de otro modo serían operativos (una preocupación mucho menos apremiante).

Este es un traspaso de los mantenedores titulares, de regreso a los desarrolladores / mantenedores originales del sitio. Como es comprensiblemente típico en este tipo de escenarios, el titular no quiere tener nada que ver con el traspaso más que lo que se les exige por contrato y legalmente para llevarlo al responsable de mantenimiento recientemente elegido. Por lo tanto, extraer información sobre la estructura del sitio existente fuera del titular es simplemente imposible.

El único enfoque que viene a la mente para ingresar a la base de código es comenzar desde la raíz del sitio y navegar lenta pero seguramente por los scripts vinculados ... y es probable que haya cientos en uso y cientos más que no. Dado que una parte sustancial del sitio está en Flash, esto es aún menos sencillo ya que, particularmente en aplicaciones Flash antiguas, los enlaces a otros scripts pueden estar integrados en archivos binarios (.FLAs) en lugar de en archivos de texto (.AS / ActionScript).

Por lo tanto, me pregunto si alguien tiene mejores sugerencias sobre cómo abordar la evaluación de la base de código en su conjunto para la mantenibilidad. Sería maravilloso si hubiera alguna forma de ver un gráfico de frecuencia de acceso a los archivos en el sistema operativo del servidor web (al que tengo acceso), ya que esto podría ofrecer una idea de qué archivos son más críticos, a pesar de que no poder eliminar aquellos archivos que nunca se usan (ya que algunos archivos podrían usarse solo una vez al año).

Ingeniero
fuente
77
No sé lo suficiente sobre flash, pero si obtiene errores de compilación cuando no hay código, debería poder cambiar el nombre de las carpetas para ver si están referenciadas.
Oded
Solución malvada: bórrelos y espere los errores / informes de errores. (¡Solo asegúrate de que sea recuperable!)
Izkata
1
@Nick ¿Podría aclarar si le pagan por la evaluación como parte de la próxima fase del contrato que todavía tiene que ofertar / obtener? Su respuesta no cambiará la pregunta "¿hay una herramienta?", Pero algunos de nosotros podríamos elaborar respuestas sobre el proceso que se adaptaría mejor a su situación (por ejemplo, evitar que se joda, etc.).
jcmeloni
@jcmeloni No, no me pagan por la evaluación. Pero en mi experiencia , y por pequeñas cosas que he recogido en los últimos días, no tienen a nadie más en la mesa en este momento. Mi conjunto de habilidades es bastante inusual, por lo que estoy aún más tranquilo de que no tengan a nadie más compitiendo por él, según la cita. La cotización real en cuestión es de mi futuro cliente a su cliente, que está planeando volver a adjudicarles el contrato. Realmente desde mi fin, estoy destinado a ayudarlos a proporcionar dicha cita. HTH.
Ingeniero
¡@Oded Rename es definitivamente más fácil que la eliminación de prueba y error! Bien pensado allí. Esa es una herramienta más en la caja.
Ingeniero

Respuestas:

32

Dado que lo que se le pide que haga es proporcionar información para que su cliente escriba una propuesta apropiada al otro cliente (propietario del código de pesadilla) para cualquier trabajo en ese código, voy a continuar una extremidad y decir que no vas a hacer ninguna prueba exhaustiva o refactorización ni nada por el estilo en este momento. Probablemente tenga muy poco tiempo para obtener una estimación aproximada. Mi respuesta se basa en mi experiencia en la misma situación, por lo que si mi interpretación es incorrecta, simplemente ignore todo lo que sigue.

  • Use una herramienta de araña para tener una idea de qué páginas hay y qué es entrante. Incluso una herramienta básica de comprobación de enlaces, no una herramienta específica de "araña con fines de auditoría", será útil a este respecto.
  • Haga una hoja de cálculo básica de auditoría / inventario. Esto podría ser tan simple como una lista de archivos y su hora de última modificación, organizada por directorio. Esto lo ayudará a tener una idea del alcance, y cuando llegue a directorios como _OLD y _DELETE, puede hacer una gran nota de que a) su evaluación se basa en cosas que no están en esos directorios b) la presencia de esos directorios y el potencial para pesadillas ocultas / ocultas atestiguan problemas más profundos que deberían tenerse en cuenta en la oferta de su cliente , de alguna manera. No tiene que pasar millones de años enumerando los posibles problemas en _OLD o _DELETE; la información alimentará la oferta eventual.
  • Dado que está revisando lo que parece una aplicación completamente basada en la web, incluso las herramientas estándar de análisis de registros serán su amigo. Podrá agregar a la hoja de cálculo una sensación de "esto está en el top 10 de los scripts accedidos" o algo así. Incluso si los scripts están incrustados en archivos Flash y, por lo tanto, no se pueden dividir, existe una alta probabilidad de que se acceda a ellos a través de POST o GET, y que se muestren en los registros del servidor. Si sabe que tiene 10 scripts de acceso elevado, no 100 (o viceversa), esto le dará una buena idea de cómo será el trabajo de mantenimiento.

Incluso en un sitio complicado, lo que describí anteriormente es algo que podría hacer en un día o día y medio. Dado que la respuesta que le va a dar a su cliente es algo así como "esto va a ser un dolor tremendo en el trasero, y aquí hay algunas razones por las que simplemente le pondrá un lápiz labial a un cerdo, por lo que debe ofertar en consecuencia "o" cualquier persona razonable haría una oferta para no mantener, sino para comenzar de nuevo, por lo que debe ofertar en consecuencia "o incluso" esto no es tan malo, pero será un flujo constante de trabajo en un período de tiempo determinado, así que haga una oferta en consecuencia " , el punto es que ellos están pasando a estar haciendo la oferta y por lo tanto no necesitan ser tan preciso como lo sería si estuviera siendo contratados directamente para hacer un contenido completo de auditoría y la arquitectura.

jcmeloni
fuente
2
+1 Esta es una respuesta fantástica. ¿Dónde está ese botón +5? ...
Ingeniero
1
TL; DR: no te envíes por una madriguera de conejo hasta que tengas que hacerlo. :)
jcmeloni
4

Recomiendo refactorizar el código fuente existente (en lugar de una reescritura) utilizando los patrones que se encuentran en el libro " Trabajar eficazmente con código heredado ".

El libro detalla varios mecanismos para cubrir eficientemente el código heredado en las pruebas unitarias, para que luego pueda comenzar a refactorizar el código de manera segura. El libro está dividido en partes, una que describe la filosofía detrás del enfoque y luego varios capítulos que resuelven problemas particulares, como "Se necesita una eternidad para hacer un cambio", "No tengo mucho tiempo y necesito cambiarlo". y "No puedo incluir esta clase en un arnés de prueba". Cada uno de estos capítulos tiene técnicas detalladas y probadas que lo ayudan a aprender cómo aplicar las mejores prácticas en las pruebas a problemas del mundo real.

Leer el libro me dejó con una sensación muy real de que "no estamos solos" ... muchos de nosotros, o quizás todos, estamos trabajando con bases de códigos complejas que se han vuelto difíciles de manejar. Las técnicas enumeradas en el libro me han dado muchas esperanzas, y personalmente he podido aplicarlas casi de inmediato.

La publicación de blog de Joel Spolsky hace un gran trabajo al explicar por qué es mejor mantener una base de código existente y funcional en lugar de comenzar desde cero. Elegí una cita del artículo que lo resume, pero es una lectura fantástica.

"Hay una sutil razón por la que los programadores siempre quieren tirar el código y comenzar de nuevo. La razón es que piensan que el código antiguo es un desastre. Y aquí está la observación interesante: probablemente estén equivocados. La razón por la que piensan que el código antiguo El código es un desastre debido a una ley fundamental y fundamental de la programación:

Es más difícil leer el código que escribirlo ". - http://www.joelonsoftware.com/articles/fog0000000069.html

Kyle Hodgson
fuente
44
+1. En respuesta al comentario de Joel, "Bien no debería ser". Porque no veo el problema como inherente. Lo veo en parte como el hecho de que muchas personas escriben código de mala calidad y no les importa, mientras que otras escriben un código razonablemente bueno pero viven según el concepto de "código autodocumentado" ... que es simplemente BS: Uno puede halagar el propio estilo de codificación que uno desea en privacidad, pero cuando se trata de bases de código públicas solo genera comentarios como si no hubiera un mañana. No duele Y, finalmente, hay personas que tienen que hacer que las cosas funcionen en bases de código heredadas, con un presupuesto ajustado.
Ingeniero
2

En una base de código Java típica, consideraré usar herramientas como PMD, FindBugs o Sonar y luego trataré de comprender las herramientas de informes (código muerto, código no documentado, código duplicado, etc.)

Con base en los informes, trataré de encontrar las diferentes capas de la aplicación / sitio (capa empresarial, DB, SQL, etc.)

Si las capas están acopladas (html dentro del servlet, sql dentro del código java), comenzaré primero desacoplando cada uno de estos pasos, se debe considerar aislado y puede confirmar al final de cada uno (al iniciar una rama y luego combinar) .

Abderrazak BOUADMA
fuente
1
Gracias. Aunque su respuesta es algo específica de Java, es interesante ver su enfoque en capas ... pelar la cebolla, por así decirlo. Algo sobre lo que pensar.
Ingeniero
1

Según su descripción, parece que este código ha alcanzado el estado imposible de mantener, lo que significa que el mejor enfoque es una reescritura completa. Los desarrolladores tendrían cheques de pago mucho más pequeños si hubiera herramientas de calidad que funcionaran para mantener una base de código desordenada mantenible. Es posible revisar y limpiar el viejo código innecesario de las carpetas, pero es una tarea manual y es probable que no obtenga todo de todos modos sin un tiempo razonable. Solo estoy adivinando aquí, pero apuesto a que el código de trabajo en sí es tan desordenado como la estructura del archivo, lo que significa que incluso si logras recortar la base de código al código de trabajo activo, seguirá siendo una pesadilla para actualizar o arreglar cualquier cosa.

Quisiera enfatizar que el esfuerzo requerido para obtener el código existente en un estado mantenible sería igual o mayor que el esfuerzo para comenzar de nuevo en una reescritura. parte de mantener algo es saber cuándo "llevarlo detrás del cobertizo y dispararle".

Ryathal
fuente
Por lo general, estaría 100% con usted en el enfoque de tirar y reescribir. Pero en este caso (y al menos por ahora), me pagarán solo por el trabajo para mantener el sitio, en lugar de una revisión más extensa que tomaría varias semanas. Además, incluso si quisiera en este momento, no podría seguir haciendo eso y mantener los otros contratos que tengo sobre la marcha, ya que mi disponibilidad semanal para esto es explícitamente limitada: mi contrato principal debe cumplirse a su Mínimo de 40 horas semanales.
Ingeniero
1
No estoy de acuerdo con tirar y reescribir! De joelonsoftware.com/articles/fog0000000069.html ... "Hay una razón sutil por la que los programadores siempre quieren tirar el código y comenzar de nuevo. La razón es que piensan que el código antiguo es un desastre. Y aquí está la observación interesante : probablemente estén equivocados. La razón por la que piensan que el código antiguo es un desastre es debido a una ley fundamental y fundamental de la programación: es más difícil leer el código que escribirlo ". En cambio, recomiendo refactorizar: amazon.ca/Working-Effectively-Legacy-Michael-Feathers/dp/…
Kyle Hodgson el
1
@KyleHodgson a veces el código en realidad es un desastre, y cuando estás en el punto de que es un desastre encontrar el código antes de leerlo, es hora de comenzar de nuevo.
Ryathal
Sí, no creo que sea tan claro como eso, aunque parece que vale la pena leer ese libro. Depende mucho del tamaño / complejidad de la base de código y de los cuerpos cálidos disponibles para hacer el trabajo.
Ingeniero
1

Un rastreador web puede ayudarlo a determinar qué URL son accesibles. Especialmente si es lo suficientemente inteligente como para extraer enlaces de Flash o JavaScript. Una vez que tenga una lista de páginas web, revíselas y enumere los archivos a los que hacen referencia. Cualquier cosa que quede después de este proceso debe considerarse un código muerto.

Mike Baranczak
fuente
1
Estoy totalmente en desacuerdo con tu última oración. El rastreador solo puede averiguar qué páginas están vinculadas entre sí como un gráfico dirigido con un punto de partida simple o múltiple. Pero cuando hablamos de un sitio web, también hay las llamadas "páginas de destino", que enlazan con otras páginas, pero no hay enlaces que apunten a ellas. Además, puede haber partes antiguas de la interfaz administrativa que también están desconectadas de otras páginas. Actualmente tengo un proyecto de este tipo.
scriptin
0

Nota: Puse un acento en el uso de la base de datos, mientras preguntaba sobre el uso del código en sí. La respuesta todavía se aplica a ambos casos en cada punto que mencioné.

Ya respondió en parte su propia pregunta en el último párrafo: vea a qué se accede mientras se ejecuta la aplicación.

  1. Es posible que desee crear un perfil de la base de datos y solicitar al generador de perfiles que registre todas las consultas de un día. Le dará una visión general de los objetos de base de datos más utilizados, pero no le dirá cuáles nunca se utilizan. Además, debe tener cuidado con los resultados: por ejemplo, una tabla puede usarse exclusivamente a través de procedimientos almacenados, pero cuando observe las consultas del generador de perfiles, parecería que la tabla no se usa en absoluto.

  2. Revisar el código fuente, buscar consultas es más útil, y después de recopilar todas las consultas, puede comprender bien el uso de la base de datos, no en términos de frecuencia (aquí es donde un perfilador es útil), sino en términos de uso / no Mesas usadas. Lamentablemente, para una base de código mal escrita / no mantenida durante años, puede ser extremadamente difícil y propensa a errores , especialmente si las consultas se construyen dinámicamente (imagine un método que, en a select, utiliza un parámetro como el nombre de la tabla; ¿cómo puede posiblemente sepa cuáles son los valores posibles del parámetro simplemente mirando el código fuente?).

  3. El análisis estático y algunos compiladores también pueden revelar código muerto, pero aún así no le da la respuesta que desea.

  4. El análisis de los datos en sí o de los metadatos de la base de datos puede revelar información interesante. Por ejemplo, sería fácil afirmar que la tabla LogonAudit(uniqueidentifier LogonAuditId, datetime LogonEvent, ...)no se utiliza por más tiempo si contiene 10 000 registros por día durante los años 2006 a 2009, y no hay registros a partir de septiembre, 18 º , 2009. Lo mismo no es cierto para una tabla que contiene los datos sangrados para ser principalmente de solo lectura.

Esos cuatro puntos juntos le darán la lista de tablas usadas. Los restantes se usan o no. Puede hacer afirmaciones y probarlas, pero sin una buena cobertura de pruebas unitarias, no sería fácil. Cualquier forma "fácil" también fallaría. Por ejemplo, si tiene una products_delme_not_usedtabla, puede afirmar que la tabla no se usa en absoluto y buscar "productos_delme_not_used" en su código. Esto es optimista: no es inusual encontrar al candidato DailyWTF como este en una antigua base de código:

// Warning: WTF code below. Read with caution, never reuse it, and don't trust
// the comments.

private IEnumerable<Product> GetProducts()
{
    // Get all the products.
    return this.GetEntities<Product>("PRODUCT");
}

private IEnumerable<T> GetEntities<T>(string tableName)
{
    // Everyone knows that SQL is case sensitive.
    tableName = tableName.ToLower();

    if (tableName == "user" || tableName == "product")
    {
        // Those tables were renamed recently in the database. Don't have time
        // to refactor the code to change the names everywhere.
        // TODO: refactor the code and remove this `if` block.
        tableName += "s";
    }

    if (this.IsDelme(tableName))
    {
        // We have some tables which are marked for deletion but are still
        // used, so we adjust their name.
        tableName = this.Delme(tableName);
    }

    return this.DoSelectQuery<T>("select top 200 * from " + tableName);
}

private bool IsDelme(string name)
{
    // Find if the table is among candidates for removal.
    List<string> names = this.Query<string>("select Names from DelmeTables");
    return names.Contains(name);
}

private string Delme(string name)
{
    // Return the new name for a table renamed for deletion.
    return string.Join("_", new [] { name, "delme", "not", "used" });
}

¿Puedes darte cuenta de que este código realmente usa products_delme_not_usedtable?

Si yo fuera tú lo haría:

  1. Mantenga todos los objetos de la base de datos en su lugar,
  2. Refactorice toda la aplicación (si vale la pena),
  3. Documente (mientras refactoriza) la aplicación y específicamente el uso de la base de datos.

Cuando termine los últimos dos pasos, probablemente tendrá una mejor comprensión del uso de la base de datos, lo que ayudará a calcular los nombres de las tablas que ya no se usan, y puede eliminarlas de manera más o menos segura.

Arseni Mourzenko
fuente
0

Me parece que necesita obtener suficiente información para crear una cotización, así que me concentraré en ese esfuerzo.

Intentaría determinar cuántos casos de uso hay involucrados en este sitio. Esto generalmente le da una idea de cuán grande y complicado es el sitio y cuánto tiempo tomará volver a crear o mantener el sitio / aplicación.

Sí, es cierto que a veces el código ya no se usa y hará que la aplicación se vea un poco más grande de lo que realmente es, pero no creo que esto afecte a los números en más del 20% como máximo , así que no me preocuparía por esa parte.

Mirar el código fuente, las páginas web y las tablas de la base de datos debería ayudarlo a descubrir esto.

También puede considerar limitar la cantidad de horas por mes que pasará en este proyecto por la tarifa predeterminada para protegerse.

En cuanto a descubrir lo que se usa y no se usa, realmente no hay una manera fácil. Las herramientas de análisis de código pueden ayudar, pero como se trata de un mal tan mixto, no creo que exista una sola herramienta que pueda ayudar. Para cada área específica, probablemente pueda encontrar una herramienta de análisis de código que pueda ayudar.

Sarel Botha
fuente