¿Es útil para el código mini-refactor con la esperanza de mejorar la calidad, o es simplemente "mover el código" sin mucho beneficio?

12

Ejemplo

Encontré un código monolítico que hace "todo" en un solo lugar: cargar datos de la base de datos, mostrar el código HTML, actuar como un enrutador / controlador / acción. Comencé a aplicar SRP moviendo el código de la base de datos a su propio archivo, proporcionando una mejor nomenclatura para las cosas, y todo se veía bien, pero luego empecé a tener dudas sobre por qué hago esto.

¿Por qué refactorizar? ¿Cuál es el propósito? ¿Es inútil? ¿Cuál es el beneficio? Tenga en cuenta que, en su mayoría, dejé el archivo monolítico tal como está, pero que solo reproduje la parte más pequeña que era relevante para el área en la que necesitaba trabajar.

Código original:

Para dar un ejemplo concreto, encontré este fragmento de código: carga las especificaciones del producto ya sea por un ID de producto conocido o por un ID de versión seleccionado por el usuario:

if ($verid)
    $sql1 = "SELECT * FROM product_spec WHERE id = " . clean_input($verid);
else
    $sql1 = "SELECT * FROM product_spec WHERE product_id = " . clean_input($productid) ;
$result1 = query($sql1);
$row1 = fetch_array($result1);
/* html markup follows */

Refactorización:

Ya que estoy haciendo un trabajo que me obliga a cambiar las cosas en esta parte específica del código, lo cambié para usar el patrón de repositorio y lo actualicé para usar las instalaciones de MySQL orientadas a objetos:

//some implementation details omitted 
$this->repository = new SpecRepository($mysql);
if ($verid)
    $row1 = $this->repository->getSpecByVersion($verid);
else 
    $row1 = $this->repository->getSpecByProductId($productid);
/* html markup follows to be refactored or left alone till another time*/

//added new class:
class SpecRepository extends MySqlRepository
{

    function getSpecByVersion(int $verid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE id = ?
        ", $verid)->getSingleArray();
    }

    function getSpecByProductId(int $productid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE product_id = ?
        ", $productid)->getSingleArray();
    }
}

¿Debo hacer esto?

Mirando hacia atrás a los cambios, el código sigue ahí, código con la misma funcionalidad, pero en diferentes archivos, diferentes nombres, lugares, utilizando un estilo más orientado a objetos en lugar de procedimientos. En realidad, es gracioso observar que el código refactorizado se ve mucho más abultado a pesar de tener la misma funcionalidad.

Preveo algunas respuestas que dicen "si no sabes las razones por las que te refieres, no lo hagas", y tal vez esté de acuerdo. Mis razones son mejorar la calidad del código con el tiempo (y mi esperanza es que lo haré siguiendo el SRP y otros principios).

¿Son esas razones lo suficientemente buenas o estoy perdiendo el tiempo en "reorganizar el código" de esta manera? En general, refactorizar esto se siente un poco como pisar el agua para ser honesto: toma tiempo y se vuelve más "separado" en lo que respecta a SRP, pero a pesar de mis buenas intenciones, no siento que esté haciendo mejoras sorprendentes. Por lo tanto, debatir si es mejor dejar el código como antes y no refactorizar.

¿Por qué me refactoricé en primer lugar?

En mi caso, estoy agregando una nueva funcionalidad para una nueva línea de productos, por lo que debo seguir la estructura de código existente para líneas de productos similares o escribir la mía.

    
pregunta Dennis 08.12.2017 - 16:50

5 respuestas

13

En el ejemplo concreto que dio, la refactorización podría no haber sido necesaria, al menos no todavía. Pero vio que había un potencial para un código más desordenado en el futuro que habría llevado a una refactorización más larga y tediosa, por lo que tomó la iniciativa y limpió las cosas ahora.

También diría que la ventaja que obtuviste aquí fue un código que es más fácil de entender, al menos desde mi punto de vista, como alguien que no conoce tu código base.

En general:

¿La refactorización facilita que otros desarrolladores entiendan su código?

¿La refactorización facilita la mejora del código?

¿La refactorización facilita el mantenimiento del código?

¿La refactorización facilita la depuración?

Si la respuesta a cualquiera de estas preguntas era "sí", entonces valía la pena y era más que simplemente "¿mover el código?

Si la respuesta a todas estas preguntas era "no", tal vez no fuera necesario volver a redactarlo.

El tamaño final de la base de código podría ser más grande en términos de LoC (aunque algunas refactorizaciones pueden reducir la base de código al simplificar el código redundante), pero eso no debería ser un factor si hay otras ganancias.

    
respondido por el FrustratedWithFormsDesigner 08.12.2017 - 17:33
9

La refactorización infla si está desmontando un monolito.

Sin embargo, ya has encontrado el beneficio.

"En mi caso, estoy agregando nuevas funcionalidades para una nueva línea de productos".

No puedes agregar funcionalidad a un monolito con mucha facilidad sin romper cosas.

Usted dijo que el mismo código es obtener los datos y hacer el marcado. Genial, hasta que desee cambiar las columnas que está seleccionando y manipulando para mostrar en ciertas condiciones. De repente, su código de marca deja de funcionar en un caso determinado y usted tiene que refactorizar.

    
respondido por el Deacon 08.12.2017 - 16:58
2

Considero la refactorización si sé que tendré que trabajar meses o incluso años con ese proyecto. Si tengo que hacer un cambio aquí y allá, entonces me resisto a la necesidad de mover el código.

La forma preferida de hacer refactorización es cuando tengo un código base con algún tipo de pruebas automatizadas. Aun así, debo tener mucho cuidado con lo que cambio para asegurarme de que las cosas estén funcionando como antes. Perderá la confianza muy pronto si entrega errores en otras áreas que no sea la que se supone que debe trabajar.

Valoro la refactorización por las siguientes razones:

  • Entiendo mejor el código
  • Quito el código duplicado, así que si tengo un error en un lugar, no tengo que cazar en todas partes donde estaba el código ha sido copiada pegada
  • Yo creo clases que tienen su rol bien definido. Por ejemplo, puedo reutilizar el mismo repositorio para hidratar una página HTML, un Feed XML o un trabajo de fondo. Esto no hubiera sido posible si el código de acceso a la base de datos solo se encuentra en la clase HTML
  • renombro variables, métodos, clases, módulos, carpetas si no coinciden con la realidad actual; I comment el código a través de nombres de variables, nombres de métodos
  • Resuelvo errores complejos con una combinación entre pruebas de unidad y refactorización
  • Tengo la flexibilidad de reemplazar módulos completos, paquetes Si el ORM actual está desactualizado, con errores o sin mantenimiento, entonces es más fácil reemplazarlo si no está esparcido por todo el proyecto.
  • Descubro nuevas capacidades o mejoras que resultan en propuestas para el cliente.
  • Creé componentes reutilizables. Este fue uno de los mayores beneficios porque el trabajo realizado en ese proyecto podría haber sido reutilizado para otro cliente / proyecto.
  • A menudo comienzo con la solución más tonta, codificada y descabellada, y luego la refactorizo una vez que aprenda más. Este último momento puede ser hoy o tal vez después de varios días. No quiero pasar mucho tiempo para architect la solución. Esto se producirá mientras se escribe, reescribiendo el código una y otra vez.

En un mundo perfecto, las refactorizaciones deben verificarse mediante pruebas unitarias, pruebas de integración, etc. Si no hay ninguno, intente agregarlos. También algunos IDE pueden ayudar mucho. Usualmente uso un plugin que cuesta dinero. Quiero pasar poco tiempo con refactorizaciones y ser muy eficiente al respecto.

También introduje errores. Puedo ver por qué algunos QA están preguntando are you guys doing refactoring? because everything stopped working! Este es el riesgo que el equipo tiene que asumir y siempre tenemos que ser transparentes al respecto.

Durante los años encontré que la refactorización continua mejoró mi productividad. Fue mucho más fácil agregar nuevas características. Además, las grandes reconstrucciones no requerían una reescritura completa, como sucedía a menudo cuando el código base no estaba adaptado a la evolución del producto. También es divertido.

    
respondido por el Adrian Iftode 08.12.2017 - 23:17
1

Creo que la pregunta que debes hacerte a ti mismo no es tanto "¿Hay algún beneficio?" pero "¿Quién pagará por este trabajo?"

Todos podemos discutir sobre los beneficios percibidos hasta el final de los días, pero a menos que tenga un cliente que crea en esos beneficios y los valore lo suficiente como para pagar los cambios, no debería hacerlo.

Es muy fácil cuando estás en un equipo de desarrollo en algún lugar para ver el código y quieres refactorizarlo para hacerlo "mejor". Pero poner un valor en 'mejor código' cuando el producto ya funciona es realmente difícil.

Cosas como 'desarrollo más rápido de nuevas características' no lo reducen porque son solo costos reducidos. Necesitas generar ventas.

    
respondido por el Ewan 08.12.2017 - 16:58
1

En mi opinión, la refactorización es una buena inversión.

De lo contrario, pronto obtendrá deudas técnicas (problemas sin resolver, código incorrecto que solo funciona bajo ciertas condiciones, etc.). Las deudas técnicas pronto serán cada vez más grandes, hasta que el software ya no sea mantenible.

Pero para que funcione la refactorización, también hay que invertir en pruebas. Debe crear pruebas automatizadas, idealmente debería tener pruebas unitarias y pruebas de integración. Esto le impide romper el código existente.

Si tiene que convencer a su jefe o sus colegas, debe leer algunos libros sobre métodos ágiles (por ejemplo, SCRUM) y el desarrollo basado en pruebas.

    
respondido por el bernie 12.12.2017 - 19:52

Lea otras preguntas en las etiquetas