¿Técnicas para reconstruir la basura y mantener la cordura? [duplicar]

38

Así que me siento en un tazón de espagueti c #, y necesito agregar algo o quitar algo ... pero tengo desafíos en todas partes, desde funciones que pasan argumentos que no tienen sentido, alguien que no entiende. las estructuras de datos abusan de cadenas, variables redundantes, algunos comentarios son audiencias rojas, la internacionalización se realiza en todos los niveles de salida, SQL no utiliza ningún tipo de DBAL, las conexiones de base de datos se dejan abiertas en todas partes ...

¿Existe alguna herramienta o técnica que pueda usar para al menos hacer un seguimiento de la "integridad funcional" del código (lo que significa que mis "mejoras" no lo rompen), o un recurso en línea con "patrones malos" comunes que ¿Explica una buena manera de transcribir el código? Básicamente estoy buscando una guía sobre cómo convertir la paja en oro.

Aquí hay algunos ejemplos de la misma función de 500 líneas:

protected void DoSave(bool cIsPostBack) {
  //ALWAYS  a cPostBack
  cIsPostBack = true;
  SetPostBack("1");
  string inCreate ="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
  parseValues = new string []{"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""};


  if (!cIsPostBack) { //.......
  //....
  //....
  if (!cIsPostBack) {

  } else {

  }
  //....  
  //....
  strHPhone = StringFormat(s1.Trim());
  s1 = parseValues[18].Replace(encStr," ");
  strWPhone = StringFormat(s1.Trim());
  s1 = parseValues[11].Replace(encStr," ");
  strWExt = StringFormat(s1.Trim());
  s1 = parseValues[21].Replace(encStr," ");
  strMPhone = StringFormat(s1.Trim());
  s1 = parseValues[19].Replace(encStr," ");
  //(hundreds of lines of this)
  //....
  //....
  SQL = "...... lots of SQL .... ";

  SqlCommand curCommand;

  curCommand = new SqlCommand();
  curCommand.Connection = conn1;

  curCommand.CommandText = SQL;
  try {
    curCommand.ExecuteNonQuery(); 
  } catch {}
  //....
}

Nunca he tenido que refactorizar algo como esto antes, y quiero saber si hay algo como una guía o una base de conocimientos sobre cómo hacer este tipo de cosas, encontrar patrones comunes y ofrecer las mejores soluciones para repararlos. No quiero atacar solo desde la órbita,

    
pregunta Incognito 08.04.2011 - 15:54

11 respuestas

30

Hay tres libros que recomendaría:

Todos estos libros hacen énfasis en colocar un "nido de seguridad" antes de dedicarse a la refactorización cuando sea posible. Esto significa tener pruebas que aseguren que no rompa la intención original del código que está refactorizando.

Y siempre haga una refactorización a la vez .

    
respondido por el Matthieu 08.04.2011 - 16:09
11

Esto es exactamente de lo que habla Martin Fowler en su libro Refactoring .

Resumen básico:

  • Pruebas de unidad! Primero, desea establecer pruebas para el código existente. Calcule cuáles son las entradas y las salidas esperadas y pruébelas. No pruebes el código. Realice una prueba según las especificaciones: no desea reproducir errores.
  • Refactorizar bits a la vez, manteniendo las pruebas a medida que avanza.
  • Tenga en cuenta que si no tiene ninguna prueba o para grandes porciones de código, una reescritura podría ser la opción más eficiente.

Esta entrevista con Martin Fowler sobre los temas del libro arroja mucha luz sobre el tema (en pruebas unitarias, pagos, encontrar errores a través de refactorización, refactorización y reescritura).

Tenga en cuenta que los malos patrones son malos por una razón: es una mala solución al problema. Eso significa que incluso si ha visto el mismo tipo de código incorrecto, no significa que el problema sea el mismo y que la mejor solución es probablemente diferente para cada caso.

    
respondido por el Nicole 08.04.2011 - 16:06
6

En mi experiencia anterior, definir de manera iterativa áreas de funcionalidad y extraer el código relevante en métodos / funciones será la forma más rápida de comenzar. Luego puede extraer el código, poner ese código en una función y luego probar para confirmar que no ha roto nada. Enjuague y repita hasta que haya terminado o hasta que tenga que agregar nuevas funciones. La refactorización iterativamente proporcionará más flexibilidad al permitirle tomar descansos ocasionales de la refactorización, especialmente si aún necesita / desea agregar un nuevo código. Psicológicamente, un enfoque iterativo le dará la satisfacción de ver que su base de código se vuelve más ordenada, lo que le facilitará completar esta tarea de refactorización.

    
respondido por el JW8 15.12.2011 - 17:40
4

Parece que lo que quieres es tener pruebas de unidad. Agregue casos de prueba que cubran el comportamiento existente, luego, cuando refactorice, puede confiar en sus pruebas para alertarlo sobre cualquier falla. Haga esto también en una nueva sucursal en el control de su fuente, para que los accidentes no se vuelvan catastróficos.

    
respondido por el Daenyth 08.04.2011 - 15:57
4

Haría algo como lo siguiente:

  • Envuelve todo el código en clases como puedas, agrupándolo por funcionalidad, pero dejándolo intacto de otro modo por ahora. Esto le permitirá clasificar su código.
  • Cree una capa de base de datos utilizando PDO.
  • Convierta su código al patrón MVC, teniendo especial cuidado de eliminar cualquier código PHP que genere innecesariamente HTML y transfiriéndolo a la vista. Sus controladores deben determinar qué modelo y qué vista cargar, y sus modelos deben contener todo lo demás.
  • Refactoriza tus clases restantes, una por una. Abordar las clases más generalizadas primero. Busque clases que hagan varias cosas y divídalos. Deshazte del código repetido. Hacer métodos de responsabilidad única.
  • Añade pruebas unitarias a medida que avanzas. Esto hará que su código sea más estable a largo plazo. Si necesita refactorizarlo nuevamente en el futuro, tendrá un contrato que especifica cómo se debe realizar el código. PHPUnit es un marco de prueba que puede usar, pero hay otros también.
respondido por el VirtuosiMedia 15.12.2011 - 18:02
3

Ingeniería inversa dirigida por pruebas.

Escriba pruebas de unidad para el "antes".

Refactor.

Asegúrese de que las pruebas se ejecutan después.

Elija piezas pequeñas que puedan identificarse claramente como pertenecientes a un único propósito o componente conceptual.

    
respondido por el S.Lott 08.04.2011 - 16:07
3

Comenzaría cubriendo la mayor parte de su código con pruebas automatizadas como pueda. Puede ser aburrido y tedioso, pero le permite capturar el comportamiento actual de su sistema. Luego, a medida que limpia las cosas y reescribe / refactoriza partes de su base de código, puede sentirse más seguro al no introducir una tonelada de regresiones. También es de esperar que puedas introducir pruebas de grano más fino que antes. Esto siempre me ha ayudado en el pasado.

    
respondido por el Matt H 15.12.2011 - 18:05
1

Definitivamente, deberías comenzar por escribir pruebas unitarias, como han mencionado otros. Desafortunadamente, sin embargo, este código claramente necesita ser eliminado de la existencia. Ahora bien, si está funcionando bien de la forma en que está funcionando, tal vez no sea necesario, pero cualquier maintinece se convertirá rápidamente en muy costoso. Este código parece ser prácticamente la definición de inconmovible. Pero bueno, con un mejor diseño, probablemente puedas soplar una reescritura mucho más rápido que la persona que la encontró (sé que los vaqueros pueden ser programadores rápidos, pero este programador no era un vaquero ... creo que podría haber sido literalmente una vaca) .

    
respondido por el Morgan Herlocker 08.04.2011 - 16:39
1

Si es una aplicación web, puede probar el "resultado" con un poco de creatividad. Use algo como selenio en el lado del navegador para asegurarse de que los bits de la interfaz de usuario todavía funcionan y luego verifique la base de datos en la parte posterior Confirme que su actualización se realizó. Su caja negra es grande, pero al menos puede revisar sus cambios de forma automática y repetitiva.

    
respondido por el Wyatt Barnett 08.04.2011 - 16:43
1

Como han dicho otros, tu arma principal aquí son las pruebas unitarias. Independientemente de lo que hagas, necesitarás estos.

En cuanto a las herramientas para ayudar a la refactorización, existen, pero no harán arreglos a gran escala para usted. Cosas como Resharper ayudarán a mover los métodos, cambiar el nombre de las variables, extraer interfaces, etc., pero sospecho que tendrá que hacer una mucha refactorización manual también.

    
respondido por el Steve Haigh 08.04.2011 - 18:39
1

Eso no es lo que es refactorizar. La refactorización es dividir un fragmento de código en sus componentes (factores) de una manera que mejora la reutilización y la legibilidad del código.

Para mejorar el código terrible es reescribir . Entonces, la pregunta es ¿cómo hace para reescribir toda una aplicación de código incorrecto? La respuesta es que empiezas desde cero. Reescribir poco a poco es mucho más difícil y, a la larga, llevará más tiempo hacerlo correctamente.

    
respondido por el Igby Largeman 15.12.2011 - 17:41

Lea otras preguntas en las etiquetas