Seguro que alguna vez han visto código con todo dentro de un único archivo de vista de 800 líneas.
En el código de la vista que dibuja la pantalla hay llamadas a la API, al lado cálculos de descuentos, debajo funciones para formatear fechas y, entre medias, envíos de eventos de analítica. Para cambiar cualquier cosa hay que leer las 800 líneas completas.
El principio que infringe este tipo de archivo es la separación de responsabilidades, Separation of Concerns en inglés. Esta es la última entrega de la serie sobre principios de desarrollo.
La separación de responsabilidades (SoC) establece que un programa debe dividirse en unidades con responsabilidades distintas, de modo que cada parte se ocupe de una sola.
Una «responsabilidad» es un tipo de tarea que el programa debe atender. Cómo mostrar la pantalla, de dónde obtener los datos y cómo aplicar las reglas de negocio son responsabilidades distintas.
El término fue acuñado por el informático Dijkstra, quien lo expresó así en un texto de 1974.
Pensar concentrándose en un solo aspecto cada vez. Es la única técnica de pensamiento eficaz que conozco.
La mente humana no puede manejar varias responsabilidades a la vez. Por eso, cada fragmento de código debería contener una sola.
Un caso conocido: HTML, CSS y JS
Si han trabajado en desarrollo web, ya han aplicado la separación de responsabilidades a diario.
| Tecnología | Responsabilidad |
|---|---|
| HTML | Estructura — qué existe |
| CSS | Presentación — cómo se ve |
| JavaScript | Comportamiento — cómo responde |
Si, como antes, llenamos las etiquetas HTML de atributos style y onclick, hasta cambiar el color de un botón exige buscar en HTML. Al separarlo en tres archivos, el diseñador solo mira CSS y quien se ocupa del marcado, solo HTML.
La estructura controlador-servicio-repositorio del backend y la separación entre vista, modelo de vista y capa de datos en iOS siguen exactamente el mismo principio. MVC y las arquitecturas por capas son, en última instancia, patrones que formalizan la separación de responsabilidades.
Si operamos aquella vista de 800 líneas
Vamos a dividir la vista de 800 líneas que vimos según sus responsabilidades.
// Before: Todas las responsabilidades en un archivo
struct ProductPage: View {
// Responsabilidad 1: Obtener datos (llamadas de red, carga y gestión de errores 150líneas)
// Responsabilidad 2: Reglas de negocio (cálculo de descuentos e inventario 200líneas)
// Responsabilidad 3: Eventos de analítica (seguimiento de pestañas 100líneas)
// Responsabilidad 4: Dibujar la pantalla (body 350líneas)
}
// After: Cada responsabilidad encuentra su propio lugar
ProductStore(id:) // Obtener datos
calcDiscount(product, user) // Reglas de negocio (función pura)
Tracker.track("product") // Eventos de analítica
struct ProductPage: View { // Solo dibujar la pantalla
@State private var store: ProductStore
var body: some View {
let price = calcDiscount(store.product, user)
...
}
}
Una vez dividido, las ventajas son claras. Si cambia la política de descuentos, basta con mirar calcDiscount; como esta función pura no depende de la pantalla, también es fácil de probar. Si cambia la especificación de la API, solo hay que modificar ProductStore. Frente a leer las 800 líneas completas, el alcance del cambio se reduce a una décima parte.
¿Hasta dónde debemos dividir?
Lo más difícil de separar responsabilidades es decidir dónde trazar la frontera. Si dividimos demasiado, acabamos en un laberinto que obliga a recorrer decenas de archivos.
Mi criterio es el motivo del cambio. Es la misma pregunta que vimos al tratar el SRP de SOLID.
¿Estos dos códigos cambian por el mismo motivo y al mismo tiempo?
La política de descuentos y el diseño de la pantalla cambian por motivos distintos, así que se separan. En cambio, el botón y su controlador de pulsación casi siempre cambian juntos, por lo que los mantenemos unidos. Que SwiftUI agrupe estructura, estilo y comportamiento en un mismo archivo por unidad de vista tampoco es una contradicción desde esta perspectiva. Las responsabilidades se han redefinido según lo que cambia conjuntamente, no según el tipo de tecnología.
Para cerrar la serie
Esto es lo esencial que conviene recordar sobre la separación de responsabilidades.
- Hagan que cada fragmento de código se ocupe de una sola responsabilidad. La mente humana no puede hacer multitarea.
- En la práctica, las fronteras deben trazarse según la «unidad que cambia conjuntamente», no según el tipo de tecnología.
- Separar demasiado crea un laberinto. Dividir no puede convertirse en el objetivo.
Con esto termina la serie sobre principios de desarrollo: KISS (mantener la sencillez), DRY (mantener el conocimiento en un solo lugar), YAGNI (solo lo necesario ahora), SOLID (limitar el impacto de los cambios), mínimo asombro (comportarse como se espera) y separación de responsabilidades (una cosa a la vez).
Al mirar atrás, los seis principios apuntan al mismo lugar. El código lo leen las personas, no las computadoras, y un buen código es fácil de cambiar. Aunque olviden los nombres, quédense con esta frase.

