Patron MVC duda de implementación...

Iniciado por digimikeh, 14 Mayo 2019, 01:41 AM

0 Miembros y 1 Visitante están viendo este tema.

digimikeh

Hola..

Tengo una duda con el patron de diseño MVC:

Entiendo que todo lo que se refiere a la visual esta en V (View)
Y todo lo que corresponda a la lógica está en C (Controller)
Lo que pertenece a base de datos en M (Model)

Pero no me imagino como pueda organizarse todo esto, aun no entiendo como se separa.. por ejemplo, un botón es una mezcla de V y C, porque no solo es algo visual sino que ejecuta una función, es decir es programación y visual... a menos que la programación de los botones no entre en la capa de Controller...  si es así, qué entra en esta capa?..

Saludos y gracias.
Dungeons & dragons;
dragons.Attack();

EdePC

Saludos,

- Todo lo que el usuario mira o ve, va en Vista.

- Cuando se inicia una página web, esta debe iniciar desde el Controlador, el controlador prepara y llama a la vista correspondiente para que sea mostrada. Si esa vista tiene un botón con una función y dicha función es código backend (del lado del servidor) el botón llama al Controlador (función en el Controlador) y este controlador hace la tarea, luego prepara y muestra la vista correspondiente (puede ser la misma u otra).

Serapis

Cita de: digimikeh en 14 Mayo 2019, 01:41 AM
...Pero no me imagino como pueda organizarse todo esto, aun no entiendo como se separa.. por ejemplo, un botón es una mezcla de V y C, porque no solo es algo visual sino que ejecuta una función...
En efecto, así es.

La separación clara solo es de cara a la teoría, en la práctica rara vez suele resultar así, por lo que simplemente hay que sacrificar alguna parte. En general para atenerse de algún modo, estricto, al patrón fuerza casi siempre a dar rodeos en ciertas partes, para lograr lo mismo (A llama a B, B llama a C, y luego C, representa algo en A... cuando directamente ese A, en vez de hacer la pertinente llamada, podría hacer la labor él mismo).

No obstante, al margen de la ineficiencia en la ejecución, suele buscarse la eficiencia en la implementación, al separarlo en partes distintas entre sí, si decides (por ejemplo) cambiar la vista (V), solo cambias esa parte, no necesitas tocar el resto, luego teóricamente resulta menos complejo y por ello más eficiente de abordar... también alejas problemas, si algo falla en la nueva implementación casi que queda claro, que será la implementación de la vista, luego no hay que repasar otras partes...

Es toda esa parte que 'no se ve' a simple vista, la que realmente le da sentido al patrón...

digimikeh

Entiendo, gracias por las explicaciones...

Por ejemplo, hoy mismo me he encontrado con un caso particular, el rellenado de una tabla con datos de la base de datos..

la tabla es pertenece a una interfaz gráfica (V)
los datos se extraen de una ejecución de SQL.. (M)

Tengo la siguiente función:

Código (cpp) [Seleccionar]

int UnaClase::rellenarTabla() {

     //Conectar con base de datos
     //ejecutar consulta SQL
     //obtener datos y meterlos a la tabla (V)

}


Como verán, aqui se mezcla los datos con la visual...
En que namespace o capa debe quedar esta función?

O quizá esté mal empleada la función...
Que tipo de datos se comparten entre capas?.. solo primitivos?, mi duda es esta ya que no me parece muy lógico dividir en capas y compartir tipos específicos de cada capa una con otra..

Disculpen tantas preguntas..

Gracias, saludos!11
Dungeons & dragons;
dragons.Attack();

EdePC

- Poniéndolo simple, la Vista solo espera recibir data, esta data se la provee el Controlador, y el Controlador le pide Data de Base de Datos al Modelo y se la entrega a la Vista.

- Para tu ejemplo:

-- Controlador
---- Mostrar  al Usuario la Vista que contiene la estructura de una tabla
---- Solicitar datos de la Base de Datos al Modelo
---- Procesar los datos recibidos del Modelo y dárselos a la Vista

-- Modelo
---- Traer los datos solicitados por parte del Controlador y dárselos

-- Vista
---- Pedir al Controlador el contenido de la Tabla
---- Recibir el contenido de la Tabla y mostrarla

- La Vista solo debería de pedir y recibir datos, no debería de Procesar ningún dato.
- El Modelo interactúa con la Base de Datos usando sentencias SQL adecuadas e incluso puede procesar los valores devueltos por dichas sentencias SQL.
- El controlador Prepara, Limpia, Sanitiza, los datos que vienen de la Vista y las Procesa, de ser necesario solicita datos de la Base de Datos al Modelo y prepara estos datos devueltos para ser entregados a la Vista.

digimikeh

Ok, entonces la función rellenarTabla() en realidad no estaría bien verdad?, tendría que desglosarla.... ya que estaría mezclando dos capas en una sola función..

podría desglosarla así?:

Vista:
Código (cpp) [Seleccionar]


//Incluyo la cabecera que manipula el controlador
#include "Manager.h"

//suponiendo que tengo una variable que represente a la tabla y se llame
//tbl_data
void UMasterWindow::mostrarTabla(){
     Controller::Manager manager;

     ui->tbl_data = manager.controlarTabla(tbl_data, "Usuarios");
     ui->tbl_data->show();
}




Controlador:
Código (cpp) [Seleccionar]

//Incluyo la cabecera que manipula la visual de la tabla...
#include "QTableView.h"
#include "SQLManagement.h"
#include "UMasterWindow.h"

QTableView Manager::controlarTabla(QTableView tbl_data, QString tbl_name){
     Model::SQLManagement sqlM;

     QString queryCmd;
     queryCmd = "SELECT * from " + tbl_name;
     return sqlM.rellenarTabla(tbl_data, queryCmd);
   
}


//Modelo:
Código (cpp) [Seleccionar]

#include "Manager.h"
#include "QTableView.h"

QSqlQueryModel * model = nullptr;

QTableView SQLManagement::rellenarTabla(QTableView tbl_data, QString queryCmd){
     model = new QSqlQueryModel;
     QSqlQuery query;
     query.exec(queryCmd);
   
     model->setQuery(queryCmd);
     tbl_data->setModel(model);
     cerrarBD();

     return tbl_data;

}

void SQLManagement::cerrarBD(){
     delete db;
     db = nullptr;
}



Es asi como lo imagino, no se si estará bien... 
Me recomiendan un buen curso de MVC?.. necesito ver en la practica con el código como funciona, porque el ejemplo que acabo de poner me parece una espagueti...

Saludos y gracias!
Dungeons & dragons;
dragons.Attack();

Daghdha

Si hablamos de una aplicación web, hay que intentar separar el frontend del backend como si de dos proyectos diferentes se tratase.
Al aplicar el patrón de diseño MVC, y ciñéndonos solo al backend, podemos separarlo en tres partes independientes.

El controlador es el encargado de tramitar todas las peticiones que nos llegan desde el frontend. Si el usuario hace click en un botón de login, el controlador es el encargado de recibir los datos pertinentes y pasárselos al modelo pertinente.

El modelo se encarga de recibirlos, comprobar o solicitar lo que se desee en la base de datos, y devolverlo. No debería tratarlos ni hacer operaciones con ellos, para eso está el controlador.

La vista se ocupa de recibir los datos resultantes, y de seleccionar el formato de estos para ser recibidos por el frontend (JSON, XML, CSV...)

Ahora bien, en otras aplicaciones, de escritorio por ejemplo, la vista es en si misma lo que se muestra por pantalla, así que de esta depende también la interacción del usuario con los componentes y de mostrar los datos que le llegan desde el controlador.

Saludos