En la entrada sobre patrones de Diseño se habla sobre el patrón MVC, en esta oportunidad vamos explicar un ejemplo practico donde se aplica este modelo mostrando la forma de independizar los componentes de nuestro sistema, además lo combinaremos con los patrones DAO y VO para facilitar el manejo de la información.
Por cuestiones de tamaño no vamos a hacer la aplicación paso a paso, pero si se explicará la lógica de la misma, al final se presenta una opción de descarga del código fuente donde veremos la aplicación en funcionamiento.
El problema.
Se solicita desarrollar un sistema de administración de usuarios con un CRUD (Create, Read, Update, Delete) básico nos advierten que la aplicación es un prototipo inicial el cual esta propenso a cambios, pues aún no se tienen definidas las ventanas con las que se va a trabajar ni la información requerida, por le momento se trabajará con una BD MySql, pero posiblemente se tenga que migrar a otro sistema gestor....
La solución.
Se aplica el MVC permitiendo independizar la lógica y la parte visual del sistema usando para eso un controlador que administra los procesos sirviendo como puente entre estos.
para la BD se usa MySql, reutilizando la BD creada en el ejemplo de conexión con Java, el Scritp es el siguiente.
CREATE DATABASE /*!32312 IF NOT EXISTS*/`codejavu` /*!40100 DEFAULT CHARACTER SET latin1 */; USE `codejavu`; /*Table structure for table `persona` */ DROP TABLE IF EXISTS `persona`; CREATE TABLE `persona` ( `id` int(10) NOT NULL, `nombre` varchar(30) default NULL, `edad` int(3) default NULL, `profesion` varchar(30) default NULL, `telefono` decimal(10,0) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*Data for the table `persona` */
De esta forma se crea la Base de Datos a la que se va a apuntar, la cual contiene solo una tabla Persona con la que se realizan todas las operaciones CRUD.
La agrupación de clases de nuestro sistema es:
La agrupación de clases de nuestro sistema es:
Como vemos tenemos la parte visual compuesta por las clases VentanaPrincipal, VentanaRegistro, VentanaBuscar, la lógica de negocio se establece en el modelo el cual se compone por la clase Logica y Conexión y aplicamos los patrones DAO y VO por medio de las clases PersonaDao y PersonaVo y por ultimo el controlador se define en la clase Coordinador, encargada de establecer todas las relaciones del sistema, la clase Principal prepara las instancias iniciales del sistema y posteriormente lo ejecuta.
Veamos como funciona el Patrón:
El Modelo.
Como se mencionó, en el modelo tenemos la lógica de negocio, serán todas las clases vinculadas con el CRUD a nivel interno, que en ultimas es en lo que gira nuestro sistema.
Clase Logica.
Esta clase permite realizar las operaciones asociadas a la lógica de negocio como tal, desde ella realizamos las validaciones y llamados a las operaciones CRUD del sistema.
En caso de que se requieran procesos adicionales asociados a la lógica de negocio, aquí será donde se creen los métodos para dichos procesos, por ejemplo el método validarRegistro determina si los datos son correctos y permite registrar la persona en el Dao.
Clase Conexión.
En esta clase tenemos la cadena de conexión con la que trabajará nuestra aplicación, en ella se define la base de datos, el usuario, password y driver de conexión, si por ejemplo en un futuro se nos pide conectarnos a una base de datos diferente o establecer un sistema gestor distinto (pero con la misma estructura de tablas y campos), tan solo modificaremos esta clase y dicho cambio sera transparente para el resto del sistema.
(Tener en cuenta que los datos de login y password corresponden a los que yo dejé por defecto al instalar MySql, es decir login root y sin contraseña)
Clase PersonaVo.
Al utilizar este tipo de clases, aplicamos el patrón Value Object o VO (Anteriormente conocidas como DTO Data Transfer Object) en el que representamos las entidades (Tablas) de la base de datos, la tabla persona tiene los campos id, nombre, edad, profesión teléfono entonces nuestra clase Vo tendrá estos mismos atributos y de esta manera podremos transportar un objeto persona con todos estos valores por medio de los métodos set y get de cada atributo.
Este patrón nos facilita enormemente el transporte de la información, evitando que se envíen gran cantidad de parámetros a un método cuando queremos hacer un registro o actualización, también en caso de que se modifique la tabla de la BD, nuestra clase deberá ser modificada así como los métodos que obtienen la información, mas no los métodos que la transportan.
Clase PersonaDao.
Cuando utilizamos estas clases, aplicamos el patrón Data Access Object o DAO, básicamente este patrón consiste en centralizar los procesos de acceso a la base de datos evitando inconsistencias y posibles problemáticas cuando esto se realiza a lo largo de la aplicación.
Con este patrón independizamos la lógica de negocio de la lógica de acceso a datos obteniendo mayor organización y flexibilidad en el sistema.
La Vista.
Aquí se define la parte visual del sistema, en la vista estableceremos todas las ventanas o interfaces gráficas de usuario, mediante las cuales representamos todo el modelo permitiendo la interacción entre la aplicación y el cliente.
Clase VentanaPrincipal.
Esta clase representa la ventana inicial de la aplicación, posee un área de texto con una pequeña descripción y 2 botones que darán inicio a los eventos principales del sistema.
se comunica con el modelo mediante la clase coordinador y desde esta se cargan las otras ventanas de la aplicación.
Clase VentanaRegistro.
Permite el ingreso de información a la BD, en ella se evidencian todos los campos de la tabla Persona y presenta un medio gráfico para las clases PersonaVo y PersonaDao, al ejecutar el evento de registro se establece comunicación entre el coordinador y la clase Lógica donde se encuentran todas las validaciones y casos para el ingreso de información.
Clase VentanaBuscar.
Esta clase permite realizar las operaciones de Consulta, Actualización y eliminación de la tabla Persona, igual que la anterior representa la parte visual del modelo y se ejecutan los eventos para la lógica de los procesos anteriores, la forma de obtener los datos y como se le envían parámetros de consulta a la BD.
El Controlador.
Esta parte del patrón es la que define la lógica de administración del sistema, establece la conexión entre la vista y el modelo.
Clase Principal.
Esta clase contiene el método main que ejecuta la aplicación, el método hace un llamado al método iniciar el cual crea las instancias de las clases ventanas y la clase Logica estableciendo las relaciones con la clase Coordinador.
A cada instancia de las clases se les envía una instancia de la clase Coordinador, y a la instancia de Coordinador se le envía cada instancia de las clases, esto por medio de los métodos set y get estableciendo las relaciones necesarias y por ultimo se usa la instancia de la clase VentanaPrincipal para cargarla en pantalla.
Clase Coordinador.
Esta clase contiene toda la lógica de relaciones en el aplicativo, es el puente entre el modelo y las vistas.
Puede contener instancias locales tanto de clases de la vista como de clases del modelo, estas instancias tienen sus respectivos métodos set y get permitiendo el flujo de llamados del sistema.
Cuando se desea registrar una persona desde la clase VentanaRegistro se hace un llamado al método registrarPersona() de la clase Coordinador, posteriormente esta clase llama al método ValidarRegistro() de la clase Logica y esta a su vez realiza las validaciones correspondientes para determinar si se llama o no al método RegistrarPersona() de la clase PersonaDao.
El proyecto tiene los directorios db y conector, estos directorios se crearon solamente para agregar el script de creación de la BD y el mysql connector, este ultimo debe ser agregado al build path para que el sistema pueda funcionar (sobre el proyecto, clic derecho/configure Build path... ).
Descarga.
En el link de descarga se encuentra el archivo .rar con la aplicación, solo es cuestión de descomprimir y abrir con Eclipse pero si usas NetBeans te interesará esta entrada con un vídeo paso a paso de como abrirlo en el............ (recuerden que es gratis.....nada cuesta opinar, compartir o agradecer :))
Y Listo, como se mencionó es un ejemplo simple, sin mucha lógica para aplicar, pero la intención es dar a conocer un poquito mas claro como se puede aplicar el MVC, espero que este ejemplo sea de utilidad..... ;)
Veamos como funciona el Patrón:
El Modelo.
Como se mencionó, en el modelo tenemos la lógica de negocio, serán todas las clases vinculadas con el CRUD a nivel interno, que en ultimas es en lo que gira nuestro sistema.
Clase Logica.
Esta clase permite realizar las operaciones asociadas a la lógica de negocio como tal, desde ella realizamos las validaciones y llamados a las operaciones CRUD del sistema.
En caso de que se requieran procesos adicionales asociados a la lógica de negocio, aquí será donde se creen los métodos para dichos procesos, por ejemplo el método validarRegistro determina si los datos son correctos y permite registrar la persona en el Dao.
public void validarRegistro(PersonaVo miPersona) { PersonaDao miPersonaDao; /*Valida que solo se ingresen id de 3 digitos*/ if (miPersona.getIdPersona() > 99) { miPersonaDao = new PersonaDao(); miPersonaDao.registrarPersona(miPersona); }else { JOptionPane.showMessageDialog(null,"El documento de la persona debe" + " ser mas de 3 digitos","Advertencia",JOptionPane.WARNING_MESSAGE); } }
Clase Conexión.
En esta clase tenemos la cadena de conexión con la que trabajará nuestra aplicación, en ella se define la base de datos, el usuario, password y driver de conexión, si por ejemplo en un futuro se nos pide conectarnos a una base de datos diferente o establecer un sistema gestor distinto (pero con la misma estructura de tablas y campos), tan solo modificaremos esta clase y dicho cambio sera transparente para el resto del sistema.
(Tener en cuenta que los datos de login y password corresponden a los que yo dejé por defecto al instalar MySql, es decir login root y sin contraseña)
public Conexion() { try{ //obtenemos el driver de para mysql Class.forName("com.mysql.jdbc.Driver"); //obtenemos la conexión conn = DriverManager.getConnection(url,login,password); if (conn!=null){ System.out.println("Conección a base de datos "+bd+" OK"); } } catch(SQLException e){ System.out.println(e); }catch(ClassNotFoundException e){ System.out.println(e); }catch(Exception e){ System.out.println(e); } }
Clase PersonaVo.
Al utilizar este tipo de clases, aplicamos el patrón Value Object o VO (Anteriormente conocidas como DTO Data Transfer Object) en el que representamos las entidades (Tablas) de la base de datos, la tabla persona tiene los campos id, nombre, edad, profesión teléfono entonces nuestra clase Vo tendrá estos mismos atributos y de esta manera podremos transportar un objeto persona con todos estos valores por medio de los métodos set y get de cada atributo.
Este patrón nos facilita enormemente el transporte de la información, evitando que se envíen gran cantidad de parámetros a un método cuando queremos hacer un registro o actualización, también en caso de que se modifique la tabla de la BD, nuestra clase deberá ser modificada así como los métodos que obtienen la información, mas no los métodos que la transportan.
/** * @return the idPersona */ public Integer getIdPersona() { return idPersona; } /** * @param idPersona the idPersona to set */ public void setIdPersona(Integer idPersona) { this.idPersona = idPersona; }
Clase PersonaDao.
Cuando utilizamos estas clases, aplicamos el patrón Data Access Object o DAO, básicamente este patrón consiste en centralizar los procesos de acceso a la base de datos evitando inconsistencias y posibles problemáticas cuando esto se realiza a lo largo de la aplicación.
Con este patrón independizamos la lógica de negocio de la lógica de acceso a datos obteniendo mayor organización y flexibilidad en el sistema.
public void eliminarPersona(String codigo) { Conexion conex= new Conexion(); try { Statement estatuto = conex.getConnection().createStatement(); estatuto.executeUpdate("DELETE FROM persona WHERE id='"+codigo+"'"); JOptionPane.showMessageDialog(null, " Se ha Eliminado" + " Correctamente","Información",JOptionPane.INFORMATION_MESSAGE); estatuto.close(); conex.desconectar(); } catch (SQLException e) { System.out.println(e.getMessage()); JOptionPane.showMessageDialog(null, "No se Elimino"); } }
La Vista.
Aquí se define la parte visual del sistema, en la vista estableceremos todas las ventanas o interfaces gráficas de usuario, mediante las cuales representamos todo el modelo permitiendo la interacción entre la aplicación y el cliente.
Clase VentanaPrincipal.
Esta clase representa la ventana inicial de la aplicación, posee un área de texto con una pequeña descripción y 2 botones que darán inicio a los eventos principales del sistema.
se comunica con el modelo mediante la clase coordinador y desde esta se cargan las otras ventanas de la aplicación.
Clase VentanaRegistro.
Permite el ingreso de información a la BD, en ella se evidencian todos los campos de la tabla Persona y presenta un medio gráfico para las clases PersonaVo y PersonaDao, al ejecutar el evento de registro se establece comunicación entre el coordinador y la clase Lógica donde se encuentran todas las validaciones y casos para el ingreso de información.
Clase VentanaBuscar.
Esta clase permite realizar las operaciones de Consulta, Actualización y eliminación de la tabla Persona, igual que la anterior representa la parte visual del modelo y se ejecutan los eventos para la lógica de los procesos anteriores, la forma de obtener los datos y como se le envían parámetros de consulta a la BD.
El Controlador.
Esta parte del patrón es la que define la lógica de administración del sistema, establece la conexión entre la vista y el modelo.
Clase Principal.
Esta clase contiene el método main que ejecuta la aplicación, el método hace un llamado al método iniciar el cual crea las instancias de las clases ventanas y la clase Logica estableciendo las relaciones con la clase Coordinador.
A cada instancia de las clases se les envía una instancia de la clase Coordinador, y a la instancia de Coordinador se le envía cada instancia de las clases, esto por medio de los métodos set y get estableciendo las relaciones necesarias y por ultimo se usa la instancia de la clase VentanaPrincipal para cargarla en pantalla.
private void iniciar() { /**Se instancian las clases*/ miVentanaPrincipal=new VentanaPrincipal(); miVentanaRegistro=new VentanaRegistro(); miVentanaBuscar= new VentanaBuscar(); miLogica=new Logica(); miCoordinador= new Coordinador(); /**Se establecen las relaciones entre clases*/ miVentanaPrincipal.setCoordinador(miCoordinador); miVentanaRegistro.setCoordinador(miCoordinador); miVentanaBuscar.setCoordinador(miCoordinador); miLogica.setCoordinador(miCoordinador); /**Se establecen relaciones con la clase coordinador*/ miCoordinador.setMiVentanaPrincipal(miVentanaPrincipal); miCoordinador.setMiVentanaRegistro(miVentanaRegistro); miCoordinador.setMiVentanaBuscar(miVentanaBuscar); miCoordinador.setMiLogica(miLogica); miVentanaPrincipal.setVisible(true); }
Clase Coordinador.
Esta clase contiene toda la lógica de relaciones en el aplicativo, es el puente entre el modelo y las vistas.
Puede contener instancias locales tanto de clases de la vista como de clases del modelo, estas instancias tienen sus respectivos métodos set y get permitiendo el flujo de llamados del sistema.
Cuando se desea registrar una persona desde la clase VentanaRegistro se hace un llamado al método registrarPersona() de la clase Coordinador, posteriormente esta clase llama al método ValidarRegistro() de la clase Logica y esta a su vez realiza las validaciones correspondientes para determinar si se llama o no al método RegistrarPersona() de la clase PersonaDao.
public Logica getMiLogica() { return miLogica; } public void setMiLogica(Logica miLogica) { this.miLogica = miLogica; } public void mostrarVentanaRegistro() { miVentanaRegistro.setVisible(true); } public void mostrarVentanaConsulta() { miVentanaBuscar.setVisible(true); } public void registrarPersona(PersonaVo miPersona) { miLogica.validarRegistro(miPersona); }
La Aplicación.
El Sistema esta desarrollado como un proyecto Eclipse, En la siguiente imagen vemos que se crearon tres paquetes principales y de esta forma se tiene independiente la parte de la vista, el modelo y el controlador, el paquete modelo posee los paquetes conexión dao y vo ya que aunque pertenecen al modelo y la lógica de negocio debe establecerse también su independencia con respecto a las operaciones, es decir, las clases Vo por ejemplo no poseen métodos de operaciones asociadas a la lógica de negocio, tan solo deben representar las tablas de la BD, entonces en el paquete vo se agruparán todas las clases equivalente a entidades.El proyecto tiene los directorios db y conector, estos directorios se crearon solamente para agregar el script de creación de la BD y el mysql connector, este ultimo debe ser agregado al build path para que el sistema pueda funcionar (sobre el proyecto, clic derecho/configure Build path... ).
Conclusiones.
Como vimos tenemos un proyecto funcional que realiza las operaciones básicas del CRUD, y donde todas sus partes se encuentran separadas por funcionalidades, separando la parte visual de la lógica de negocio y estableciendo relaciones entre ellas............ en si se desarrolló como ejemplo practico, existen validaciones muy básicas y procesos simples pero pensado en modo de ejemplo sin mayor complejidad, también se utilizan algunos conceptos vistos en entradas anteriores como es el caso del manejo de excepciones, patrones entre otros...Descarga.
En el link de descarga se encuentra el archivo .rar con la aplicación, solo es cuestión de descomprimir y abrir con Eclipse pero si usas NetBeans te interesará esta entrada con un vídeo paso a paso de como abrirlo en el............ (recuerden que es gratis.....nada cuesta opinar, compartir o agradecer :))
Y Listo, como se mencionó es un ejemplo simple, sin mucha lógica para aplicar, pero la intención es dar a conocer un poquito mas claro como se puede aplicar el MVC, espero que este ejemplo sea de utilidad..... ;)
También te podría Interesar.
- Que son los Patrones de Diseño ?
- Ejemplo Conectando Java con MySql
- Manejo de Excepciones en Java
- Conceptos Básicos de Programación Orientada a Objetos.
- ¿ String Vrs StringBuffer Vrs StringBuilder ?
- Comparando Fechas En Java
- Integración Continua, Primeros Pasos Con Jenkins
- Leer Archivo Properties en Java
- Tutorial Proyecto Web Con Eclipse
¿Hay algo que quieras anexar o comentar sobre esta entrada? no dudes en hacerlo.....y si te gustó, te invito a compartir y Suscribirte ingresando al botón "Participar en este sitio" para darte cuenta de mas entradas como esta ;)
Muy bueno tu artículo, voy a compartirlo
ResponderEliminarMe alegra que te gustara (Y)
EliminarMuy bien explicados estos temas, muchas gracias por compartir material de tan buena calidad.
ResponderEliminarEs con mucho gusto, me alegra que te sirvan ;)
EliminarHola me sirvió mucho, excelente!
ResponderEliminarMe alegra, gracias por hacermelo saber ;)
EliminarMuchas gracias por el ejemplo, me ha aclarado mucho el tema.
ResponderEliminarTengo una pregunta: si tuviésemos varias tablas en la base de datos (por ejemplo: empresas, facturas, albaranes,etc) ¿tendríamos que hacer una clase controlador para cada tabla, o solo se implementa todo en una única clase controlador?
¿y con la clase lógica, habría varias también (logicaEmpresa, LogicaPersonas, LogicaFacturas,...(incluso puede ver condiciones que tengan relacionadas varias tablas (LogicaEmpresaProveedor)), o se mete todo en una única clase lógica?
¿como sería la forma según el modelo-vista-controlador? ¿depende de cada caso?
Hola Julio, te respondo:
ResponderEliminarSi tienes varias tablas, lo ideal es utilizar los patrones VO y DAO donde cada tabla representa un VO (Con los Atributos correspondientes a los campos) y un DAO (Correspondiente a las operaciones que se pueden hacer sobre la tabla por lo regular un CRUD) por ejemplo EmpresaVo, EmpresaDao, FacturaVo, FacturaDao... el Controlador no giraría en torno a las tablas sino mas como a la organización del sistema, por lo tanto seria independiente y podrías hacer uno solo, aunque dependiendo del tamaño de la aplicación de puedes apoyar en los controladores que desees, por ejemplo yo en un proyecto utilicé un controlador principal para que manejara todas las clases de la lógica y otro controlador que manejaba todos los llamados a interfaces graficas....
Con respecto a la lógica, funciona de forma similar, la lógica solo establece las reglas de negocio y como el sistema las va a atacar, tu puedes hacer cuantas clases de lógica sean necesarias, pero ten en cuenta que cuando son procesos relacionados con la BD lo ideal es usar los DAO, en la lógica se establecería los llamados a los métodos que vas a utilizar y en los DAO la implementación.
En ultimas el patrón es muy flexible, pero lo importante es saber aplicarlo, para que la lógica no se confunda con el controlador y el modelo....
Un poquito Larga pero espero que te sirva ;)
Ok, muchas gracias por la explicación, ahora lo entiendo un poco mejor.
ResponderEliminarGracias!!!
Con Gusto ;)
EliminarEn mi blog, he hecho un ejemplo igual que en el tuyo pero realizado en el lenguaje de programación Gambas3 (programación visual en gnu/linux), donde he intentado aplicar todo lo que nos has explicado sobre el MVC:
ResponderEliminarhttp://jsbsan.blogspot.com.es/2013/08/modelo-vista-controlador-mvc-ejemplos.html
Gracias!!
Este comentario ha sido eliminado por el autor.
EliminarJulio No me esperaba esto la verdad, muchas gracias, es gratificante saber que mi ejemplo te pudo servir ;)
EliminarAnte todo, GRACIAS x el ejemplo, me ha quitado muchas dudas.
ResponderEliminarSin embargo al ser estudiante, se me han creado otras tantas referentes al diagrama de clases y al proyecto de ejemplo (que he estudiado), si tienes unas lineas para contestar?, te lo agradecería.
X ejemplo tengo duda en la "VentaRegistro", creas directamente la "PersonaVO", ¿no sería necesario pasar los datos (no objeto) a "Coordinador" y de ahí a "Logica" para que sea esta última la que instancie "PersonaVO" dado que es la que en el diagrama de clases tiene la relación?.
Otra duda, x ejemplo en el diagrama también dibujas que es "Logica" la que tiene relación con "Conexion", sin embargo veo que es en "PersonaDAO" donde utilizas las conexiones ... ¿?
Quiero aprenderlo bien, ¿si me puedes ayudar?, gracias.
Hola Valentin, antes de responderte te agradezco por el interés que demuestras y porque veo que hiciste un muy buen análisis al ejercicio.
EliminarAhora si, te respondo en geral.... la verdad es que para estos ejercicios no me enfoqué mucho en los diagramas de clases, en otra entrada recuerdo haber puesto un comentario advirtiendo que el modelo era mas como para representar la idea, mas no era el diagrama de clases como tal, por ende no me fijé mucho en las relaciones ni los componentes ajustándome al estándar UML (Como debería de ser), simplemente quise generalizar mostrando de forma gráfica las agrupaciones, pero me hiciste caer en cuenta que pude generar un poquito de ambigüedad al no aclarar eso.
Basado en lo anterior y dejando a un lado el diagrama de clases, con respecto a PersonaVO, si ves la entrada sobre Patrones de Diseño (http://codejavu.blogspot.com/2013/06/que-son-los-patrones-de-diseno.html) el VO nos sirve bastante para el transporte de Datos, si pasáramos los datos directamente a la clase Coordinador, tendríamos que enviar n cantidad de parametros y tener uno o varios métodos que reciben la misma cantidad de datos, si nos toca hacer un control de cambios anexando otros datos, la modificación se tendría que hacer no solo en cada envió sino en cada método que recibe, por tal razón enviando todo en un objeto hace mas fácil mantener nuestro código....
Con respecto a PersonaDAO y la relación con Conexion, tienes toda la razón, no se porque lo asocie ahí, que pena por eso y en cuanto pueda actualizo la imagen ;).
Amigo muchas gracias, todo explicado perfectamente.
ResponderEliminarMuchas gracias a ti por tu comentario, me alegra que te gustara ;)
EliminarEspectacular!!
ResponderEliminarMuchas Gracias ;)
EliminarExcelente , muy bien explicado ! gracias
ResponderEliminarCon Gusto ;)
Eliminarde mucha ayuda!! gracias.
ResponderEliminarCon Mucho Gusto, gracias por el comentario ;)
EliminarDe nuevo te felicito, creo que eres el primero en explicar con un ejemplo como funciona el patrón mvc con bases de datos.
ResponderEliminarSigue así :)
Pepe muchas gracias por el comentario, esa es la idea, que los post puedan servir, y como dicen aqui, al que le gusta repite dos veces ;)
EliminarJOptionPane.showMessageDialog(null,"El documento de la persona debe" +
ResponderEliminar" ser mas de 3 digitos","Advertencia",JOptionPane.WARNING_MESSAGE);
Eso que tu pones en el modelo no seria correcto no?, porque en el modelo no puedes mostrar nada porque no sabes con que vista se va a mostrar, si es linea de comandos, ventanas, movil u otras ventanas.
Al igual que :
if (conn!=null){
System.out.println("Conección a base de datos "+bd+" OK");
}
Eso estaría mal no? El modelo tiene que lanzar una excepción que la controlaría el controlador y notificaría a la vista que tiene que mostrar una ventana o un System.out.println.
Por que si lo quieres hacer independiente lo primero que habría que hacer no seria depender de una plataforma o vista, en este ejemplo el modelo depende de que tiene que ser en ventanas por el Joption...
Hola, gracias por tu aporte, y tienes razon, lo ideal es como tu mencionas, sin animos de excusarme esos detalles se me pasaron talvez por los afanes o por ser detalles pequeños, me alegra que comentaras porque eso me hace mejorar cada vez mas ;) Un saludo y Gracias por comentar.
EliminarHola,
EliminarSi es un error utilizar el JOptionPane.showMessageDialog dentro de la Clase Logica, entonces como va implementado..... si en la validacion es nulo como hago para que aparezca el error con un JOptionPane.showMessageDialog ??
Espero me ayuden con el mismo ejemplo pero corregido .. Gracias de antemano..
Gracias. :D
ResponderEliminarCon Gusto Daniel ;)
EliminarBuena explicación, pero me gustaría si conoces algun manual con ejemplos y esas cosas sobre la creacion de interfaz en java con la Clase Swing. Para la creacion de botones, campos de texto y eso. Si conocieras uno bueno y me lo dijeras me ayudaría mucho. Un coordial saludo.
ResponderEliminarHola, gracias por comentar, te cuento que llevo una secuencia de java Swing que te puede servir, te comparto 2 de los ejemplos:
EliminarComponentes Simples:
http://codejavu.blogspot.com/2013/09/componentes-atomicos-java-swing.html
Componentes de Texto:
http://codejavu.blogspot.com/2013/09/componentes-de-texto-java-swing.html
Gracias por tu ejemplo, es de mucha utilidad, quisiera saber si tienes algun ejemplo usando siempre el patron MVC pero con conexion a Microsoft Sql Server, De antemano muchas gracias por tu respuesta.
ResponderEliminarHola, solo tengo este ejemplo del MVC con MySql, sin embargo la conexion es basicamente de la misma forma, solo cambiaria el conector, lamento no poderte colaborar... un saludo ;)
EliminarSaludos desde Honduras y gracias por tus aportes!
ResponderEliminarGracias Caballero, te regreso el Saludo desde Colombia..... Gracias a ti por comentar ;)
EliminarIncreíble el post, muy completo y bien explicado :) Aquí dejo un ejemplo orientado a web en vez de a aplicaciones de escritorio, por si a alguien le interesa... http://trendfinder.comyr.com/wordpress/?p=713 Saludos!
ResponderEliminarFlautista, Gracias por tu aporte un saludo
EliminarHola amigo, buen trabajo.
ResponderEliminarMe preguntaba si tienes algun ejemplo mas completo.
Mi correo es: car_19.91@hotmail.com
Tengo q buscar en mis archivos, cualquier cosa te contaré, un saludo ;)
EliminarHola, muy interesante tu ejemplo y muchas gracias por compartir tu conocimiento.
ResponderEliminarTengo una pregunta y quisiera saber si me puedes ayudar, Necesito crear un templeate para aplicaciones de escritorio. Es dicir, Crear un solo frame que tenga varios componentes Jtbutton, Jlabel, JtextField, etc, etc. Y de esos componentes hacer uso en los frame que se van a heredar del frame principal.
Quedo atento a tus respuesta.
Gracias
Hola, podrias trabajar con Paneles para simular el proceso del Template, ocultando o mostrando lo que necesites usando para eso diferentes clases, dentro de poco espero subir un ejemplo similar al que pides, talvez te sirva...un saludo ;)
EliminarCristian, Muchas gracias por tu pronta respuesta, que excelente labor que haces........ Quedo atento a tus comentarios y soluciones.
EliminarAmigo, estoy esperando el ejemplo que quedastes de subir jejejjejee estoy super atento.
EliminarGracias por el articulo muy bueno
ResponderEliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarExcelente este articulo, me despejo de muchas dudas, me podría ayudar con un ejemplo mas completo para continuar analizando MVC en profundidad.
ResponderEliminarCorreo: robinson_paguay@hotmail.es
Gracias.
Hola Robinson, voy a buscar haber si encuentro uno que tenia, si algo te comento
EliminarGracias, excelente ejemplo esta muy didáctico.
ResponderEliminar:-)
Con Gusto!!!
EliminarMuy ilustrativo, muchas gracias
ResponderEliminarCon gusto, me alegra que te sirviera ;)
EliminarHola, mirando el codigo veo que creas una personaVO en las ventanas.
ResponderEliminarNo estas agregando logica en la vista ????
Hola, voy a revisar.... aunque muchas veces los VO los podemos usar solo para crear el objeto a transportar así que en ese caso no sería tan critico, sin embargo tienes razón, se podría definir un método para realizar ese proceso en otra clase.... gracias por comentar ;)
EliminarExcelente articulo me ayudo mucho a entender un el MVC.
ResponderEliminarHola, me alegra que te sirviera, gracias por comentar ;)
EliminarMuy bueno...
ResponderEliminarGracias (Y)
Eliminarjeje gracias CHENAO (Y)
ResponderEliminarGracias Cesar ;)
EliminarPara cuando uno del DAO?, creo que es un patrón bastante importante
ResponderEliminarHola, tienes razón, mira en esta entrada sobre la conexión de Java con Mysql utilizó el patrón http://kcy.me/126nz
EliminarRealmente didáctico tu tutorial y excelentes los aportes mejorandolo de los que lo siguen.
ResponderEliminarRedFinal
Gracias por comentar ;)
Eliminarmuy bueno amigo
ResponderEliminarGracias Richard ;)
EliminarHola, muy buen tutorial. No consigo descargar el código desde la pagina que indicas, le doy al botón de descargar y no hace nada. ¿Que puede pasar?. Gracias
ResponderEliminarHola, ya lo subí nuevamente, algo paso en la otra plataforma que no permitia la descarga pero ya esta listo ;) Gracias por avisarme ;)
EliminarHola Cristian Henao:
ResponderEliminarNo se puedes descargar el archivo...
Sds...
Hola, ya lo subí nuevamente, algo paso en la otra plataforma que no permitia la descarga pero ya esta listo ;)
EliminarGenial Bro muy bueno 10 puntos. Ahora ya entiendo bastante mejor lo de mvc. Ahora solo me queda practicar lo en una aplicación.
ResponderEliminarHola, si esa es la idea, me alegra que te sirviera ;)
EliminarExcelente tu explicación. Gracias por tu aporte a la comunidad :D
ResponderEliminarHola, con gusto ;)
EliminarUna pregunta como sacas la vista de puros folders uno dentro de otro (model -> conexion -> Clase) esa vista como árbol . Porque a mi solo me salen las de paquetes. y no puedo sacar esa vista T_T. Gracias de Antemano
ResponderEliminarHola en eclipse desde la opción windows/Show View seleccionas la vista que quieras, si es navigator o explorador de paquetes y listo ;)
EliminarEstimado Cristian,
ResponderEliminarHe leido tu post y la verdad que esta muy bueno.
Hay dos cosas que respetando el patron MVC estan mal.
La primera que en VentaRegistro creas un objeto PersonaVo. Las ventanas no tienen logica.
La segunda dentro la logica no se comunica con la vista, estaria mal la parte de "JOptionPane.showMessageDialog"
Saludos!
Hola, si tienes razón, en un comentario anterior me comentaron el mismo error, planeo modificarlo solo que no he tenido el tiempo suficiente para hacerlo, muchas gracias.
EliminarEste comentario ha sido eliminado por el autor.
EliminarHola,
EliminarSi es un error utilizr el JOptionPane.showMessageDialog dentro de la Clase Logica, entonces como va implementado..si en la validacion es nulo como hago para que aparezca el error en un JOptionPane.showMessageDialog ??
Espero me ayuden con el mismo ejemplo pero corregido .. Gracias de antemano..
Hola, puedes hacerlo en un if con una comparacion de si es == null por ejemplo o si es !=null
EliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarMuy buen post! Es justo lo que andaba buscando.
ResponderEliminarHola namesde, me alegra que te sirviera, gracias por comentar.
Eliminarmuy buen articulo
ResponderEliminarGracias ;)
EliminarMira que ando programando en C# y aunque no he tenido clases de programación en mucho tiempo, me sirvió muchísimo leer esto para poder darme una idea del modelo, lo cual me llevó a escribir las clases necesarias en un proyecto de pruebas y luego llevarlas a cosas más grandes sin ningún problema. Muchísimas gracias por el trabajo, muy bien explicado, así como otros que he leído aquí y que también me llevaron a solucionar mis dudas aunque fueran lenguajes diferentes :D
ResponderEliminarHola wkats, me alegra leer eso, esto es lo bueno de la programación, los conceptos pueden ser aplicados a muchos lenguajes, un saludo.
EliminarMuy buen post me aclaro muchas dudas :D
ResponderEliminarGracias, me alegra que te sirviera
EliminarMuy bueno gracias por el aporte!
ResponderEliminarCon gusto!!!
EliminarHola,
ResponderEliminarPrimero: Quiero felicitarte y darte las gracias por el foro, el esfuezo y dedicación que haces, al poner un poquito de tu tiempo para compartir tus conocimientos a los demas atraves de este portal, esta todo muy bien explicado y ayuda a muchos.
Segundo: Me parece que todavia no hasta tenido tiempo de arreglar el ejemplo, como mencionaron en los comentarios en algunas vistas se estan creando objetos dentro de ellas, y segun lo que yo entendi el controlador es el enlace entre la visto y el modelo, por ende es donde deberia ir toda la codificacion a lo referente de la logica del negocio, creacion objetos, etc. Corrigeme si me equiboco.
Tercero: Me sugrio una duda, supeniendo que yo tengo tres (3) tablas de una base de datos cualquiera, que podrian ser a modo de ejemplo: perro, raza, dueño, donde muchos perro tiene una raza y una raza muchos perros, y supongamos que un perro pueden tener muchos dueños y un dueño puede tener muchos perros, para lo cual se necesitaria una tabla detalle perros/dueño, como deberia de ser el VO y sobre todo el DAO a la hora de mostrar los datos, dado que a la hora de mostrar perro, se debe mostrar la raza del perro y no la id, y los mismo para el nombre del dueño. ¿Deberia de hacer una consulta especial en el controlador o empalear otro forma de hacerlo? normalmente haria una consulta como la siguiente para mostrar todos los perros y sus razas"select idPerro, nombreP, raza, from Perro, Raza; Tengo tiempo sin programar y puede que alla cometido algun error en la consulta, en cuanto para mostrar todos los perro que tiene un dueño puede que la haria en dos consultas separadas, no pongo algun ejemplo pero que no me llega nada a la mente en este momento, y me parece irrelevante, en cuanto al codigo, se tendria PerroVo, PerroDao, RazaVo, RazaDao, ¿cual seria la forma obtima para unir ambas tablas y donde deberia de hacerse?.
Espero haberme dado a entender bien, en caso contrario me lo dices y trato de formular mejor mi duda.
------------ ----------- ------------ -----------------
|Perro | |Raza | |Dueño | |perroDueño|
------------ ----------- ------------ ------------------
|idPerro | |idRaza | |idDueño | |idPerro |
|nombreP| |raza | |nombreD| |idDueño |
|idRaza | ------------ ------------- -----------------
|idDueño |
-------------
Hey hermano tu blog es uno de los mejores que he visto, no pares de redactar articulos muy buenos!
ResponderEliminarMuy bueno Felicidades uno de los mejores blogs, muy bien explicado me sirvió bastante.
ResponderEliminarHola, gracias por la explicación, me parecen excelentes porque me amplían mucho el panorama pero a su vez también me confundo un poco.
ResponderEliminarHe estado viendo este tutorial donde explican sobre el patrón de arquitectura de software MVC: https://www.youtube.com/watch?v=IywnWQTqSh0 y también hacen un ejemplo para hacer un CRUD:
https://www.youtube.com/watch?v=AUcibt-cf4E y estoy tratando de sacar una conclusión entre lo que tú explicas en tu blog y lo que explican en el videotutorial.
Ando recién buscando, investigando y practicando sobre el patrón MVC en Java y pude hacer un pequeño programita aplicando lo que he aprendido recientemente pero ahora que leí tu blog tengo algunas dudas porque he visto que tú incorporas algunas clases adicionales que yo no sabía que también se usaban. Entre las conclusiones que había llegado al investigar sobre el MVC están que yo tenía pensado que si en una base de datos teníamos 10 tablas, entonces en nuestro componente modelo necesitábamos crear 20 clases: 10 clases DAO y 10 clases VO. Creo que hasta allí concuerda con lo que mencionas en tu blog. Luego, tenía entendido que por cada vista (JFrame, JDialog, JInternalFrame, etc) tenía que crear un controlador. Por ejemplo, si tuviera 15 vistas, entonces para cada vista necesitaría declarar 15 controladores, uno para manejar cada vista.
En tu blog he visto que utilizas una clase Lógica y otra clase llamada Coordinador y eso me confunde un poco porque creo que es la primera vez que oigo acerca de dichas clases.
Por ejemplo, en una aplicación que cuenta con una base de datos que contiene solo una tabla llamada "alumnos", yo utilizo dentro dentro de mi componente "modelo" dos clases por dicha tabla:
Componente MODELO:
-Alumno.java (// Esta sería el AlumnoVO.java)
http://ideone.com/IEKnEc
-AlumnoDAO.java
http://ideone.com/IutpBS
También una clase que realice la conexión con la base de datos
- Conexión.java
http://ideone.com/pBRNsJ
A parte, para el componente vista, solo utilizo una JFrame en donde se va a poder registrar y borrar un Alumno
Componente VISTA:
- JFAlumno.java
http://ideone.com/SckbUj
Y como intermediario entre dicha vista y los datos, utilizo una clase Controlador:
Componente CONTROLADOR:
- ControladorAlumno
http://ideone.com/ObTwx6
De esa forma pensé que se implementaba el patrón MVC pero en tu blog como te dije, veo que incluyes las clases "Lógica" y "Coordinador" y creo que eso me confunde un poco. Si es que tuvieras el tiempo de revisar mi código te estaría muy agradecido porque no estoy seguro si mi manera de usar el MVC está bien o tal vez estoy haciendo cualquier otra cosa menos MVC. Gracias :)
VistA: http://oi61.tinypic.com/2i7kztx.jpg
EliminarOye amigo tienes algun avance de la clase logica y coordinador. Te lo agradeceria
EliminarEste comentario ha sido eliminado por el autor.
EliminarTengo la misma duda The Oliztik en la clase lógica.
EliminarPudiste comprender como va implementado en el MVC la clase lógica espero me ayudes con un ejemplo ..??
El resto concuerdo contigo en que se crea un controlador por cada vista..
Hola, Gracias por comentar, les cuento que basicamente lo que se debe tener muy presente es el concepto del MVC, asumo que ya lo saben pero es identificar que debe ir en que categoria por asi decirlo, en el Modelo debe estar toda la logica, en la Vista todo lo que tenga que ver con interfaz grafica (en ocasiones por el afan se me van JOption en el Modelo, aunque es algo que no afecta tanto deberia gestionarse desde las vista) y el controlador esas clases encargadas de relacionar las anteriores.... en cuanto a la clase logica si ven la imagen la estoy gestionando como parte del modelo, ya que en mi logica de programacion quise crear dicha clase para validar cosas antes de hacer el llamado a los DAO, se llama logica pero puede llamarse como quiera, simplemente es una clase que me ayuda en mi negocio (la logica del sistema), segun la teoria no deberiamos hacer logica de negocio en los dao y los vo por eso yo hago eso desde otra clase, para asi hacer el llamado a los dao que se encargaran de gestionar mi BD.
EliminarSupongamos que vamos a hacer una calculadora, en las vistas van las interfaces donde se encuentran los campos para ingresar los numeros, en el modelo va la clase logica que para mi seria donde hago las operaciones matematicas y cuando tengo los resultados los envio al DAO para el registro a la BD y la clase coordinador que se encarga de recibir los datos para pasarselos a la logica y luego posteriormente enviarselos a las interfaces graficas....
les comparto esta secuencia de videos donde aplico el MVC, tal vez aclare un poco mas.
https://www.youtube.com/playlist?list=PLAg6Lv5Bbjjc91pwodQr8oXYPAjasIZ_M
Hola quiero felicitarte por este gran aporte. Gracias por compartir tu conocimiento.
ResponderEliminarMuchas Gracias Roberto
EliminarMuy bueno pero como se comportaria si fueran dos tablas relacionadas. Por poner un ejemplo persona y ventas
ResponderEliminarPodrias usar una vista que se encargue de gestionar esa info y la vista tener su DAO y en dicho dao mezclar lo necesario de las 2 tablas.
EliminarComo lo puedo ejecutar en visual studio 2012?
ResponderEliminarEsta muy bien explicado pero porf avor podría realizar este mismo modelo pero ahora con servlets y jsp
ResponderEliminarMe salvaste la vida gracias !!! :D
ResponderEliminarCon gusto
Eliminargracias me a servido de mucho
ResponderEliminarMuy buena explicacion. Gracias me ha servido tu ayuda
ResponderEliminarAlguien podria pasarme el codigo, no me funciona el link de mega, gracias!!!
ResponderEliminarQue buena explicación, tengo unas dudas sobre estos temas.
ResponderEliminar1. Los VO o DTO hacen un mapeo de cada tabla en la BD con sus respectivos campos según entiendo, en las tablas que contiene campos autoincrementales (generados automáticamente por la BD) como iría el metodo de la clase VO. Se omite en el método y se crea un constructor sin este campo ?
2. Los DAO tienen el ¿que Hacer? Y los VO el ¿como lo hacen ? Cierto ?. Esto quiere decir que todas las consultas adicionales sobre la BD deben ir aquí?. Como puedo manejar consultas extras como para llenar tablas o combobox sin romper las reglas del patrón
Si manejo view para mostrar al usuario final en la aplicación debo manejarlas aquí?. ¿ esto no rompería la idea del patrón ??
3. La clase coordinador hace el papel del FACADE ?.
Una vez más gracias por las explicaciones
Muy bueno el aporte!!
ResponderEliminarIng. Cristian estoy intentando hacer el mismo ejemplo pero en la interfaz estoy utilizando el dise;ador grafico de NetBeans y no se como utilizar la clase controlador, se me complica mucho, quisiera si es posible me diera una guia de como puedo hacerlo. gracias
Muy buen aporte¿, excelente (y)
ResponderEliminarGracias Cristian por tu tutoriql, muy bien detallado.
ResponderEliminarSaludos
Thierry
Mil gracias! Es el mejor artículo que he conseguido sobre el tema :)
ResponderEliminarMuy buen contenido y no se diga la explicación en tus vídeos, gracias por compartir tu conocimento Cristian
ResponderEliminarMuchas gracias.
ResponderEliminarEstaba buscando un ejemplo bien explicado del MVC y el tuyo ha sido el mejor. Muy claro y mejor estructurado.
Estoy aprendiendo a programar con Java. Tus explicaciones son excelentes y me estan sirviendo de mucha ayuda.
ResponderEliminarMuchas gracias.
Muchas gracias! Excelente artículo.
ResponderEliminarSaludos!
como seria con mas de un controlador?
ResponderEliminargracias
Muchísimas gracias por este blog, tu dedicación y tu profesionalismo. Llevo tiempo tratando de comprender este patrón de diseño y hasta ahora no podía terminar de identificar cuales eran las clase que debían intervenir en cada una de las partes del esquema.
ResponderEliminarSolo me resta una última consulta. Estoy haciendo un programa sencillo, que tiene por objeto más que nada el poder aplicar este patrón para poder integrarlo a mi saber.
Resulta que la GUI tiene varios botones y varios eventos de pérdidas de foco. Seria aconsejable que hiciera una clase por cada tipo de evento que deseo administrar con el controlador, o me conviene implementar todas las interfaces de evento en una misma clase controladora?
Hola, depende de lo que vas a hacer, podrias usar diferentes controladores o uno solo, pero mas que todo depende de que tan grande es tu aplicación.
EliminarQue buen ejemplo amigo, tengo una pregunta que no tiene que ver con el tema pero eso sobre una imagen que pusiste con todas las clases y paquetes del proyecto, y es ¿Como haces para que se vea un paquete dentro de otro paquete en Eclipse, ya que yo al tratar de crear un paquete dentro de otro queda asi modelo.dao por ejemplo?
ResponderEliminarHola, mira las vistas en eclipse, ahí seleccionas navigator...
EliminarMuy buena hermano , es agradable el trabajo que haces no dejes de hacerlo
ResponderEliminarMuchas Gracias!!!
EliminarEs 2017 y aun sirve demasiado este contenido, gente como tu debería haber mas en internet. Gracias, idolo!
ResponderEliminarMuchas Gracias!!!
EliminarMuy bueno, entendible y práctico, me servirá de mucho con mis prácticas de desarrollo de aplicaciones en la escuela. Muchas gracias, compartiré el artículo con el resto de mis compañeros.
ResponderEliminarSaludos!
muchas gracias profesor excelente explicacion Dios lo bendiga por sus aportes son muy pocos los que explican claro y directo.
ResponderEliminarMuchas gracias por la excelente explicación, tengo una duda especifica: ¿cual es la utilidad de los set y get entre las clases vistas y el coordinador? ¿porque es necesario pasar esas instancias por parametro si ya se cuenta con una en la misma clase? por ejemplo la clase coordinador ya cuenta con una instancia de VentanaPrincipal y luego en el metodo es seteada con otra instancia de VentanaPrincipal, espero haber sido claro sobre mi consulta, nuevamente gracias por el aporte
ResponderEliminarBrillante mi amigo Te felicito por las explicaciones y por el deseo que otros aprendan.
ResponderEliminarGracias por esa buena explicacion y el ejemplo que compartes, me a ayudado a entender un poco más sobre el tema de MVC.
ResponderEliminarMe gustaria hacerte una pregunta:
Como harías para llamar no un Jframe sino un JDialog (dentro de un HFrame padre) o un JInternalFrame (dentro de un contenedor) desde el evento del botón, y que este a su vez se comunique con el coordinador y todas las clases?
Es que e intentado hacerlo como lo explicas y no funciona. Agradezco de antemano tu ayuda. Muchas Gracias.
Gracias por tan buena explicacion de este tema!
ResponderEliminarMuchas dudas
ResponderEliminarse rifo xD
ResponderEliminarTengo dudas, demasiadas dudas
ResponderEliminarBuen aporte, aclara algunas dudas que tenía. Saludos
ResponderEliminarBuen aporte, me aclaró varias dudas!!!
ResponderEliminarme encanto, muchas gracias...
ResponderEliminarestare pendiente de tus publicaciones
Gracias muy util para entender el modelo
ResponderEliminarLo primero muchas gracias por el aporte. Planteo lo siguiente a ver que te parece, tenía dudas sobre como tratar la conexión a la base de datos. Veo que abres y cierras conexión cada vez vas a realizar alguna operación del CRUD. ¿no sería mejor abrir una conexión al ejecutar el programa por primera vez y cerrar la conexión al salir del programa?¿crees que ganamos en rendimiento?
ResponderEliminarMuchas gracias de nuevo y un saludo.
Gracias por compartir ya que las explicaciones que das a los temas son muy comprensibles y practicas.
ResponderEliminarSaldos
Muchas gracias por compartir tus conocimientos, me fue de mucha utilidad. Gracias, Gracias!
ResponderEliminar######################################################################################
ResponderEliminar# #
# ,.--------._ #
# / ''. #
# ,' \ |"\ /\ /\ #
# /"| / \ |__" ( \\ // ) #
# "_"| / z#####z \ // \ \\ // / #
# \\ ##### ##------". \// \_\\||||//_/ #
# \\/-----\ / ". \ \/ _ _ \ #
# \| \ | ,,--.. \ \/|(O)(O)| #
# | ,.--._ \ ( | ## \) \ \/ | | #
# |( ## )/ \ `-....-// |///////////////_\/ \ / #
# '--'." \ \ // |____| #
# /' / ) --. \ || / \ #
# ,..| \.________/ `-.. \ \ \| \ 0 0 / #
# _,##/ | ,/ / \ \ \ \ U / \_//_/ #
# :###.- | ,/ / \ /' ""\ .\ ( / #
# /####| | (.___________,---',/ | |\=._____| |_/ #
# /#####| | \__|__|__|__|_,/ |####\ | || #
# /######\ \ \__________/ /#####| \ || #
# /|#######`. `\ /#######\ | || #
# /++\#########\ \ _,' _/#########\ | || #
# /++++|#########| \ .---.. ,/ ,'##########.\|_|| Donkey By #
# //++++|#########\. \. ,-/ ,'########,+++++\\_\\ Hard'96 #
# /++++++|##########\. '._ _,/ ,'######,''++++++++\ #
# |+++++++|###########| -----." _'#######' +++++++++++\ #
# |+++++++|############\. \\ // /#######/++++ S@yaN +++\ #
# ________________________\\___//______________________________________ #
# / ____________________________________________________________________) #
# / / _ _ #
# | | | | | | #
# \ \ | | _ ____ ____ | | _ #
# \ \ | || \ / ___) / _ ) | | / ) #
# _____) ) | | | | | | ( __ / | |< ( #
# (______/ |_| |_| |_| \_____) |_| \_) #
# 19.08.02 #
######################################################################################
c,_.--.,y
ResponderEliminar7 a.a(
( ,_Y)
: '---;
___.'\. - (
.'"""S,._'--'_2..,_
| ':::::=::::: \
. f== ;-,---.' T
Y. r,-,_/_ |
|:\___.---' '---./
|'` )
\ ,
':;,.________.;L
/ '---------' |
| \
L---'-,--.-'--,-'
T / \ Y
| Y , |
| \ ( |
( ) \,_L
7-./ ) `,
snd / _( '._ \
'---' '--'
__.-._
ResponderEliminar'-._"7'
/'.-c
| /T
snd _)_/LI
buenas como implementaria las pestañas usando el modelo vista controlador?
ResponderEliminarurfa evden eve nakliyat
ResponderEliminarmalatya evden eve nakliyat
burdur evden eve nakliyat
kırıkkale evden eve nakliyat
kars evden eve nakliyat
HM7BLH
DC3BA
ResponderEliminarYobit Güvenilir mi
Samsun Lojistik
Maraş Şehir İçi Nakliyat
Sincan Boya Ustası
Tunceli Şehirler Arası Nakliyat
Silivri Evden Eve Nakliyat
Balıkesir Lojistik
Kastamonu Şehirler Arası Nakliyat
Iğdır Şehir İçi Nakliyat
7F827
ResponderEliminarAdana Evden Eve Nakliyat
Manisa Şehirler Arası Nakliyat
Bilecik Evden Eve Nakliyat
Ardahan Lojistik
Sakarya Evden Eve Nakliyat
Nevşehir Parça Eşya Taşıma
Kütahya Şehir İçi Nakliyat
Şırnak Şehirler Arası Nakliyat
Çerkezköy Bulaşık Makinesi Tamircisi
54E01
ResponderEliminarIsparta Şehir İçi Nakliyat
Kırşehir Parça Eşya Taşıma
Edirne Evden Eve Nakliyat
Karapürçek Boya Ustası
Aydın Şehir İçi Nakliyat
Bilecik Lojistik
Paribu Güvenilir mi
Muş Evden Eve Nakliyat
Isparta Evden Eve Nakliyat
D9F70
ResponderEliminarBinance Güvenilir mi
Çerkezköy Buzdolabı Tamircisi
Çerkezköy Bulaşık Makinesi Tamircisi
Denizli Evden Eve Nakliyat
Tekirdağ Boya Ustası
Trabzon Evden Eve Nakliyat
Maraş Evden Eve Nakliyat
Altındağ Boya Ustası
Muş Evden Eve Nakliyat
F60DD
ResponderEliminarIğdır Evden Eve Nakliyat
Sakarya Evden Eve Nakliyat
Çerkezköy Organizasyon
Bartın Şehir İçi Nakliyat
Etlik Boya Ustası
Isparta Parça Eşya Taşıma
Bingöl Evden Eve Nakliyat
Zonguldak Şehir İçi Nakliyat
Meta Coin Hangi Borsada
3C258
ResponderEliminarCoin Nasıl Kazılır
Bitcoin Kazma Siteleri
Kripto Para Kazma Siteleri
Binance Nasıl Üye Olunur
Madencilik Nedir
Binance Borsası Güvenilir mi
Kripto Para Madenciliği Nasıl Yapılır
Bitcoin Giriş Nasıl Yapılır
Coin Nedir
3BC71
ResponderEliminaramiclear
hola me sale error al momento de guardar datos en la ejecución, me podrias ayudar es para un deber
ResponderEliminarDE2C9
ResponderEliminarcanlı sohbet ücretsiz
poloniex
cointiger
huobi
çay ağacı sabunu
en eski kripto borsası
papatya sabunu
okex
kraken
5FA19
ResponderEliminarprobit
papaya meyvesi
bitcoin haram mı
okex
bitget
kaldıraç ne demek
en iyi kripto grupları telegram
kripto para kanalları telegram
en güvenilir kripto borsası
A514E
ResponderEliminarbingx
bitcoin nasıl üretilir
bitmex
bitexen
kredi kartı ile kripto para alma
okex
coinex
kripto para nasıl alınır
kripto para nereden alınır
1801F
ResponderEliminarMarch 2024 Calendar
October 2024 Calendar
probit
bybit
bitrue
kızlarla canlı sohbet
mexc
kucoin
kripto para telegram
2C2D4
ResponderEliminarmatadorbet
----
----
----
----
----
----
----
----