Capítulo 1. Código limpio

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Cuando Martin Fowler definió la refactorización en su libro Refactoring: Improving the Design of Existing Code, mostró los puntos fuertes y las ventajas, así como las razones que hay detrás de la refactorización. Afortunadamente, después de más de dos décadas, la mayoría de los desarrolladores conocen el significado de la refactorización y los olores de código. Los desarrolladores se enfrentan a diario a la deuda tecnológica y la refactorización se ha convertido en una parte esencial del desarrollo de software. En su libro fundacional, Fowler utilizó las refactorizaciones para abordar los olores de código. Este libro recorre algunos de ellos en forma de recetas semánticas para mejorar tus soluciones.

1.1 ¿Qué es el olor a código?

Un olor a código es síntoma de un problema. La gente tiende a pensar que la presencia de olores de código es una prueba de que toda la entidad necesita ser desmontada y reconstruida. Éste no es el espíritu de la definición original. Los olores de código son simplemente indicadores de oportunidades de mejora. Un olor a código no te dice necesariamente qué va mal; te está diciendo que prestes especial atención.

Las recetas de este libro ofrecen algunas soluciones a esos síntomas. Como en cualquier libro de cocina, las recetas son opcionales y los olores del código son directrices y heurísticas, no reglas rígidas. Antes de aplicar cualquier receta a ciegas, debes comprender los problemas y evaluar el coste y los beneficios de tu propio diseño y código. Un buen diseño implica equilibrar las directrices con consideraciones prácticas y contextuales.

1.2 ¿Qué es la refactorización?

Volviendo al libro de Martin Fowler, da dos definiciones complementarias:

Refactorización (sustantivo): cambio realizado en la estructura interna del software para hacerlo más fácil de entender y más barato de modificar sin cambiar su comportamiento observable.

Refactorizar (verbo): reestructurar el software aplicando una serie de refactorizaciones sin cambiar su comportamiento observable.

Las refactorizaciones fueron inventadas por William Opdyke en su tesis doctoral de 1992, "Refactoring Object-Oriented Frameworks", y se popularizaron después del libro de Fowler. Han evolucionado desde la definición de Fowler. La mayoría de los IDE modernos admiten refactorizaciones automáticas. Éstas son seguras y realizan cambios estructurales sin modificar el comportamiento del sistema. Este libro tiene muchas recetas con refactorizaciones automáticas y seguras, y además también incluye refactorizaciones semánticas. Los refactorizadores semánticos no son seguros, ya que pueden cambiar parte del comportamiento del sistema. Debes aplicar las recetas con refactorizaciones semánticas con cuidado, ya que pueden romper tu software. Indicaré si una receta tiene refactorización semántica en las recetas aplicables. Si tienes una buena cobertura de código de comportamiento, puedes estar seguro de que no romperás escenarios empresariales importantes. No debes aplicar recetas de refactorización al mismo tiempo que corriges un defecto o desarrollas una nueva característica.

La mayoría de las organizaciones modernas tienen suites de cobertura de pruebas sólidas en sus conductos de integración continua/entrega continua. Consulta Software Engineering at Google de Titus Winters et al. (O'Reilly 2020) para averiguar si tienes estas suites de cobertura de pruebas.

1.3 ¿Qué es una receta?

Utilizo el término receta a la ligera. Una receta es un conjunto de instrucciones para crear o modificar algo. Las recetas de este libro funcionan mejor si entiendes el espíritu de la receta para poder aplicarla con tus propios sabores. Otros libros de recetas de esta serie son más concretos, con soluciones paso a paso. Para utilizar las recetas de este libro, tendrás que traducirlas a tu lenguaje de programación y diseñar la solución. La receta es un vehículo para enseñarte a comprender un problema, identificar las consecuencias y mejorar tu código.

1.4 ¿Por qué Código Limpio?

El código limpio es fácil de leer, comprender y mantener. Está bien estructurado, es conciso y utiliza nombres significativos para variables, funciones y clases. También sigue las buenas prácticas y los patrones de diseño y favorece la legibilidad y el comportamiento por encima del rendimiento y los detalles de implementación.

El código limpio es muy importante en todos los sistemas en evolución en los que se realizan cambios a diario. Sigue siendo especialmente relevante en determinados entornos en los que no es posible implementar actualizaciones con la rapidez deseada. Esto incluye sistemas embebidos, sondas espaciales, contratos inteligentes, aplicaciones móviles y muchas otras aplicaciones.

Los libros clásicos de refactorización, los sitios web y los IDE se centran en refactorizaciones que no cambian el comportamiento del sistema. Este libro tiene algunas recetas para escenarios así, como los renombramientos seguros. Pero también encontrarás varias recetas relacionadas con refactorizaciones semánticas en las que cambias la forma de resolver algunos problemas. Tendrás que entender el código, los problemas y la receta para hacer los cambios apropiados.

1.5 Legibilidad, rendimiento o ambos

Este libro trata sobre código limpio. Algunas de sus recetas no son las más eficaces. Elijo la legibilidad sobre el rendimiento cuando está en conflicto. Por ejemplo, he dedicado un capítulo entero(Capítulo 16) a la optimización prematura para resolver problemas de rendimiento sin pruebas suficientes.

Para las soluciones de rendimiento de misión crítica, la mejor estrategia es escribir código limpio, cubrirlo con pruebas y luego mejorar los cuellos de botella utilizando las reglas de Pareto. El principio de Pareto aplicado al software establece que si solucionas el 20% de los cuellos de botella críticos, mejorarás el rendimiento de tu software en un 80%. Si mejoras el 20% del mal rendimiento, es probable que aumente la velocidad del sistema en un 80%.

Este método te disuade de hacer cambios prematuros de optimización que carezcan de escenarios basados en pruebas, porque eso dará lugar a pocas mejoras y dañará el código limpio.

1.6 Tipos de software

La mayoría de las recetas de este libro están dirigidas a sistemas backend con reglas de negocio complejas. El simulador que vas a construir a partir del Capítulo 2 es perfecto para ello. Dado que las recetas son agnósticas al dominio, también puedes utilizar la mayoría de ellas para el desarrollo del frontend, bases de datos, sistemas embebidos, blockchains y muchos otros escenarios. También hay recetas específicas con ejemplos de código para UX, frontend, contratos inteligentes y otros dominios específicos (consulta la Receta 22.7, "Ocultar errores de bajo nivel a los usuarios finales", por ejemplo).

1.7 Código generado por máquina

¿Necesitas código limpio ahora que hay muchas herramientas disponibles para el código generado por ordenador? La respuesta en 2023 es: sí. Más que nunca. Hay muchos asistentes comerciales de codificación de software. Sin embargo, (todavía) no tienen el control total; son copilotos y ayudantes, y los humanos siguen siendo los que toman las decisiones de diseño.

En el momento de escribir este libro, la mayoría de las herramientas comerciales y de inteligencia artificial escriben soluciones anémicas y algoritmos estándar. Pero son increíblemente útiles cuando no recuerdas cómo se hace una pequeña función y son prácticas para traducir entre lenguajes de programación. Las he utilizado mucho mientras escribía este libro. No domino los más de 25 lenguajes que he utilizado en las recetas. He traducido y probado varios fragmentos de código en distintos idiomas con muchas herramientas de ayuda. Te invito a que tú también utilices todas las herramientas disponibles para traducir algunas de las recetas de este libro a tu idioma favorito. Las herramientas están aquí para quedarse, y los futuros desarrolladores serán centauros tecnológicos: mitad humanos, mitad máquinas.

1.8 Consideraciones sobre los nombres a lo largo del libro

A lo largo del libro, utilizo indistintamente los siguientes términos :

  • Métodos/funciones/procedimientos

  • Atributos/variables de instancia/propiedades

  • Protocolo/comportamiento/interfaz

  • Argumentos/colaboradores/parámetros

  • Funciones anónimas/cierres/lambdas

Las diferencias entre ellas son sutiles y a veces dependen del idioma. Añado una nota cuando es necesario para aclarar el uso.

1.9 Patrones de diseño

Este libro asume que el lector tiene una comprensión básica de los conceptos de diseño orientado a objetos. Algunas de las recetas de este libro se basan en patrones de diseño populares, incluidos los descritos en el libro de patrones de diseño "Gang of Four". Otras recetas presentan patrones menos conocidos, como el objeto nulo y el objeto método. Además, este libro incluye explicaciones y orientaciones sobre cómo sustituir patrones que ahora se consideran antipatrones, como el patrón singleton en la Receta 17.2, "Sustitución de Singletons".

1.10 Paradigmas del lenguaje de programación

Según David Farley

La obsesión de nuestra industria por los lenguajes y las herramientas ha perjudicado a nuestra profesión. Esto no significa que no se puedan conseguir avances en el diseño de lenguajes, pero la mayor parte del trabajo en diseño de lenguajes parece concentrarse en cosas equivocadas, como avances sintácticos en lugar de estructurales.

Los conceptos de código limpio que se presentan en este libro pueden aplicarse a diversos paradigmas de programación. Muchas de estas ideas tienen sus raíces en la programación estructurada y la programación funcional, mientras que otras proceden del mundo orientado a objetos. Estos conceptos pueden ayudarte a escribir un código más elegante y eficiente en cualquier paradigma.

Utilizaré la mayoría de las recetas en lenguajes orientados a objetos y construiré un simulador (denominado MAPPER) utilizando objetos como metáforas de entidades del mundo real. Hago referencia a MAPPER con frecuencia a lo largo del libro. Muchas recetas te llevarán a pensar en código declarativo y de comportamiento (véase el Capítulo 6, "Código declarativo") en lugar de código de implementación.

1.11 Objetos frente a clases

La mayoría de las recetas de este libro hablan de objetos y no de clases (aunque hay un capítulo entero sobre clasificación: véase el Capítulo 19, "Jerarquías"). Por ejemplo, la Receta 3.2 se titula "Identificar la esencia de tus objetos" en lugar de "Identificar la esencia de tu clase". Este libro habla de utilizar objetos para mapear objetos del mundo real.

La forma de crear estos objetos es accidental; puedes utilizar la clasificación, la creación de prototipos, las fábricas, la clonación, etc. El Capítulo 2 trata de la importancia de mapear tus objetos y del imperativo de modelar cosas que puedas ver en el mundo real. Para crear objetos, muchos lenguajes utilizan clases, que son artefactos y no son evidentes en el mundo real. Las necesitas si utilizas un lenguaje de clasificación. Pero no son el objetivo principal de las recetas.

1.12 Modificabilidad

El código limpio no consiste sólo en garantizar que tu software funcione correctamente, sino también en facilitar su mantenimiento y evolución. De nuevo, según Modern Software Engineering de Dave Farley, debéis ser expertos en aprender y hacer que el software esté preparado para el cambio. Éste es un gran reto para la industria tecnológica, y espero que este libro te ayude a mantenerte al día de estos avances.

Get Libro de cocina de código limpio now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.