Bórralo. ¿Todo se volvió más simple?
Borra el módulo. ¿Todo se volvió más simple?
Nos entrenaron para agregar abstracción, así que seguimos agregándola: un wrapper aquí, un helper allá, un servicio frente a otro servicio. Pero no todo módulo se gana su lugar. Un módulo debe ocultar complejidad. Si su interfaz es casi tan complicada como el código detrás, no oculta nada. Es solo un salto extra que tienes que leer para entender qué pasa realmente.
Módulos profundos vs superficiales
A Philosophy of Software Design de John Ousterhout lo plantea con precisión. El valor de un módulo es su funcionalidad menos la complejidad de su interfaz.
- Un módulo profundo presenta una interfaz pequeña y simple sobre mucho comportamiento.
read()ywrite()en un sistema de archivos ocultan una maquinaria enorme detrás de dos llamadas. Alto valor. - Un módulo superficial presenta una interfaz casi tan compleja como su implementación. Ofrece poca funcionalidad por unidad de interfaz. Valor bajo, a veces negativo.
Un módulo superficial es de valor negativo porque la interfaz misma es un costo: cada consumidor debe aprenderla, y no obtiene a cambio ninguna complejidad oculta.
# Passthrough superficial: la interfaz es tan ancha como el cuerpo.
def get_user_name(user_service, user_id):
return user_service.get_user(user_id).name
# Los consumidores ya tienen user_service. Esto no oculta nada;
# solo agrega un nombre que memorizar y un archivo que abrir.
Aplica la prueba del módulo
El chequeo concreto del reel: borra el módulo e incorpora su código en cada punto de llamada. ¿El sistema completo se volvió más simple?
Si incorporarlo aclara las cosas — menos archivos, menos nombres, un camino más corto de la pregunta a la respuesta — el módulo era un passthrough superficial. Intégralo. Si incorporarlo empeora las cosas — la misma lógica no trivial copiada por todos lados, una abstracción genuina perdida — entonces el módulo hacía su trabajo. Consérvalo.
| Tras incorporarlo... | Veredicto |
|---|---|
| El sistema es más simple, hay menos que leer | Passthrough superficial — bórralo |
| Lógica duplicada, abstracción real perdida | Módulo profundo — consérvalo |
| Más o menos igual | Inclínate por borrarlo; ganan las menos partes |
Por qué los passthroughs hacen daño
Los módulos superficiales se sienten como arquitectura pero actúan como fricción. Cada uno astilla el diseño en más piezas, así que entender un solo comportamiento significa saltar por más capas. La "classitis" — la creencia de que más clases y módulos, más pequeños, siempre son mejores — produce exactamente esto: un sistema de wrappers delgados donde las interfaces cuestan más de lo que las implementaciones ocultan. Prefiere menos módulos, más profundos, que oculten cada uno algo real.
Movidas avanzadas
- Cuenta los saltos. Si rastrear una operación abre cinco archivos que cada uno reenvía al siguiente, la mayoría de esas capas son superficiales.
- Relación interfaz-implementación. Cuando la firma y el docstring son tan largos como el cuerpo, eso huele a passthrough.
- No confundas una frontera con un wrapper. Un adaptador delgado en una frontera real del sistema (una capa anticorrupción, un puerto) puede valer la pena; un wrapper delgado en medio de tu propio código normalmente no.
- Resiste la extracción prematura. Espera a que la lógica se reutilice de verdad o sea genuinamente compleja antes de darle su propio módulo.
Recursos
- A Philosophy of Software Design — John Ousterhout
- John Ousterhout sobre módulos profundos vs superficiales (charla)
- The Wrong Abstraction — Sandi Metz
- "Rule of Three" — Martin Fowler, Refactoring
¿Desarrollas sistemas de IA o en la nube? Yeda AI audita y refuerza bases de código de LLM y aplicaciones en producción. Hablemos · Lee el blog