Recuerdo haber leído algunos libros y ver representaciones
del MVC, pero todos ellos mostraban en sus clases de la capa vista, una referencia a alguna clase de la capa modelo, o viceversa. Pero… y
entonces…. tengo una duda; no era que el MVC era una “¿programación en 3 capas?”,
y si hablamos de capas, por que existen referencias cruzadas. Bueno, después de exhaustivos y apasionales
debates sobre si el modelo debía considerarse una capa transversal a toda la arquitectura (y algunos otros
argumentos más alocados), descubrimos, que el MVC no fue igual toda la vida (es más hasta el día
de hoy encuentro tantos MVC como arquitectos). Pero no todo es tan relativo, se
mantiene algunos principios de responsabilidad de las capas.
Inicialmente y a grande rasgos, podemos decir que existen dos formas de MVC. Y la diferencia básica entre el primero y el segundo, es que en el primero (versión inicial), no se tiene una variable de referencia a alguna clase del “Modelo” en la capa de la vista, como mencione anteriormente.
Realizaré la presentacion en dos post, el primero, será el MVC inicial y el segundo el que tome en cuenta las relaciones entre el modelo, y la vista, y por que evoluciono de esta forma.
Inicialmente y a grande rasgos, podemos decir que existen dos formas de MVC. Y la diferencia básica entre el primero y el segundo, es que en el primero (versión inicial), no se tiene una variable de referencia a alguna clase del “Modelo” en la capa de la vista, como mencione anteriormente.
Realizaré la presentacion en dos post, el primero, será el MVC inicial y el segundo el que tome en cuenta las relaciones entre el modelo, y la vista, y por que evoluciono de esta forma.
MVC + V1
La comunicación de cada capa con la inmediata superior, es
lo que llevó a mucha gente a llamar a esto “programación en tres capas”. Como se
distingue en las relaciones del diagrama, no existe una comunicación directa
entre el modelo, y la vista. Las
referencias a interfaces y no
directamente hacia las clases, nos permitirán un crecimiento por agregación (crear una clase y agregarla a nuestro software) y
no por modificación. Así por ejemplo si en lugar de instanciar en el
controlador un JFrame, instanciaramos un JInternalFrame, solo tendríamos que crear un Internal Frame e implementar la interfaz, sin tener que modificar el
controlador mas que para cambiar la referencia. En esta forma de orgenizar el código, solo se utilizan “objetos del lenguaje” (Map), y no "objetos del modelo" (Persona), y es esta característica, la que le dá la pureza de la separación entre
capas.
El codigo fuente Java de esta Ejemplo se puede encontrar aquí!
Algunas consideraciones
Como vemos cada una de las clases tienen una referencia a
una interfáz, y no a una clases concreta. También se lo puede hacer con clases
abstractas, pero debido a la posibilidad de herencia múltiple de interfaces (Una interfaz puede heredar varias interfaces) e implementación
múltiple que tienen las clases (Una clase puede implementar varias interfaces), en Java, nos conviene utilizarlo de esta forma para ganar en flexibilidad para agregar
y sacar métodos
... private IControlable controler; public FrmPersona(IControlable controler) { super(); this.controler = controler; initGUI(); } ...
... private IControlable controlador; public Persona(IControlable controlador){ this.controlador = controlador; } ...
Vista - "Las pantallitas"1
La vista tiene como responsabilidad mostrar y tomar datos. Las vistas no conocen nada de enteros, o tipos de dato. Todo para ellas son Strings. Con el desarrollo de las tecnologias web, se pensaba en poner validaciones de formato en esta capa (numerales, etc) para no tener que ir hasta los servidores y disminuir tanto performance como experiencia de usuario, pero con las tecnologias asincronas como ajax, esto pronto dejó de ser nacesario. No realiza ningún tipo de validación de negocio, ya que es el modelo el encargado de realizar dichas validaciones. Cada una de las acciones realizadas es una llamada al controlador para que él sea el encargado de tomar cualquier decisión.... @Override public void setData(Mapdata) { this.txtNombre.setText(data.get(CtrlPersona.NAME)); this.txtApellido.setText(data.get(CtrlPersona.SURNAME)); this.txtEdad.setText(data.get(CtrlPersona.AGE)); } ... @Override public Map getData() { Map data = new HashMap (); data.put(CtrlPersona.NAME, this.txtNombre.getText()); data.put(CtrlPersona.SURNAME, this.txtApellido.getText()); data.put(CtrlPersona.AGE, this.txtEdad.getText()); return data; } ... @Override public void actionPerformed(ActionEvent arg0) { if(arg0.getSource() == this.btnCancel){ controler.cacelAction(); } if(arg0.getSource() == this.btnOK){ controler.oKAction(); } } ...
Controlador - "Eso que entedes vos y nadie más... ponelo si querés...pero no pierdas tiempo.. bla bla...bla... cerveza!"1
En la capa de controlador, podemos encontrar que es donde se
instancia las interfaces y modelos que el controlador quiere manejar. Una alternativa a esto ultimo, es que las instancias (Tanto de la vista, como del Modelo) sean pasadas como parametros al constructor del controlador.
Algunas de las responsabilidades de esta capa podrían ser
las siguientes:
- Realizar validaciones de formato
- Subir y bajar variables de sesión
- Redireccionar y hacer el forwared de las pantallas y manejar el ciclo de vida de las Interfaces de usuario o sistemas.
- Capturar tanto las excepciones de negocio, como de formato.
- Tomar y poner información en las interfaces
... { myView = new FrmPersona(this); myModel = new Persona(this); } ... public void oKAction() { Mapdata = myView.getData(); try{ ParameterTool.checkMandatoryFields(data); ParameterTool.checkInteger(AGE, data.get(AGE)); myModel.save(data); }catch(MenorDeEdadException e){ setReturningMessage(e.getMessage()); }catch(IllegalArgumentException e){ setReturningMessage(e.getLocalizedMessage()); } } ...
Modelo - "El diagramita de clases"1
La capa del modelo, es aquella que representa el negocio de
la aplicación. Son aquellas clases con estructura de Java Beans que tanto
conocemos. En un MVC la lógica de guardado de la base de datos suele estar en
las clases del modelo, por supuesto haciendo llamadas a métodos de alguna librería
o un paquete de utilidades para conectarnos con las bases. Es la capa que con las
sucesivas iteraciones (y evoluciones a stacks de software) ha ido subdividiéndose,
en subcapas, como por ejemplo la de repositorios de objetos.
Una responsabilidad de implementación definida e interesante
de destacar es la de chequear las reglas del negocio.
Bueno, existe mucho más que se puede decir de este patrón,
ya que como dije al principio, se ha hablado mucho. Pero esto es lo que considero
importante para poder aplicarlo, no solo de una forma académica, si no también implementable.
En el próximo post escribiré de la evolución
del MVC y esto será en los próximos N días. (O tal vez N a la M días).
Mi pasión siempre ha sido no solo hablar teóricamente de
algo, porque de eso seguro hay mucha gente que puede hablar más y mejor, pero
al final del día… siempre soy solo un programador… y quiero ¡ver pantallitas
funcionando!
1) Nota: traducidos a lenguaje "jefe" para la fácil adaptacion a todo tipo de públicos.