¿Cómo abordar la refactorización de una aplicación web existente?

11

He estado leyendo y pensando mucho últimamente, y he llegado a la conclusión de que tal vez debería repensar mi estrategia de desarrollo web. Estoy haciendo mucha programación sobre la marcha, y en los 2 años que llevo trabajando en una aplicación web PHP, lo que podría haber comenzado como una pequeña herramienta se convirtió en un gran proyecto. Pero hay un montón de código heredado de mí y de mi predecesor, fragmento de código que podría tener sentido en ese momento, pero ahora estoy cuestionando la utilidad de dicho código en la forma en que realmente es. Además, cosas como las pruebas unitarias y el desarrollo impulsado por pruebas no estaban en mi alcance hasta hace muy poco.

Entonces, ¿cómo abordaría la refactorización de la aplicación web? ¿Cuáles serían las cosas que debería buscar y en qué orden? ¿Qué pasa con el juego de navegador versus la aplicación web funcional? ¿Habría entonces una diferencia en el enfoque?

Eldros
fuente
44
Si no está roto, no lo arregles. Pase más tiempo escribiendo pruebas y menos tiempo haciendo cambios innecesarios.
Macneil
Solo por interés. ¿Qué idioma / tecnologías ha usado para escribir su aplicación? ¿Qué tipo de sitio es? Ver welie.com/patterns -> Contexto de diseño -> Tipos de sitio
JW01
@ JW01 Uso PHP para lógica interna y AJAX para gestión de vistas y validación de formularios. Esta sería una variante del patrón de aplicación basado en la web, pero solo está disponible en un entorno dado, ya que es una herramienta interna.
Eldros
Tenía una imagen completamente diferente de tu aplicación en mi cabeza cuando respondí la pregunta. Tiene mucha más libertad para cambiar la API que si fuera de dominio público.
JW01
@ JW01 No quería ser demasiado específico, ya que quería que esta pregunta también fuera útil para otros.
Eldros

Respuestas:

6

Más o menos de la misma manera que te acercas a cualquier tipo de código heredado. Encuentras una pieza que se puede probar, escribes pruebas y la refactorizas.

Si no puede encontrar una pieza fácilmente comprobable, tendrá que hacerlo comprobable sin el arnés de seguridad de un conjunto de pruebas, en cuyo caso cambia con mucho cuidado algún código casi comprobable para que sea comprobable.

El código que no muestra cosas al navegador (código de "infraestructura", modelos, cosas que tocan bases de datos) podría ser un buen lugar para comenzar.

Editar: Prueba de interfaz de usuario: con la advertencia de que tengo poca experiencia aquí, un amigo mío hace esto: ejecuta una pieza de código generador de HTML. Luego piratea su código y compara el código recién generado con la versión anterior (usando diff; no se ha automatizado por completo). Los cambios en el HTML significan que su refactorización se rompió.

Frank Shearar
fuente
¿Cómo recomendaría probar la parte "vista" de una aplicación heredada, es decir, la parte HTML / JavaScript / CSS / etc. Estoy de acuerdo en que la prueba unitaria es el camino a seguir, pero la prueba del código de la aplicación parece difícil de automatizar.
Justin Ethier
al crear pruebas para una interfaz de usuario web: comparar HTML antiguo con HTML nuevo es una forma un poco frágil de hacer las cosas. Tiendo a identificar la semántica de una página web y probar eso. Es decir, "¿Ha cambiado la impresión web (título de la página, título, palabras clave, enlaces salientes, formularios)?" no "¿Ha cambiado el HTML?".
JW01
Puede probar aplicaciones web con un 'navegador sin cabeza', básicamente una biblioteca que es para una unidad de prueba de lo que es un navegador para un tipo de control de calidad. En el mundo de Java, hay HTMLUnit (Java puro, autocontenido) y WebDriver (controla de forma remota un navegador real como Firefox). Mi proyecto tiene un conjunto de cientos de pruebas escritas de esta manera.
Tom Anderson
@ JW01 Tienes toda la razón: es muy frágil. Es excelente para probar una refactorización de una manera única: puede comprobar que la refactorización no cambió la salida, pero cada vez que cambia el HTML generado, debe guardar el HTML "nuevo esperado".
Frank Shearar
10

Hay un gran libro sobre esto llamado "Trabajando eficazmente con código heredado" de Michael Feathers. Seamos realistas, todos tenemos código heredado.

Lo principal es probar el nuevo código que está creando. Como debe tocar otras piezas de código, también encontrará oportunidades para ponerlas a prueba. Es un proceso largo y lento, pero si lo hace sistemáticamente, realmente puede mejorar el producto en general con el tiempo.

Marcie
fuente
3
"Seamos realistas, todo lo que estamos haciendo es escribir el software heredado de mañana hoy". - Martin Fowler
Frank Shearar
3
  • Sí, las aplicaciones web son diferentes a los sitios web

Los trataría por separado. Si tiene una parte de su sitio que es simplemente una colección de documentos (que se ve igual para usuarios anónimos y usuarios registrados), entonces el mejor método para estructurarlo es muy diferente de una aplicación web que sirve páginas dinámicamente diferentes a cada usuario Divida esas dos partes del sitio en dos aplicaciones / componentes y aborde cada parte de manera diferente.

  • Comience a usar el control de versiones

Una vez que su código esté bajo el control de la versión, puede pasar y, con confianza, eliminar todo el código innecesario que había guardado 'por si acaso', etc. No sé cómo sobreviví sin el control de la versión.

  • Reducir los infinitos

Si cuatro URL diferentes apuntan al mismo recurso, entonces el problema es mucho mayor. Terminas lidiando con una cantidad infinita de URL. Tan pronto como pueda, asegúrese de tener una política de normalización de URL. Una vez hecho esto, puede comenzar a adjuntar significados semánticos a las URL y poder realizar búsquedas inversas de recurso a URL. Esto le permite separar la 'impresión web' de los 'recursos' del sitio.

Tienes que preguntarte, "dada una url, ¿cuál es su forma normalizada?". Una vez que tengas esto anclado. Luego, más de 50,0000 URL en su sitio pueden reducirse a 2,000. lo cual es mucho más fácil de comprender y manejar en tu mente.

ver: http://www.sugarrae.com/be-a-normalizer-a-c14n-exterminator/

  • Comience modelando 'lo que es', no 'lo que quiere que sea'

Si está ordenando un sitio heredado, que no fue diseñado teniendo en cuenta las mejores prácticas desde el principio, entonces es tentador pasar de "un desastre" al "diseño ideal". Creo que debe hacerlo al menos en dos pasos: 'desorden' -> 'código heredado bien modelado' -> 'código nuevo ideal con características adicionales'. Deja de agregar funciones. Concéntrese en arreglar el desastre o encapsularlo detrás de una capa anticorrupción. Solo entonces, puede comenzar a cambiar el diseño en algo mejor.

Ver: http://www.joelonsoftware.com/articles/fog0000000069.html

Ver: http://www.laputan.org/mud/

  • Ponerlo a prueba es una buena idea.

Cree un conjunto de pruebas / marco y comience a agregar pruebas. Pero, es bastante difícil probar algún código heredado. Por lo tanto, no te obsesiones demasiado con eso. Mientras tenga el marco allí, puede agregar pruebas poco a poco.

Ver: http://www.simpletest.org/en/web_tester_documentation.html

  • Ten coraje en tus convicciones

La mayor parte de la literatura sobre las mejores prácticas de desarrollo de software está centrada en el escritorio / Enterprise App Centric. Mientras su sitio está en un desastre, lee estos libros y puede asombrarle la sabiduría que emana de ellos. Pero, no olvide que la mayor parte de esta mejor práctica se ha acumulado en tiempos anteriores a la importancia de la web / SEO. Sabe mucho sobre la web moderna, más de lo que se menciona en libros clásicos como POEA, Gof, etc. Hay mucho que aprender de ellos, pero no descarte por completo su propia experiencia y conocimiento.


Podría seguir. Pero esas son algunas cosas que he elegido al refactorizar un antiguo sitio heredado en uno nuevo y brillante.

JW01
fuente
¡Buenos enlaces de referencia!
Nilesh
2

Antes de hacer nada, es mejor tener su proyecto en control de fuente. De esta manera, puede revertir los cambios o trabajar en cambios importantes en una rama separada, así como etiquetar hitos.

Luego, escriba pruebas para cualquier código que planee cambiar. No necesita hacer todo de una vez, escribiendo pruebas para todo. Justo en lo que planeas estar trabajando inmediatamente. La teoría dice que, dado el tiempo suficiente, la mayor parte del código base estará cubierto por pruebas. Tenga en cuenta que algunas refactorizaciones son "seguras" sin pruebas: estas están documentadas en el libro de Legacy Code mencionado anteriormente, y sin duda en otro lugar.

Con las pruebas establecidas para una sección de código, cambie el código. Haga lo que sea necesario, siempre y cuando las pruebas aún pasen.

Incluso con código heredado, puede hacer TDD si realiza adiciones o cambios. Simplemente escriba las pruebas primero para sus cambios anticipados, vea cómo fallan y luego realice los cambios.

Algunas herramientas pueden ser útiles aquí. NDepend puede señalar código altamente acoplado y otros olores. NCover rastrea los niveles de cobertura de su código. FxCop es esencialmente un verificador de corrección de código, más allá de lo que hace el compilador. Todas estas son herramientas útiles para tener a mano para un proyecto de cualquier tamaño real, especialmente la variedad heredada.

En definitiva, es un proceso de varios pasos. No intentes hacerlo todo de una vez, solo tómalo de a poco.

Grant Palin
fuente
-2

Si es lo suficientemente feo como para molestarme, es lo suficientemente feo como para eliminar todo y escribir un reemplazo de reemplazo.

Descubrirá que, la mayoría de las veces, se necesita la misma cantidad de tiempo para hacer esto, como para sentarse allí y caminar de puntillas alrededor de un desorden no organizado e indocumentado y acariciarlo suavemente.

Astucia
fuente
2
No estoy de acuerdo (aunque no te di -1). joelonsoftware.com/articles/fog0000000069.html
JW01
1
Realmente es demasiado una decisión situacional para defenderme con precisión. Es posible que no haga esto cuando estoy trabajando en una biblioteca masiva de Objective-C, sin embargo, no tengo reparos en escribir una biblioteca javascript completamente nueva.
Sneakyness
Muy mala idea! Desearía haber leído el artículo de Joel Spolsky al que @ JW01 se vinculó hace 2 años antes de que decidiera reescribir una aplicación PHP existente usando Angular & Bootstrap. Angular y Bootstrap son excelentes tecnologías, pero TODAVÍA estoy tratando de convertir esta vieja aplicación 2 años después. Debería haber modificado la aplicación existente y no haberla eliminado / reemplazado.
Zack Macomber
Estoy de acuerdo especialmente al tener en cuenta tu comentario. "escenario" es la clave que determina una decisión. ¿Deberías extraer esa enorme API que sirve a todo tu negocio? Quién sabe, hay mucho que considerar. Desea pruebas antes para probar después. El artículo vinculado es demasiado lineal, como si hubiera una talla única para todos, pero ¿qué pasa cuando algo tiene errores o es un código realmente antiguo? ¿El artículo realmente sugiere que no pasamos del legado con un código más nuevo, más fácil de leer y mantener? No hay blanco y negro en el mundo de desarrollo, solo escenarios y decisiones
James