c# - tutorial - Comprender el patrón MVC
patron de diseño mvc c# (10)
Estoy teniendo problemas para entender el patrón MVC. Entiendo que intentemos desacoplar la GUI de la lógica comercial, aunque tengo problemas para entender cómo.
De lo que entendí, la View
, es lo que el usuario ve. Por lo general, es la ventana / forma. El Controller
está entre la View
y el Model
. El controlador hará que los datos "fluyan" en ambas direcciones. También se mantendrá en estado cuando sea necesario (si tengo un asistente con 5 pasos, es responsabilidad del Controller
asegurarse de que estén hechos en el orden correcto, etc.). El Model,
es donde vive el núcleo de mi lógica de aplicación.
¿Es esta vista correcta?
Para tratar de convertir esto en algo más significativo, trataré de esbozar un ejemplo simple con WinForms (¡no ASP.NET o WPF, por favor!) Para la multitud de Java, por lo que entiendo, Swing funciona de manera similar. camino a WinForms!), para ver si lo hago bien, y plantearé las preguntas que siempre hago cuando lo hago.
Supongamos que tengo un modelo que solo contiene una clase (solo para hacerlo más fácil. Sé que hará que el ejemplo parezca tonto, pero es más fácil de esta manera):
class MyNumbers {
private IList<int> listOfNumbers = new List<int> { 1, 3, 5, 7, 9 };
public IList<int> GetNumbers() {
return new ReadOnlyCollection<int>(listOfNumbers);
}
}
Ahora es el momento de hacer mi Controller
:
class Controller
{
private MyNumbers myNumbers = new MyNumbers();
public IList<int> GetNumbers() {
return myNumbers.GetNumbers();
}
}
La View
solo debe tener un ListBox
que tenga como elementos todos los números recuperados en MyNumbers
.
Ahora, surge la primera pregunta:
¿Debería el Controller
ser responsable de crear MyNumbers
? En este caso simple, creo que es aceptable (ya que MyNumbers
hará exactamente lo mismo, sin importar qué, y no tiene un estado asociado). Pero supongamos que quisiera usar para todos los diferentes controladores. Mi aplicación tiene la misma instancia de MyNumbers
. Tendría que pasarle a este Controller
(y a todos los demás que lo necesiten) esa instancia de MyNumbers
que quiero usar. ¿Quién será responsable de eso? En este ejemplo de WinForms, ¿sería esa la View
? ¿O esa sería la clase que crea la View
?
Pasando la pregunta: ¿cuál es el orden de instanciación de estas 3 partes? ¿Cuál es el código que el "propietario" del MVC
llamó para crearlo? ¿Debería el Controller
crear tanto la View
como el Model
? ¿Debería la View
instanciar el Controller
y el Controller
del Model
?
Segunda pregunta:
¿Cómo se supone que debe ser el método main
, suponiendo que solo quiero que mi aplicación tenga el Use Case
retrata este Controller
?
Tercero:
¿Por qué en el siguiente diagrama de MVC, la View
tiene una flecha hacia el Model
? ¿No debería el Controller
ser siempre el puente entre View
y Model
?
Tendré una o dos preguntas más, pero probablemente tendrán más sentido después de entender este primer detalle. O tal vez después de que entiendo esa primera pregunta todos los demás se separan.
¡Gracias!
¿Debería el controlador ser responsable de crear MyNumbers?
Yo diría '' definitivamente no ''.
Si el patrón MVC está diseñado para desacoplar los elementos M, V y C, ¿cómo puede funcionar esto si la C simplemente instancia la M con new MyNumbers()
?
En Java, usaríamos algo como Spring Framework aquí. Necesita una forma de expresar la relación de dependencia, o más bien los detalles de cómo se cumple, en un archivo de configuración u otro lugar adecuado ( es decir, no en código compilado).
Pero hay otro elemento en este tema: probablemente no deba definir la variable myNumbers
(dentro de C) con el tipo concreto de tiempo de ejecución que pretende utilizar. Use una interfaz o clase abstracta, y déjela abierta en cuanto a cuál es el tipo de tiempo de ejecución real. De esta forma, en el futuro puede volver a implementar la interfaz IMyNumbers para satisfacer los requisitos emergentes (los que no conoce hoy en día) y su componente C continuará funcionando a la perfección, de ninguna manera.
¿Por qué en el siguiente diagrama de MVC, la Vista tiene una flecha hacia el Modelo? ¿No debería el controlador ser siempre el puente entre View y Model?
Es el modelo MVC 2. Puede verlo generalmente en la aplicación empresarial Java donde CONTROL realiza el negocio y procesa los datos desde / hasta MODELO y elige qué VISTA devolver al cliente. Al renderizar al cliente, VIEW usará los datos de MODEL:
texto alternativo http://www.blogjava.net/images/blogjava_net/marco/7342/o_2.JPG
Aquí hay un ejemplo de cómo acceder a los datos de un archivo JSP (VIEW) que contiene un bean (MODEL):
class Person {String name;} // MODEL
My name is ${bean.name} // VIEW
"De lo que entendí, la Vista, es lo que ve el usuario. Por lo general, es la ventana / forma. El Controlador se encuentra entre la Vista y el Modelo. El Controlador manejará los datos en ambas direcciones. También persistirá en el estado. cuando sea necesario (si tengo un asistente con 5 pasos, es responsabilidad del Controlador asegurarse de que estén hechos en el orden correcto, etc.) El Modelo, es donde vive el núcleo de mi lógica de aplicación ".
Esto es casi correcto El controlador no persiste datos. Llama a un servicio que persiste en los datos. La razón es que los datos persistentes nunca son solo una llamada para guardar. Es posible que desee hacer comprobaciones de validación de los datos para asegurarse de que estén en orden según las necesidades de su negocio. Es posible que desee hacer alguna autenticación para asegurarse de que un usuario pueda guardar los datos. Si haces eso en un servicio, entonces tienes un buen conjunto de funcionalidades que puedes usar una y otra vez, por ejemplo para una aplicación web y un servicio web. Si lo hace en un controlador, digamos que para una aplicación web, cuando vaya a escribir su servicio web tendrá que refactorizar y / o duplicar el código.
En respuesta a su comentario "No estoy seguro de haber entendido totalmente su punto. ¿Controla el controlador la entrada de UI, o es el Modelo que lo hace?"
Su controlador solo debe controlar qué rutas de funcionalidad comercial se ejecutan. Eso es. Los controladores deben ser la parte más fácil del código para escribir. Puede hacer alguna validación en la interfaz gráfica (es decir, ver, por ejemplo, asegurarse de que las direcciones de correo electrónico estén formateadas correctamente, las entradas de texto no excedan los máximos), pero la capa empresarial también debe validar la entrada, por la razón que mencioné anteriormente, cuando comience a poner de pie más puntos finales, no tiene que refactorizar.
En cuanto a la crítica dentro de mi publicación, pensé que podría dar una publicación sobre cómo tiendo a crear un patrón MVC en PHP
Dentro de PHP, escupo el marco en varias secciones, algunas de las cuales son normales cuando se trata de MVC.
Primarias:
- Controlador
- Modelo
- Ver
Secondariness - ModelLayer
- ViewLoader
- Biblioteca
- ErrorLayer
Dentro del controlador, por lo general, permito que todos accedan a las capas secundarias y a la Vista y el Modelo desde la Primaria.
Así es como lo estructuraría
|---------| |------------| |------------|
| Browser | ----> | Controller | ----> | Model |
|---------| |------------| |------------|
| | | |
| | |----------------|
| |
| |------------|
-------------| View |
|------------|
En mi diagrama, normalmente evito la conexión del View <-> Model
y hago un View <-> Model
Controller <-> Model
y luego el enlace del Controller <-> View
asigna los datos.
Dentro de mi marco, tiendo a crear un sistema de almacenamiento de objetos para que pueda buscar objetos fácilmente y así sucesivamente. un ejemplo de mi almacenamiento de objetos es como
class Registry
{
static $storage = array();
public static function get($key)
{
return isset(self::storage[$key]) ? self::storage[$key] : null;
}
public static function set($key,$object)
{
self::"storage[$key] = $object;
}
}
Algo más avanzado por ese es el contorno, así que con esto cuando primero inicializo los objetos, los almaceno como Registry::set("View",new View());
para que siempre haya acceso.
Así que dentro de mi controlador que es el controlador base, creo varios métodos mágicos __get()
__set()
para que cualquier clase que amplíe el controlador pueda devolver fácilmente la solicitud, por ejemplo:
abstract class Controller
{
public function __get($key)
{
//check to make sure key is ok for item such as View,Library etc
return Registry::get($key); //Object / Null
}
}
Y el controlador de usuario
class Controller_index extends Controller
{
public function index()
{
$this->View->assign("key","value"); // Exucutes a method in the View class
}
}
El modelo también se colocará en el registro, pero solo se podrá llamar desde ModelLayer.
class Model_index extends ModelLayer_MySql
{
}
o
class Model_index extends ModelLayer_MySqli
{
}
o sistema de archivos
class Model_file extends ModelLayer_FileSystem
{
}
para que cada clase pueda ser específica para el tipo de almacenamiento.
Este no es el tipo tradicional de Patrón MVC, pero se puede llamar MVC Adoptivo.
Otros objetos, como View Loader, no se deben colocar en el registro, ya que no están específicamente destinados a los intereses de los usuarios, sino que los utilizan otras entidades, como View.
abstract class ViewLoader
{
function __construct($file,$data) //send the file and data
{
//Include the file and set the data to a local variable
}
public function MakeUri()
{
return Registry::get(''URITools'')->CreateURIByArgs(func_get_args());
}
}
como el archivo de plantilla se está incluyendo en el cargador de vistas y NO en la clase de vista, separa los métodos de usuario de los métodos del sistema y también permite que los métodos se utilicen dentro de las vistas para la lógica general.
Ejemplo de archivo de plantilla.
<html>
<body>
<?php $this->_include("another_tpl_file.php"); ?>
<?php if(isset($this->session->admin)):?>
<a href="<?php echo $this->MakeUri("user","admin","panel","id",$this->session->admin_uid) ?>"><?php echo $this->lang->admin->admin_link ?></a>
<?php endif; ?>
</body>
</html>
Espero que mis ejemplos te ayuden a entender un poco más.
Esto es de Java, pero con suerte lo ayudará.
Para el principal:
public static void main(String[] args)
{
MyNumbers myNums = new MyNumbers(); // Create your Model
// Create controller, send in Model reference.
Controller controller = new Controller(myNums);
}
Su controlador necesita una referencia a su modelo. En este caso, el controlador realmente crea todos los componentes de Swing. Para C #, es posible que desee dejar la inicialización del formulario aquí, pero la vista / formulario necesita una referencia al modelo (myNums) y al controlador (controlador). Con suerte, algunas personas C # pueden ayudar en este frente. La Vista también necesita registrarse como un Observador del Modelo (ver Patrón de Observer).
Aquí está el constructor que tengo (ajustado para su caso):
public NumberView(Controller controller, MyNumbers myNums)
{
this.controller = controller; // You''ll need a local variable for this
this.myNums = myNums; //You''ll need a local variable for this
myNums.registerObserver(this); // This is where it registers itself
}
La Vista pasa el trabajo al Controlador para manejar las acciones del usuario (botones, lo que sea). El controlador decide qué llamar / hacer en el modelo. En general, el Modelo hace algo y cambia su estado (tal vez más números en su lista. Lo que sea que haga). En ese momento, el Modelo informará a sus Observadores que ha cambiado y se actualizará. Luego, la vista se ejecuta y obtiene los nuevos datos y las actualizaciones. Es por eso que el modelo y la vista hablan (su tercera pregunta).
Entonces el Modelo tendrá:
public void notifyObservers()
{
for (Observer o: observers)
{
o.update(); // this will call the View update below since it is an Observer
}
}
Entonces, en la vista, tendrás algo como esto:
public void update()
{
setListBox(myNums.getNumbers()); // Or whatever form update you want
}
Espero que ayude. Sé que es Java, pero el concepto aún se aplica. Tendrás que leer un poco en el patrón Observer para obtenerlo por completo. ¡Buena suerte!
La forma más fácil de manejar MVC es usarlo en un marco que lo haga cumplir, eso dicho ...
- El Modelo interactúa con la fuente de datos (DB o lo que sea) y le da acceso a sus datos.
- La Vista interactúa con el mundo exterior, recibe información de algún lugar y entrega los datos al Controlador, también escucha al Controlador para asegurarse de que muestra los datos correctos.
- El controlador es donde sucede toda la magia; el Controlador manipula datos, empuja eventos y maneja cambios en ambas direcciones (hacia / desde la Vista y hacia / desde el Modelo).
Este diagrama es muy útil (tiene mucho más sentido que el de Wikipedia): MVC Diagram http://java.sun.com/developer/technicalArticles/javase/mvc/images/Figure4.gif
Source y un excelente artículo sobre MVC!
Trataré de responder a esto desde un punto de vista relativamente menos técnico sobre lo que vale. Trataré de recorrer un ejemplo general.
Controller
controla qué view
se usa. Entonces, por ejemplo, si está escribiendo en la página, el controller
lo dirigirá a la input view
(por ejemplo), mientras que si está leyendo la misma página, lo dirigirá a su success view
(por ejemplo).
Después de que uno escribe en la página, el controller
pasará esos parámetros al model
relevante donde reside la lógica que pertenece a lo que tiene que hacerse con ellos. Si hay un error, el controller
lo dirigirá a la error view
.
Mi conocimiento se basa en mi experiencia de un mes con Agavi. Espero que esto ayude.
Ver
interfaz de usuario / responsable con salida de entrada / alguna validación / necesita tener una forma de notificar al mundo exterior de los eventos de nivel de interfaz de usuario
sabe solo sobre el modelo
Modelo
- estructura de datos / representa los datos que se presentan / no deben contener la lógica de negocios (tal vez solo algunos datos / validación de estructuras como máximo)
- solo sabe de sí mismo (piense en una clase de Persona que solo tiene Nombre y Edad)
Controlador
es responsable de la lógica de negocio / agrupa Vistas y pega los respectivos modelos en ellas / tiene que poder responder a Ver eventos / accede a otras capas de la aplicación (persistencia / servicios externos / capas de negocios, etc.)
sabe todo (al menos Ver y modelo) y es responsable de pegar todo junto
Responda a la tercera pregunta :
Cuando el modelo cambia, notifica a la vista, luego la vista obtiene los datos del modelo utilizando sus captadores.
- Ver dibuja el modelo y lo representa para el usuario
- El controlador maneja la entrada del usuario y los traduce a las modificaciones en el modelo
- El modelo contiene la lógica de datos y modificación
No tiene sentido traducirlo en código. No lo obtendrás correctamente directamente de todos modos.