Model-View-Presenter
Qué organiza
Model-View-Presenter (MVP) es una familia de patrones que asigna al Presenter una coordinación explícita entre interacción, resultados de aplicación y representación. Busca extraer decisiones de presentación de controles concretos para poder comprenderlas y ejercitarlas con independencia de la pantalla.
En el Atlas pertenece a Presentation Patterns, junto a model-view-controller y model-view-viewmodel. Su alcance es la UI de un cliente o capa de presentación. No especifica un architecture-profile completo ni reemplaza reglas de organización interna.
Historia y variantes
Mike Potel describió en Taligent, en 1996, una generalización de MVC que incluía Model, View, Presenter y otros conceptos, como selections, commands e interactors. El Presenter coordinaba la aplicación interactiva. Ese modelo histórico es más amplio que la habitual tríada resumida y no equivale exactamente a Passive View. MVP: The Taligent Programming Model for C++ and Java.
El informe usa business logic en una descripción amplia del coordinador. Aquí distinguimos coordinación de presentación de reglas autoritativas de dominio: no trasladamos automáticamente esa terminología histórica a una obligación de concentrar negocio en Presenter.
Esta diversidad importa al comparar frameworks. Una descripción que admite binding directo entre View y Model puede ser una variante reconocida de MVP. No contradice necesariamente otra descripción que concentra actualizaciones en Presenter; primero hay que identificar qué formulación está empleando cada autor.
Roles y contratos
Un esquema orientativo es:
User → View ↔ Presenter → Model / ApplicationRepresenta colaboración durante interacción, no todos los imports ni una única topología válida. Presenter normalmente recibe eventos de View, coordina operaciones, obtiene resultados, transforma información y decide cómo actualizar la presentación.
Model no significa database table ni ORM entity. Puede representar estado de dominio o aplicación, comportamiento, datos requeridos por presentación y abstracciones fuera del mecanismo de UI. Un Presenter que conoce un caso de uso no necesita acceder directamente a un driver.
View representa controles, layout e interacción concreta. Puede exponer eventos semánticos como SaveRequested en lugar de detalles del mouse. Presenter puede depender de una abstracción de View; que esta sea interface, protocolo o conjunto de callbacks depende de la implementación.
Presenter no es simplemente Controller renombrado. La diferencia útil está en cuánto comportamiento de presentación coordina, cómo conoce la View y quién sincroniza sus datos. Nombres parecidos no demuestran equivalencia de responsabilidades.
Passive View
En Passive View, la View deja prácticamente toda la coordinación al Presenter. Este obtiene entradas, delega operaciones y actualiza controles mediante un contrato; View no sincroniza directamente con Model. Fowler desarrolla esta variante para hacer la lógica de presentación comprobable sin ejecutar la UI. Passive View.
Una abstracción puede ofrecer leer nombre, mostrar error y establecer disponibilidad de Guardar. No necesita reproducir toda la API del toolkit. El contrato debería expresar intenciones comprensibles; exponer cada propiedad de cada widget hace crecer la interfaz sin conservar una separación útil.
Ventajas habituales son View simple, decisiones de presentación aisladas y pruebas con un sustituto de la pantalla. El costo es coordinación explícita: muchas llamadas, boilerplate, interfaces amplias y Presenters que crecen con cada interacción. Esos costos requieren revisar cohesión, no añadir indiscriminadamente otra capa.
En nuestro diseño, una prueba puede afirmar que el rechazo conserva el texto y presenta el error adecuado. Aun así, hay que verificar la View real: que el botón emita el evento correcto, que mapping y layout sean accesibles y que el error resulte visible. Testabilidad del Presenter no garantiza corrección completa de UI.
Supervising Controller
En Supervising Controller, la sincronización simple puede permanecer en la View o su binding. El coordinador interviene en decisiones más complejas. Fowler usa Controller para este papel, también asociado a Presenter: es una advertencia sobre vocabulario, no un cuarto participante obligatorio. Supervising Controller.
Así, el campo de nombre puede sincronizarse automáticamente con un modelo editable, mientras Presenter coordina guardar y decide qué hacer con un conflicto. Frente a Passive View, no todas las actualizaciones pasan por llamadas explícitas del coordinador.
El beneficio es menos código repetitivo para sincronización sencilla. El costo es repartir comportamiento entre binding y Presenter, aumentando lo que debe entenderse para reconstruir una interacción. Conviene declarar quién actualiza cada dato y quién decide cuándo un cambio está listo para mostrar.
Si binding y Presenter escriben alternativamente el mismo estado sin reglas, puede haber eventos recursivos o valores sobrescritos. Ese problema no se resuelve escogiendo un nombre: requiere un ownership coherente y pruebas de las interacciones reales.
Ejemplo común: Edit Customer
Usamos el mismo caso propio de MVC y MVVM: cargar cliente, editar nombre, validar, guardar y mostrar éxito o error. Una operación de aplicación conserva la autoridad sobre la modificación; la UI administra un borrador y feedback.
En una implementación Passive View:
- Al abrir la pantalla, View avisa a Presenter, que solicita el cliente y muestra el nombre mediante su contrato.
- View entrega el nombre propuesto cuando el usuario guarda, o Presenter lo lee a través del contrato definido.
- Presenter aplica feedback de entrada y solicita guardar a la aplicación. Una regla de negocio sigue evaluándose allí.
- Mientras espera, Presenter actualiza la indicación de operación pendiente y disponibilidad de acciones.
- Ante aceptación muestra éxito y actualiza el estado confirmado; ante rechazo conserva el borrador y muestra los errores.
En Supervising Controller, el borrador puede sincronizarse directamente con la View. Presenter mantiene carga, guardado y tratamiento de resultados complejos. Ambas versiones deben acordar si leen el valor por cada evento, al abandonar el campo o al guardar; mezclar supuestos puede enviar un nombre anterior.
No es necesario copiar el cliente entero para cada cambio de presentación. Sí hace falta distinguir una edición todavía no confirmada de estado de negocio aceptado. La elección del objeto que contiene el borrador depende de la variante, no de la existencia de una carpeta Models.
Comparación con MVC y MVVM
| Pregunta | Orientación útil para comparar |
|---|---|
| ¿Quién actualiza View? | Presenter explícitamente en Passive View; reparto con binding en Supervising Controller. |
| ¿View consulta Model? | No en Passive View; puede hacerlo en otras variantes. |
| ¿Existe un contrato de View? | Frecuente para aislar coordinación, sin exigir una palabra clave concreta. |
| ¿Dónde se prueba la decisión? | En Presenter y colaboradores; sincronización y controles requieren integración. |
Frente al MVC clásico, MVP suele dar al coordinador mayor conocimiento de representación y una abstracción explícita de View. Pero las familias se solapan: no existe una frontera universal por nombre de clase.
Frente a MVVM, Presenter suele enviar actualizaciones explícitas, mientras ViewModel expone estado que View consume mediante binding. Supervising Controller muestra por qué «MVP no usa binding» sería falso. Comparar contratos, llamadas, estado observable, comandos y sincronización resulta más informativo. presentation-patterns reúne esas dimensiones.
Negocio, composición y costos
Que Order no pueda cancelarse después de shipment es una regla de negocio, no una condición que deba existir exclusivamente en Presenter. Mostrar Cancel deshabilitado puede ser una decisión de presentación derivada. Otra entrada a la aplicación debe respetar la misma regla aunque no use esta pantalla.
MVP puede organizar presentación dentro de layered-architecture. Con ports-and-adapters, la UI y su coordinación pueden traducir interacción a contratos del núcleo. Con clean-architecture, deben conservarse dependencias hacia políticas interiores. El patrón no decide automáticamente dónde vive cada contrato ni cuántos procesos existen.
Su valor depende de complejidad real y facilidad de probar decisiones. Para una pantalla trivial, una interfaz enorme y delegaciones vacías pueden costar más que la separación obtenida. Para una interacción compleja, aislar feedback y coordinación puede reducir cambios en controles.
Carpetas Views/Presenters/Models no demuestran MVP. Revisar responsabilidades, ownership del borrador y resultados, dependencia del framework y mecanismos concretos de actualización permite evaluar la separación efectiva.