DÍA 10 / 2017

Refactorizar: Welcome to the CSS jungle

Una de las tareas más ingratas a la que todo frontend ha de enfrentarse alguna vez es limpiar, estructurar y arreglar bugs generados por un código desastroso heredado en el 99% de los casos. Durante el artículo me alejaré de cuestiones moralizantes sobre buen código, centrándome más en trucos, estrategias y experiencias que en su día, me hicieron más fácil el enfrentarme a este tipo de actividad.


¿Qué es refactorizar un código CSS?

Generar u ordenar de forma más óptima la estructura de los estilos, así como aprovechar para hacer más y mejor escalable el CSS. Todo ello, hará posible la rápida detección y arreglo de bugs futuros y presentes. Como podrás comprobar en esta definición parece que todo son ventajas, pero ¿cuáles son esas consecuencias de la refactorización? Ánimo, ármate un poco de paciencia, porque en los siguientes apartados iré diseccionando cada uno de ellas.

¿Cuando refactorizar los estilos CSS de tu proyecto?

A grandes rasgos existen dos situaciones que te llevarán a ello: La primera sería refactorización por iniciativa ajena vía encargo de tu superior, jefe o requerimiento del proyecto, la segunda refactorización por iniciativa propia. La única diferencia entre una u otra es el grado el compromiso que desarrollamos para realizarla, en la primera tienes deadlines en la segunda las deadlines se suelen convertir en "trampas al solitario".

Contexto del código que encontrarás en este tipo de proyectos

  • Código heredado: En el siglo XXI el trabajo en equipo es la piedra angular de todo proyecto serio, por tanto la soledad del desarrollador frontend es más bien, la soledad del equipo de desarrolladores frontend.
  • Falta de estructura: Proyectos en los que no se usan preprocesadores y mucho menos una arquitectura postCSS. Estos suelen carecer de una base jerarquizada y/o mal implementada.
  • Sobre-especificidad y redundancia en el código css: Sabrás identificarlos rápidamente por su important!-ancia ( perdón por el chiste malo ) o innecesaria utilización de la especificidad.
  • Falta de comentarios o Comentarios en otros idiomas: Quizás mucho más que ausencia, la presencia de comentarios en otros idiomas ajenos al inglés. Te distraerá o provocará un pérdida de tiempo precioso al intentar entender el comentario, ante un código ilegible referenciado. Cuando tengas la suerte de trabajar en proyectos internacionales, te darás cuenta de lo mucho que amarás el idioma de Shakespeare.
  • Nomenclatura incierta: El nombrado óptimo de clases es una tarea titánica, donde todo el mundo tiene la solución mágica. En mi experiencia, lo realmente importante es la consistencia, es decir, la existencia de unas reglas de nomenclatura propias del proyecto y no propias del gusto del programador.
  • Tabs or Espacios: La falta de consenso en el modo de identación de archivos provocará esos conflictos irritantes durante los merge. Decídete, eres un extraño ser que prefiere los espacios o una persona cabal, sensata, centrada, amante de las tabulaciones.

Antes de ponerse a picar, toca analizar

Lo primero es analizar la situación, identificar los problemas, preparar un plan de acción y estimar el tiempo que tardarás en solucionarlo, todo ello, antes de ponerse a "picar código" Estos pasos te ayudarán a poder argumentar frente a tu jefe o frente al espejo tu trabajo.

  1. Analizar: En este punto has de tener una idea general del proyecto, debería saber explicar en pocas palabras a un compañero, jefe o colega, cuál es la problemática general que has percibido y la magnitud real de la misma. Por ejemplo:

"El proyecto X empezó con el framework bootstrap, no tiene arquitectura custom como tal, sino un archivo style.css donde se aplican las modificaciones" "Además nunca existió un procedimiento al abordar los estilos, así que todo hijo de vecino tocó y modificó como le dió la gana" "el proyecto ha crecido con estas deficiencias y no tenemos ni tiempo ni dinero para rehacer de cero"
- Posible Análisis

  1. Identificar: Nunca trates de abordar todo, divídelo en pequeñas metas fácilmente reconocibles. En la práctica es siempre mejor dividir una meta grande en otras más pequeñas. Por ejemplo:

"Establecer una arquitectura tipo ITCSS bajo una estructura SASS" "Crear un guía de estilos que clarifique y complemente la tarea de refactorización de cara a futuro"
- Posibles puntos de Identificación o metas

  1. Preparar: La parte más relacionada con el código en sí. Aquí apuntas las tareas más concretas que has de realizar para implementar los puntos anteriormente identificados. Pueden ser técnicas o más específicas al código en sí. Por ejemplo:

"Instalar Gulp así como todos los plugins necesarios" "Reunión con el equipo para consensuar la mejor manera de abordar la guía de estilos" "Respirar y relajarme cada vez que vea un important! para posteriormente poder sustituirlo por una opción menos sangrante a los ojos"
- Posibles tareas concretas que preparar

  1. Estimar: El punto más importante y a su vez más difícil de abordar. Requiere compromiso y capacidad de conocerse a uno mismo y sus habilidades. Un consejo a la hora de estimar tiempos de ejecución, es añadir siempre un poco más para imprevistos, porque siempre siempre siempre surgen imprevistos.

Llegó la hora de picar código

Retomamos el plan de acción y nos metemos en faena. Intuyo que has estado leyendo con entusiasmo, deseando llegar hasta aquí; soñando con una herramienta mágica, con una estrategia infalible, con el consejo universal perfecto… Pues no, lo siento, pero esto es la vida real, donde no existen herramientas mágicas, ni rockStar-developers.

Disminuir el impacto del código heredado

Existen proyectos en los que las labores de frontend se solapan, de manera que distintos perfiles de programadores dentro del equipo pueden tocar o tocaron los estilos. La solución más correcta sería crear y divulgar una guía de estilos  que defina bien, tipografías, color, patrones… Como pasa con toda documentación de proyecto, la realidad es que la documentación nunca nunca se lee, por ello abogo más por mantener una comunicación fluida dentro del equipo que refresque estas pautas.

No existe refactorización sin estructura

La base coherente del CSS se centra en la herencia y cascada. En los personal, me gusta mucho la arquitectura ITCSS, por ello recomiendo que reviséis el proyecto haiticss.

Falla la estructura y toca parchear

Si amigos, esto pasa y mucho, normalmente por cuestiones de tiempo (una máxima en este mundillo es que da igual la magnitud, presupuesto o empresa detrás, porque nunca hay tiempo ) A continuación os expongo algunas de las problemáticas más frecuentes que encontrarás, así como las posibles soluciones:

  • Excesiva especificidad: El mal entendimiento de la identación durante el uso de preprocesadores da como resultado en muchas ocasiones una sobre-especificidad en la elección de selectores. Sobre todo entre aquellos que olvidan o ignoran las bases del CSS. Posibles soluciones:
    • Usa atributos attribute modules.
    • Vencer a un important! con sólo duplicar la clase.
    • El valor initial es el gran olvidado del CSS.
// Attribute Modules
[class~=shameClass] { /* tus estilos */ };
// Duplicar Clase
.shameClass { color: pink !important } ==> .shameClass.shameClass { color: green; }
// Usa el valor initial
.shameClass { color: initial; }
  • Escasa especificidad: El caso contrario al mencionado anteriormente, muy fácilmente solucionable.
  • MediaQueries infinitas: La falta de criterio, de estructura clara y las prisas son el caldo de cultivo perfecto para generar un frankenstein de breakpoints. Mi propuesta es centralizar las media queries en un solo archivo, establecer un mínimo de 4 breakpoint ( denomina esos puntos de corte por jerarquía de tamaño y mantén esa proporcionalidad ) sólo en caso extremadamente necesario testea, crea y define mediaqueries intermedias a esas cuatro.
/* DEFINE UNA JERARQUÍA SIGUIENDO EL MODELO MOBILE FIRST */

// Modelos clásico de nombrado, válido, pero confuso.

@media @media-mobile {}
@media @media-tablet {}
@media @media-desktop {}
@media @media-desktop-plus{}
// ¿Qué pasará el día que en que el Samsung Galaxy Note 2999 no entre dentro del corte tipo @media-mobile? ¿Crearemos un media llamado @media-galaxyNote? :/

// Modelo tipo bootstrap que recomiendo

@media @media-xs {}
@media @media-sm {}
@media @media-md {}
@media @media-lg {}

// Sí, sé que no soy mainstream porque he dicho una cosa buena de bootstrap
  • Querer ser mobile-first pero terminar siendo desktop-first: Los principios básicos al entrar de lleno en un proyecto de maquetación deberían ser ¿Qué navegadores soportaremos?, ¿Queremos ser mobile first realmente? Si el primer día al entrar en el proyecto no tienes claro los navegadores y versiones soportadas, te tocará refactorizar. Cuando aplicas la sabia decisión de usar el modelo de arquitectura css mobile-first , pero el cliente se empeña en ver sólo el resultado desktop-first, tienes todas las papeletas para en un futuro cercano tener que refactorizar. Solución: no es cuestión de código, ahí entra en juego tu capacidad de negociación y fundamentación de tus decisiones.
  • Todo se convierte en un agujero negro: Has empezado la refactorización pero los bugs reaparecen o se crean otros nuevos, empiezas a pensar 'por qué me metería yo en esto', la presión de tus superiores o de ti mismo hace mella en tu rendimiento y estás a punto de tirar la toalla.

Cómo salir del agujero negro de la refactorización

  1. Respira hondo, ya sabes que no eres el primero al que le pasa.
  2. Divide tu código en pequeñas tareas fácilmente testeables.
  3. Trabaja siguiendo estos pasos:
    1. El inspector de código de tu navegador es tu amigo, usalo.
    2. Testea la funcionalidad, elemento o patrón que estas refactorizando.
    3. Sobreescribe el código.
    4. Testea con una visión global del proyecto (evitando daños colaterales).
    5. Corrige.
    6. Vuelve a testear globalmente.
    7. Comitea tu cambio.

Conclusión final

Todo lo dicho en este artículo forma parte de mis experiencia personal y de tantos otros amigos, conocidos y colegas del sector. No pretendo sentar cátedra, ni instaurar el santo decálogo del master developer, pero a ti, que estás empezando, permíteme un pequeño consejo:

"Apártate de las frases grandilocuentes, los gurús del desarrollo, de esos profesionales a los que todo les sale bien. La excelencia, experiencia y pasión son las claves para ser un buen profesional."