Sobreingeniería en software: cómo complicar lo sencillo sin necesidad
21 de octubre de 2024
Todos hemos estado allí. Te sientas frente a tu flamante Macbook pro con procesador M3 y 32GB de RAM (sí, esa bestialidad que nos da SNGULAR y que tanto nos merecemos), listo para diseñar la próxima gran cosa en software. Tienes un café en la mano, un millón de ideas en la cabeza y un arsenal de patrones de diseño que acabas de aprender. ¿Qué podría salir mal? Pues... ¡la sobreingeniería!
¿Qué es la sobreingeniería?
Imagina que quieres construir una casita en el árbol para tus sobrinos. Lo más lógico sería armar algo sencillo: unas tablas, unos clavos, ¡y listo! Pero de repente te emocionas y decides instalar un sistema de poleas, puertas automáticas, sistemas de alarma, paneles solares y, por qué no, un ascensor. ¿Resultado? Tus sobrinos ahora necesitan un manual de 50 páginas para entrar a su casita.
En software, la sobreingeniería es exactamente eso: añadir capas y capas de complejidad que no son necesarias. Es como si en lugar de usar una simple lista para almacenar unos números, decides implementar tu propia estructura de datos con herencia múltiple, patrones de fábrica, y un sistema de eventos que ni tú mismo entiendes del todo. ¿Por qué? Porque puedes.
El efecto de la sobreingeniería cuando empezamos a aprender arquitectura del software
A medida que avanzamos en el mundo del desarrollo de software, es fácil caer en la trampa de la sobreingeniería. ¿Por qué? Pues porque es emocionante, suena sofisticado, y quieres demostrar que puedes manejar patrones de diseño como un verdadero profesional. Estás aprendiendo sobre arquitecturas limpias, microservicios, inyección de dependencias y toda esa “movida molona que te pone tontorrón”, y te preguntas: ¿Por qué no usarlos todos en mi proyecto?
La realidad es que, aunque los patrones de diseño y las arquitecturas complejas son herramientas poderosas, no siempre son necesarias. Es completamente normal querer probar todo lo que aprendes. Es parte del proceso de crecimiento. El problema viene cuando te das cuenta de que, después de todo, quizás no necesitabas esa fábrica abstracta para crear un único objeto de configuración en tu aplicación.
El problemón de las clases base que no son tan base
Y hablando de fábricas abstractas y demás “pamplinadas”, hablemos de las clases base. Sí, esas que deberían ser la piedra angular de tu arquitectura pero terminan convirtiéndose en una trampa mortal para la simplicidad.
El uso de clases base puede parecer una idea genial. Piensas: «voy a agrupar todo este código repetido en una clase padre, y listo, todas las hijas heredan esta maravilla». Pero, ¿qué pasa cuando esa clase base termina siendo un monstruo de Frankenstein con más métodos de los que cualquiera puede recordar? De repente, tu clase base se convierte en un laberinto que oculta el comportamiento normal de las clases hijas, como, por ejemplo, los ciclos de vida en Android. ¡Nada como intentar depurar un bug y descubrir que está enterrado en alguna sobrecargada función de tu clase base, oculta por la niebla del override!
Además, suele ocurrir, que no todas las funcionalidades que agrupas en tu clase base son necesarias para todas las clases que heredan de ella. Imagina que decides que todas las instancias de tu clase base Ave de tu programa deben saber nadar porque, bueno, ¿por qué no? Ahora cada vez que alguien cree una instancia de un objeto que herede de tu clase base Aver (por ejemplo el objeto que representa al enigmático "polloCamperoTerrestre"), tiene que lidiar con métodos de natación que no necesita, todo porque alguien (tú en un momento de inspiración excesiva) decidió que sería útil... por si acaso.
¿Arquitectura prefabricada? ¡No, gracias!
Sigamos con los excesos y hablemos de esas arquitecturas ya montadas que vienen con todo el combo: librerías para peticiones, manejadores de eventos, caché y quién sabe cuántas cosas más. Sí, suena práctico y tentador. Todo está listo para usar, empaquetado con un moño bonito. Pero… spoiler alert: lo que ganas en conveniencia, lo pierdes en flexibilidad.
Imagina que te mudas a una casa totalmente amueblada. Puede parecer una ganga, pero luego te das cuenta de que no te gusta el sofá, odias las cortinas y esa lámpara en forma de piña te da escalofríos. Pero, como todo venía en el paquete, ahora estás atrapado con cosas que no necesitas y que no puedes cambiar sin hacer un gran esfuerzo.
En software, usar una arquitectura prefabricada puede llevar a un escenario similar. Terminas utilizando librerías que quizás no son las mejores para tu proyecto, simplemente porque vienen con la arquitectura. Y lo peor de todo, te obliga a diseñar tu software alrededor de esas decisiones pre-tomadas, en lugar de construir algo que realmente se adapte a tus necesidades.
Lo ideal es que las arquitecturas, librerías y herramientas que elijas sean un traje hecho a medida para tu proyecto, no un disfraz genérico de Halloween. No tengas miedo de crear tu propio camino y elegir lo que realmente necesitas, en lugar de acoplarte a lo que ya está hecho.
Conclusión
La sobreingeniería es como esa voz en tu cabeza que te dice que necesitas más complejidad para ser mejor desarrollador. Pero, en realidad, ser un buen desarrollador implica saber cuándo dejar de añadir capas y cuándo simplificar las cosas. Menos capas, más claridad. Esa es la verdadera habilidad. Y hablando de claridad, ¡ojo con esas clases base que terminan ocultando más de lo que revelan! Recuerda, una clase base debe ser eso mismo, una base, no un cajón de sastre donde todo termina amontonado.
Por último, no te dejes seducir por arquitecturas prefabricadas que te atan a decisiones que no son ideales para tu proyecto. Construye tu arquitectura con las herramientas y librerías que realmente necesitas, y no más. Al final del día, tu objetivo es resolver un problema de la manera más eficiente y clara posible, no crear un enigma que ni tú puedas resolver.
Así que la próxima vez que te encuentres tentado a añadir una nueva capa de abstracción "por si acaso", “porque mola y he visto que Uncle Bob lo explica en su último gran libro”, recuerda: a veces, la mejor solución es la más sencilla. ¡No compliques lo que no necesitas complicar!
¡Nos vemos en el próximo artículo, donde seguiremos desentrañando los misterios del desarrollo! Hasta entonces….
¡Que la fuerza del Pollo Campero te acompañe 🐔!
Nuestras últimas novedades
¿Te interesa saber cómo nos adaptamos constantemente a la nueva frontera digital?
21 de noviembre de 2024
Contract Testing as a Service: apoya a tus clientes
5 de noviembre de 2024
Innovación de impacto: Cómo evaluar y diseñar productos digitales sostenibles
14 de octubre de 2024
PactFlow & Contract Testing: Un caso de uso empresarial
7 de octubre de 2024
Configuración de Tareas Personalizadas de Lint en Gradle con Kotlin DSL