DanLevy.net

Cuidado con las Personas de un Solo Propósito

Tan puro que duele

El Principio de Responsabilidad Única es una de esas ideas que suena tan sensata que puede colarse por debajo de tu juicio.

Haz una cosa. Hazla bien. Mantén los módulos enfocados. Dale al código una razón para cambiar. Buen consejo.

Luego alguien convierte el consejo en una cinta métrica y empieza a declarar que cualquier función de más de cinco líneas es un olor a código.

El problema no es SRP. El problema es tratar “pequeño” como un sustituto de “cohesivo”.

En ese punto te has encontrado con las Personas de un Solo Propósito: desarrolladores que no están exactamente equivocados sobre la modularidad, pero han confundido los límites útiles con la fragmentación máxima.

Violencia en la Arquitectura de Software
Componentes, componentes en todas partes

I. La Idea Útil Debajo

Añadir un solo checkbox a un formulario idealmente solo debería afectar a un archivo. No 8 archivos en 5 directorios… Te estoy mirando a ti, React/Redux.

Cuando SRP se aplica con juicio, ayuda. Las unidades de código enfocadas en una única tarea conceptual son más fáciles de entender. Las pruebas pueden apuntar al comportamiento en un límite sensato. Los módulos claros facilitan cambiar una parte del sistema sin arrastrar al resto de la aplicación a la sala.

Incluso los ejemplos clásicos de Unix son más pragmáticos de lo que sugiere el eslogan. ls lista archivos, sí, pero también coordina llamadas como opendir, readdir, closedir y stat. La unidad útil no es la operación más pequeña posible. La unidad útil es la cosa coherente más pequeña que resuelve la tarea.

La filosofía original de Unix trataba sobre composición y simplicidad, no sobre reducir todo a una sola función o archivo.

Esa distinción importa. “Una responsabilidad” no es lo mismo que “una línea de comportamiento”.

II. Sobre-Abstracción: Cuando la Simplicidad se Convierte en Caos

Nuestro arquitecto insiste en que cada función de más de 5 líneas es un ‘olor a código’. Nuestra base de código ahora huele ligeramente a desesperación clueless.

El modo de fallo es fácil de detectar después de que ya ha empeorado tu semana.

La base de código tiene más archivos, pero menos forma. Cada ayudante tiene un ayudante. Cada concepto se ha dividido en carpetas nombradas según roles técnicos en lugar de significado del producto. Añadir un checkbox requiere tocar un componente, un hook, un selector, una acción, un reductor, una constante, un fixture de prueba y una exportación de barril que existe principalmente para evitar que las rutas de importación parezcan culpables.

Sin escape para este patrón de trabajo infinito
Componentes, componentes en todas partes

¿Qué compró toda esa pureza?

He mirado al abismo de bases de código donde una función directa de 100 líneas fue viviseccionada en más de 15 archivos, cada uno un pequeño ángel “puro” que contenía quizás una o dos funciones. El radio de explosión cognitiva de intentar mantener ese desorden en tu cabeza negaba por completo cualquier ganancia teórica de la separación. No era más simple; simplemente estaba disperso.

III. El Peaje de la Perfección: Impacto en los Desarrolladores

Pasamos más tiempo debatiendo sobre la estructura de archivos y convenciones de nomenclatura que realmente enviando funciones. ¿Esto es Agile?

Tan desordenado que bordea el arte
Tan desordenado que bordea el arte

Esta fragmentación patológica no es solo un problema estético. Cambia cómo los desarrolladores gastan su atención:

La Fuga de Productividad: Olvida la deuda técnica; esto es deuda organizacional acumulada a través de anidamiento de directorios obsesivo-compulsivo. Cada pequeño ajuste se convierte en una excavación arqueológica a través de capas de abstracción. El tiempo se desvanece en el agujero negro de cd .. y grep.

El Impuesto de Pruebas: En lugar de proporcionar confianza, la suite de pruebas se convierte en una fuente de fricción. Las horas se derriten arreglando pruebas rotas por refactorizaciones triviales, pruebas que estaban demasiado acopladas a los detalles microscópicos que se suponía que debían verificar.

La Carga Cognitiva: Hay un límite estricto en cuántas piezas desconectadas de información puede malabarear el cerebro humano. Obligar a los desarrolladores a reconstruir el flujo del programa desde una docena de archivos dispersos obstaculiza activamente la comprensión y hace que los cambios seguros sean más difíciles.

IV. Abrazando el Pragmatismo: Una Alternativa Práctica

Sugerí que pusiéramos dos funciones relacionadas en el mismo archivo. La sala reaccionó como si hubiera propuesto eliminar la puesta en escena. — Un lector en recuperación purista

La salida de emergencia no es abandonar SRP. La respuesta es aplicarlo en el nivel correcto de significado.

Así es como se ve eso en la práctica:

El objetivo no es la perfección teórica digna de una tesis doctoral; es crear código que tus colegas (y tu yo futuro) puedan navegar, entender y modificar sin querer incendiar el edificio.

A veces esto significa que un archivo tiene 200 líneas en lugar de 50. A veces una función maneja la obtención de datos y los transforma ligeramente. A veces una clase tiene dos responsabilidades que están tan estrechamente acopladas que deberían vivir juntas. Si hace que el sistema sea más fácil de usar en general, probablemente sea la decisión correcta.

Mantente enfocado implacablemente en las preguntas prácticas:

V. Conclusión: Fomentando un Código Cohesivo y Mantenible

El Principio de Responsabilidad Única es una herramienta útil. No es un mandato para pulverizar tu base de código en polvo atómico. Como cualquier herramienta, su valor depende del juicio de la persona que la usa.

Así que cuando te encuentres con las Personas de un Solo Propósito, listas para librar una guerra contra cualquier función que se atreva a exceder las tres líneas, respira. Recuerda el checkbox de 12 archivos.

Nuestro trabajo no es construir funciones de copo de nieve teóricamente inmaculadas. Nuestro trabajo es construir software que funcione, resuelva problemas y no castigue a la siguiente persona que tenga que tocarlo.

Mantente pragmático. Enfócate en los resultados. No dejes que la búsqueda de la pureza perfecta se convierta en el enemigo del código mantenible. Tu cordura, y la velocidad de tu equipo, dependen de ello.

¹ La ironía es que lograr verdadero propósito único en los niveles más bajos requiere una inmensa complejidad oculta justo debajo de la superficie.

² Estamos hablando de pureza conceptual aquí: la idea de que una función debería hacer solo “una cosa” lógicamente. No confundas esto con el concepto de programación funcional de “función pura” sin efectos secundarios, que es una idea diferente, aunque a veces relacionada.