Sí, has leído bien, «El arte del refactoring» ya que para mí la refactorización es todo un arte, es el proceso mediante el que convertimos a un código no muy escalable y flexible en otro que sí lo es y nos permite aumentar nuestro ritmo de trabajo.
En el post sobre La regla del Boy Scout vimos la importancia de aplicar pequeños refactors de legibilidad sobre las clases por las que pasemos y cómo esto ayuda poco a poco a tener un mejor código.
Hoy os voy a hablar de refactors de código a nivel estructurales, cuando y porque debemos hacerlos. Los cambios estructurales seguramente afecten a varios archivos y nos lleven más tiempo, por lo que no hay que volverse locos refactorizando todo y solo debemos hacerlo cuando realmente aporte algo al proyecto.
No me vale la excusa de «este código es muy feo vamos a refactorizarlo», o «este código podría ser mejor», o «este código no cumple X principio». Un refactor de estructura siempre debe estar justificado.
¿Cuándo está justificado refactorizar nuestro código?
Desde mi punto de vista, solo deberíamos de refactorizar cuando tenemos previsión de que esa parte del código nos va a lastrar en el desarrollo. Si tenemos un sistema maduro al que no le vamos a añadir nueva funcionalidad, invertir tiempo mejorándolo sería como perder el tiempo.
Si hacemos esto tendremos un código más «bonito», nuestro ego estará satisfecho pero no le habremos aportado ningún valor al proyecto ya que nadie iba a tocar ese sistema y no repercute en nada.
Yo he sido un «programador de refactor fácil» cuando veía un mal código tenía que refactorizarlo y luego darme una palmadita en la espalda por mi «buen trabajo». Hasta que un día me di cuenta que esto no nos estaba ayudando en nada, hay que ser pragmáticos e invertir nuestro tiempo en cosas que realmente tengan un impacto.
Recordar que estamos hablando de refactors de estructura que nos obligan a cambiar como se comunican las clases, no estoy hablando de refactors de legibilidad que solo afectan a esa clase en concreto o a algunos consumidores en muy baja medida, estos refactors si que los aplico a menudo porque aportan claridad al código (La regla del Boy Scout).
¿Cómo identificamos cuando el código nos va a lastrar?
Esto a la vez es sencillo y complicado porque son conceptos simples pero identificarlos puede ser complicado, voy a poner algunos ejemplos:
Imaginemos que tenemos un sistema de combate que aún lo estamos desarrollando y nos viene una feature nueva para el combate.
Si para añadir esta nueva feature tenemos que modificar muchos archivos, nos cuesta plantear un diagrama, hay muchos colaboradores, tal vez haya llegado el momento de pararse y refactorizar este código, como mínimo se merece un pensamiento.
Recordemos que si estamos aplicando un refactor es para obtener un beneficio, y este tiene que ser mayor al coste. Si invertimos una semana en el refactor y dos días en añadir la feature, pero de no hacer el refactor el coste sería de tres días y nunca más volveríamos sobre este código, no es una buena inversión.
Obviamente esto es difícil de predecir y medir, es algo que solo se obtiene con la experiencia y aún así nunca serás un maestro porque cada caso es distinto.
Otro ejemplo de cuando aplicar refactoring
Nos hemos pegado la paliza para añadir los 10 primeros items de nuestro juego, hoy sabemos que no vamos a añadir más items, pero también sabemos que es muy probable que en un futuro se quiera ampliar con más items.
En este caso tendría sentido refactorizar el código para que resulte más simple de extender, pero a la vez invertir este tiempo ahora puede no ser la mejor estrategia. Tal vez sea mejor esperar a que llegue el momento de ampliarlo y entonces aplicar el refactor antes de hacer nada.
Sea cual sea la decisión en este caso, el responsable del proyecto debería de estar al tanto y saber que si no refactorizamos ahora tendremos que hacerlo cuando queramos ampliar, y tal vez en ese momento tengamos prisa. Es una balanza bastante difícil de equilibrar.
¿Cómo evitamos llegar a este punto de tener que elegir si refactorizar o no?
Esta sí que es muy fácil, hagamos el mejor código posible, si no hacemos un mal código no tendremos código que refactorizar 😝.
Solo bromeaba, hacer el mejor código posible siempre es algo bastante difícil si no imposible, ya que no olvidemos las circunstancias en las que escribimos ese código. No es lo mismo estar tranquilamente en tu casa trabajando en tu proyecto con todo el tiempo del mundo, que estar trabajando en un proyecto con el tiempo limitado.
Tampoco es lo mismo estar en una época «normal» que en una época de rush en la que el tiempo lo es todo porque no llegamos a fecha, o a salido un imprevisto, o nos ha caído un marrón de mil narices. Seguramente cuando termine este rush será un buen momento para refactorizar y arreglar ese caos que hemos creado.
Cosas que sí podemos hacer para evitar el refactoring
Aplicar cualquier arquitectura que siga los principios SOLID y nos fuerce a ello, como la Clean Architecture. Pero no vale con aplicarla cuando nos venga de gusto, si tenemos una arquitectura es para seguirla, que no sería la primera vez que he visto arquitecturas a medias 😒.
Una buena arquitectura será nuestro mejor aliado en tiempos difíciles ya que nos obligará a hacer un código mínimamente <<bonito>> dentro de los estándares de la arquitectura.
Por ejemplo, la Clean Architecture cuenta con la regla de la dependencia que nos fuerza a que nuestras clases sean independientes y solo las capas externas dependan de las internas, con lo que aislamos nuestro core.
Otra opción es seguir siempre SOLID y Clean Code. Como ya vimos en la introducción a los principios SOLID, seguir estos principios nos aportará muchísima mantenibilidad en nuestro proyecto, y es totalmente compatible con una época de rush.
Conclusión
Aunque refactorizar es importante, hacer un buen código lo es más, por eso es de vital importancia que definamos unas normas mínimas en nuestro proyecto, y si puede ser basadas en principios contrastados (como SOLID) mucho mejor.
También es importante contar con una buena arquitectura muy bien definida y clara, que no nos haga dudar cuándo vayamos a implementar algo aprisa y corriendo y que no sea fácil saltárnosla.
Si aún así llegamos al punto de necesitar un refactor, el siguiente paso será preguntarnos si vale la pena y si es hoy cuando debemos invertir ese tiempo. Ya que a veces refactorizamos en previsión a algo y esto no llega nunca.
Si te gustaría aprender más sobre SOLID y Clean Code en The Power Ups tenemos un curso orientado totalmente a videojuegos con el que aprenderás los principios SOLID y como crear un código más legible y mantenible. Obtén toda la información en este enlace.
Fuentes
- Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin)
- Refactoring: Improving the Design of Existing Code (Martin Fowler)
Otras entradas
- ¿Cómo empezar en el desarrollo de videojuegos?
- Patrones de diseño – Template Method
- Patrones de diseño – Service Locator
- Cómo aumentar el rendimiento de tu equipo en Unity
- Patrones de diseño – Composite
- Devlog #00 – Empezamos proyecto nuevo