<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3703334709787879039</id><updated>2012-02-15T06:39:13.055-03:00</updated><category term='acoplamiento'/><category term='proxy'/><category term='principios de diseño'/><category term='MVC'/><category term='3 capas'/><category term='JAVA'/><category term='gof'/><category term='ActiveRecord'/><category term='patrones de persistencia'/><category term='NET'/><category term='desarrollo'/><category term='Mar del Plata'/><category term='Componentes software'/><category term='interfaces'/><category term='jornadas desarrollo de software'/><category term='objetos de negocio'/><category term='cohesion'/><category term='arquitectura'/><category term='composicion'/><category term='modelo de dominio'/><category term='delegacion'/><category term='web stateless'/><category term='ORM'/><category term='controladora'/><category term='2 capas'/><category term='DDD'/><category term='herencia'/><category term='sessionstate'/><category term='simple factory'/><category term='mapeo objeto relacional'/><category term='DAO'/><category term='patrones de diseño'/><category term='WebForms'/><category term='dependency injection'/><category term='marshaling'/><category term='decorador'/><category term='REST'/><category term='cookies'/><category term='modelo'/><category term='aop'/><category term='Ruby On Rails'/><category term='fabrica'/><category term='casos de uso'/><category term='abierto-cerrado'/><category term='code behind'/><category term='concerns'/><category term='application domains'/><category term='django'/><category term='modelo de negocio'/><category term='aspect'/><category term='aplicacion web'/><category term='estrategia'/><category term='managed code'/><category term='presentación'/><category term='responsabilidad'/><category term='NHibernate'/><category term='patrones'/><category term='asp.net'/><category term='factory method'/><category term='viewstate'/><category term='procesos de negocio'/><category term='framework'/><category term='spring.net'/><category term='3 tiers'/><category term='DataMapper'/><category term='vista'/><category term='Diseño OO'/><title type='text'>Arquitectura de Sistemas Informáticos</title><subtitle type='html'>Aqui tratamos todo lo relacionado a la arquitectura del soft. Esencialmente las técnicas de diseño OO, y la investigación de todo framework ó herramienta que nos ayude al desarrollo en alguna de sus etapas. Temas como : Model Driven Development, Test Driven Develop., Patrones, Principios de diseño, ORMs, serán bienvenidos.  
Patrones de diseño.  Diagramas y herramientas a utilizar en cada etapa de un ciclo de vida.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-8904454653750101553</id><published>2010-10-26T09:27:00.005-03:00</published><updated>2010-10-26T10:48:43.236-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='aplicacion web'/><category scheme='http://www.blogger.com/atom/ns#' term='arquitectura'/><title type='text'>Arquitectura del Django framework (parte 1)</title><content type='html'>En este post no voy a referirme a detalles de &lt;a href="http://docs.djangoproject.com/en/dev/intro/install/"&gt;instalación&lt;/a&gt; ni a un &lt;a href="http://docs.djangoproject.com/en/dev/intro/tutorial01/"&gt;&lt;span style="font-style: italic;"&gt;getting started&lt;/span&gt;&lt;/a&gt; con este producto.&lt;br /&gt;Django esta construido con &lt;a href="http://es.wikipedia.org/wiki/Python"&gt;Python&lt;/a&gt;, lenguaje OO, interpretado y con tipado dinámico (+ &lt;a href="http://es.wikipedia.org/wiki/Duck_typing"&gt;duck typing&lt;/a&gt;)&lt;br /&gt;En Django todo comienza creando un proyecto, este servirá de base para luego crear nuestra aplicaciones. Creamos un proyecto así:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;django-admin.py startproject mi_sitio&lt;/span&gt;            &lt;br /&gt;(&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 102, 102); font-style: italic;"&gt;django-admin.py&lt;/span&gt;&lt;/span&gt; &lt;span style="font-size:85%;"&gt;es un utilitario de comandos para tareas de administracion del django)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Esto genera una carpeta con los archivos de python que se muestran en la clase Project&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_iGJtoWG_NkY/TMbNFhxoNZI/AAAAAAAAATo/JUHGEmCwZlE/s1600/django-projects.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 364px; height: 86px;" src="http://3.bp.blogspot.com/_iGJtoWG_NkY/TMbNFhxoNZI/AAAAAAAAATo/JUHGEmCwZlE/s400/django-projects.JPG" alt="" id="BLOGGER_PHOTO_ID_5532334687120799122" border="0" /&gt;&lt;/a&gt;Como vemos, un Project posee 3 archivos python:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Settings.py, formado por un conjunto se variables donde se setean por ej.: los detalles de conexión con la/s base de datos, directorios de archivos media y templates, aplicaciones ó módulos instalados en el proyecto.&lt;/li&gt;&lt;li&gt;Urls.py, es como una tabla donde se mapean las urls de nuestro proyecto con las funciones que controlan la creación de nuestros templates html, de aquí en más &lt;span style="font-style: italic;"&gt;views&lt;/span&gt; de cada aplicación.&lt;/li&gt;&lt;li&gt;Manage.py, es un &lt;span style="font-style: italic;"&gt;wrapper&lt;/span&gt; del &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;django-admin.py&lt;/span&gt;&lt;/tt&gt; que realiza las sig. tareas antes de delegar el comando al &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;django-admin.py&lt;/span&gt;&lt;/tt&gt;: 1) pone el paquete del proyecto en el &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;sys.path&lt;/span&gt;&lt;/tt&gt;, y 2) setea la variable &lt;span class="target" id="index-0"&gt;&lt;/span&gt;&lt;tt class="xref std std-envvar docutils literal"&gt;&lt;span class="pre"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;/tt&gt; para que apunte al &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;settings.py&lt;/span&gt;&lt;/tt&gt; de su proyecto.&lt;/li&gt;&lt;/ul&gt;A continuación (&lt;span style="font-style: italic;"&gt;desde la carpeta del project...&lt;/span&gt;) creamos la aplicación '&lt;span style="font-style: italic; color: rgb(0, 0, 153);"&gt;conferencias&lt;/span&gt;' que será parte de ese proyecto (1 ó + aplicaciones):&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;python manage.py startapp conferencias&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Esto genera una nueva carpeta dependiente del proyecto, donde se crearán los archivos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;models.py, aquí crearemos las clases que  forman el modelo de esa aplicación, nuestros '&lt;span style="color: rgb(0, 0, 153);"&gt;business objects&lt;/span&gt;', por ej: &lt;span style="font-style: italic;"&gt;Conferencia, Oyente, Disertante, etc.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;views.py&lt;span style="font-style: italic;"&gt;, &lt;/span&gt;aquí van los métodos que contienen la lógica de negocio&lt;span style="font-style: italic;"&gt; &lt;/span&gt;que construirá la página, nuestras controladoras de Casos de uso. Cada una de estas funciones es llamada en Django : &lt;span style="font-style: italic;"&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;View&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; y está mapeada a una url (&lt;span style="font-style: italic;"&gt;no necesariamente todas...&lt;/span&gt;) del sitio web en el archivo urls.py del proyecto.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;** &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Tanto projects como applications tienen un archivo python que no fue descripto anteriormente:&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt; __init__.py&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt; &lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;este archivo es requerido por Python para tratar al directorio como un &lt;span style="font-weight: bold;"&gt;paquete&lt;/span&gt;, o sea un grupo de módulos (&lt;span style="font-style: italic;"&gt;cada archivo .py&lt;/span&gt;)&lt;span style="color: rgb(0, 0, 0);"&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ejecutando el localhost para probar nuestro sitio&lt;/span&gt;&lt;br /&gt;Django posee funcionalidad de web server para poder probar nuestras aplicaciones en un localhost, ejecutando el sig. comando desde la carpeta del proyecto:&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;python manage.py runserver&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;veremos en la consola que se validan los modelos (models.py de las aplicaciones) y luego nos muestra la versión de Django usada y que el server de desarrollo esta ejecutandose en http://127.0.0.1:8000/&lt;br /&gt;Si queremos que la aplicación que se está generando se vea en otros clientes de la red podremos especificar el nro. de ip de nuestra máquina (&lt;span style="font-style: italic;"&gt;y el puerto que deseemos&lt;/span&gt;) , por ej:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;python manage.py runserver 10.0.0.78:8000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Al probar en nuestro browser favorito veremos un mensaje de bienvenida de Django.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;/span&gt;&lt;/span&gt;Django es un framework web MVC, aunque ellos lo describan como &lt;a href="http://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names"&gt;MVT&lt;/a&gt; (model-View-Template), es un tema de conceptos que esta bien explicado por la gente de Django.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-8904454653750101553?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/8904454653750101553/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=8904454653750101553' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/8904454653750101553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/8904454653750101553'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2010/10/arquitectura-del-django-framework-parte.html' title='Arquitectura del Django framework (parte 1)'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_iGJtoWG_NkY/TMbNFhxoNZI/AAAAAAAAATo/JUHGEmCwZlE/s72-c/django-projects.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-4735121932798002748</id><published>2010-10-21T11:21:00.011-03:00</published><updated>2010-10-21T13:13:18.772-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='framework'/><title type='text'>Los Frameworks son nuestro silver bullet ?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_iGJtoWG_NkY/TMBcq8ZwrlI/AAAAAAAAATA/_Izrl783w-s/s1600/sw_400.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px; height: 180px;" src="http://2.bp.blogspot.com/_iGJtoWG_NkY/TMBcq8ZwrlI/AAAAAAAAATA/_Izrl783w-s/s200/sw_400.jpg" alt="" id="BLOGGER_PHOTO_ID_5530522235249405522" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Uno nace como programador de software&lt;/span&gt; aprendiendo un lenguaje determinado, luego otros, siempre desarrollando algoritmos que cumplan con la funcionalidad requerida del sistema.&lt;br /&gt;Como no queremos volver a escribir las mismas soluciones generamos nuestras librerías de codigo para reutilizarlo, con el diseño orientado a objetos lo hacemos todo más flexible creando clases abstractas e interfaces, usando patrones de diseño, inyectores de dependencia, etc y aplicando alguna arquitectura que nos permita &lt;span style="font-weight: bold;"&gt;convertir nuestra solución en un producto&lt;/span&gt;.&lt;br /&gt;Así cumplimos con nuestro objetivo de vivir de esta hermosa profesión, logrando vender nuestro software a diversos clientes con distintas variantes funcionales.&lt;br /&gt;Siempre uno busca ir programando menos y reutilizar más nuestros componentes y por supues&lt;a href="http://3.bp.blogspot.com/_iGJtoWG_NkY/TMBc6CD0iNI/AAAAAAAAATI/nSG2ALADORI/s1600/CorroPuzzle.gif"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 123px; height: 123px;" src="http://3.bp.blogspot.com/_iGJtoWG_NkY/TMBc6CD0iNI/AAAAAAAAATI/nSG2ALADORI/s200/CorroPuzzle.gif" alt="" id="BLOGGER_PHOTO_ID_5530522494466033874" border="0" /&gt;&lt;/a&gt;to los de otros programadores que nos ofrecen los suyos (pagos ó gratuitos), esta metodología de trabajo nos irá llevando a nuestro &lt;a href="http://en.wikipedia.org/wiki/No_Silver_Bullet"&gt;&lt;span style="color: rgb(204, 0, 0); font-weight: bold;"&gt;silver bullet&lt;/span&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;, y es la motivación principal de los creadores de &lt;span style="font-weight: bold;"&gt;FrameWorks&lt;/span&gt; (marcos de trabajo).&lt;br /&gt;Un &lt;a href="http://es.wikipedia.org/wiki/Framework"&gt;FrameWork&lt;/a&gt; es &lt;/span&gt;una estructura conceptual y tecnológica de soporte, definida normalmente con artefactos o módulos de software concretos, con base en la cual otro proyecto de software puede ser organizado y desarrollado.&lt;br /&gt;&lt;br /&gt;En mi experiencia como docente en la universidad, uno nota que muchos desarrolladores (&lt;span style="font-style: italic;"&gt;generalmente colegas&lt;/span&gt;) de mucha experiencia, no conciben la idea del desarrollo con estas herramientas basandose en la desconfianza que genera tener que aprender algo nuevo que no sabré si el año que viene seguirá existiendo, ya que generalmente estos FrameWorks son proyectos de libre disponibilidad y open source, y su existencia depende de la buena voluntad de la comunidad que los compone y mejora dia a dia.&lt;br /&gt;Si bien esta desconfianza es lógica, la proliferación de estas herramientas de desarrollo esencialmente en el ámbito web aplicando una arquitectura MVC , ampliamente consensuada y diría ya un standard para estos desarrollos, ha logrado que muchos programadores con conocimientos en diversos lenguajes de programación los utilice para lograr acercarse a su &lt;a href="http://en.wikipedia.org/wiki/No_Silver_Bullet"&gt;&lt;span style="color: rgb(153, 0, 0); font-weight: bold;"&gt;silver bullet&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_iGJtoWG_NkY/TMBd4TPE1YI/AAAAAAAAATY/wB3YUwt28QE/s1600/mvc-architecture.gif"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 172px;" src="http://4.bp.blogspot.com/_iGJtoWG_NkY/TMBd4TPE1YI/AAAAAAAAATY/wB3YUwt28QE/s200/mvc-architecture.gif" alt="" id="BLOGGER_PHOTO_ID_5530523564228531586" border="0" /&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Algunos buenos ejemplos de los mismos son para PHP: &lt;/span&gt;&lt;span style="visibility: visible;" id="main"&gt;&lt;span style="visibility: visible;" id="search"&gt;&lt;a href="http://codeigniter.com/"&gt;CodeIgniter&lt;/a&gt;, &lt;a href="http://www.symfony-project.org/"&gt;Symfony&lt;/a&gt; y &lt;a href="http://cakephp.org/"&gt;CakePHP&lt;/a&gt;; para ASP Net: &lt;a href="http://www.asp.net/mvc/whatisaspmvc"&gt;ASP Net MVC 2&lt;/a&gt; , para Python:&lt;a href="http://www.djangoproject.com/"&gt; Django&lt;/a&gt; , para Java : &lt;a href="http://java.sun.com/javaee/javaserverfaces/overview.html"&gt;JSF&lt;/a&gt; y &lt;a href="http://tapestry.apache.org/"&gt;Tapestry&lt;/a&gt; , para Ruby : &lt;a href="http://rubyonrails.org/"&gt;RubyOnRails&lt;/a&gt; , etc.&lt;br /&gt;Finalmente, todos los programadores que los usan no deben estar equivocados en su elección, particularmente me he convertido en un ferviente usuario de uno de ellos : &lt;/span&gt;&lt;/span&gt;&lt;span style="visibility: visible;" id="main"&gt;&lt;span style="visibility: visible;" id="search"&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.djangoproject.com/"&gt; Django&lt;/a&gt; &lt;span style="visibility: visible;" id="main"&gt;&lt;span style="visibility: visible;" id="search"&gt;,luego de haber investigado las características de varios de estos frameworks.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;En futuros posts iremos investigando las ventajas que nos brindan a través de mi experiencia de uso.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-4735121932798002748?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/4735121932798002748/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=4735121932798002748' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/4735121932798002748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/4735121932798002748'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2010/10/los-frameworks-son-nuestro-silver.html' title='Los Frameworks son nuestro silver bullet ?'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_iGJtoWG_NkY/TMBcq8ZwrlI/AAAAAAAAATA/_Izrl783w-s/s72-c/sw_400.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-6059200705672700903</id><published>2009-05-22T09:59:00.006-03:00</published><updated>2009-05-22T10:23:01.581-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cookies'/><category scheme='http://www.blogger.com/atom/ns#' term='viewstate'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='sessionstate'/><category scheme='http://www.blogger.com/atom/ns#' term='web stateless'/><title type='text'>Como soluciona Asp.Net el "stateLess" de la web</title><content type='html'>&lt;div&gt;&lt;div&gt;En un curso que dicto sobre AspNet, una pregunta recurrente es "&lt;span style="color:#990000;"&gt;&lt;em&gt;como maneja el lenguaje la falta de estado en el entorno web?&lt;/em&gt;&lt;/span&gt;".&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Digamos que en un programa Windows local, el usuario interactúa con una aplicación que está ejecutandose ininterrumpidamente, la cual almacena su información en una porción de la memoria del computador. En una aplicación Web esto no es así, si bien &lt;em&gt;un sitio desarrollado con ASP NET pueda verse como “ejecución ininterrumpida”, esto es solo una ilusión&lt;/em&gt;. &lt;/div&gt;&lt;br /&gt;&lt;div&gt;En un típico &lt;em&gt;Web Request&lt;/em&gt;, el cliente se conecta al Web Server y solicita una página, cuando ésta es enviada la conexión se cierra y el Web Server abandona cualquier información que posea del cliente. Por lo cual cuando el cliente recibe la página solicitada, la aplicación ya ha parado su ejecución. Por este motivo Asp Net nos dota con las siguientes posibilidades para manejar el almacenamiento de los datos (&lt;em&gt;mantener el estado&lt;/em&gt;):&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Tenemos 4 posibilidades, aquí las 2 primeras, ViewState y QuieryString&lt;/div&gt;&lt;img id="BLOGGER_PHOTO_ID_5338637425209968946" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 337px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_iGJtoWG_NkY/Shamc_I_CTI/AAAAAAAAASU/rLfW2zYyuXo/s400/viewstate+y+querystring.png" border="0" /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;Por último, cookies y session state:&lt;/div&gt;&lt;img id="BLOGGER_PHOTO_ID_5338637803184662322" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 286px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_iGJtoWG_NkY/Shamy_NLJzI/AAAAAAAAASc/-8wj9HQN50U/s400/cookie+y+session.png" border="0" /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-6059200705672700903?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/6059200705672700903/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=6059200705672700903' title='17 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/6059200705672700903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/6059200705672700903'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2009/05/como-soluciona-aspnet-el-stateless-de.html' title='Como soluciona Asp.Net el &quot;stateLess&quot; de la web'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_iGJtoWG_NkY/Shamc_I_CTI/AAAAAAAAASU/rLfW2zYyuXo/s72-c/viewstate+y+querystring.png' height='72' width='72'/><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-3126650571113078618</id><published>2009-05-19T11:54:00.010-03:00</published><updated>2009-05-19T15:23:48.426-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spring.net'/><category scheme='http://www.blogger.com/atom/ns#' term='dependency injection'/><category scheme='http://www.blogger.com/atom/ns#' term='aop'/><title type='text'>AOP y DI con Spring Net</title><content type='html'>Finalmente y despues de tantos meses, he vuelto al ruedo con mi Blog, y he visto que me he comprometido en mi anterior post a proveer de un ejemplo de AOP con Spring Net, &lt;a href="http://www.codeproject.com/KB/architecture/AOP_UsingSpringPart1.aspx"&gt;en este link &lt;/a&gt;tienen un ejemplo sencillo, donde se implementa un "Around Advice", lo cual implica poder ejecutar código antes y despues del llamado al método actual interceptado.&lt;br /&gt;&lt;br /&gt;Tambien les dejo un ejemplo de como realizar DI (dependency injection) :&lt;a href="http://1.bp.blogspot.com/_iGJtoWG_NkY/ShLwovQSuTI/AAAAAAAAARs/E7NK6dDsM1A/s1600-h/userService.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5337593091057695026" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 280px; CURSOR: hand; HEIGHT: 205px" alt="" src="http://1.bp.blogspot.com/_iGJtoWG_NkY/ShLwovQSuTI/AAAAAAAAARs/E7NK6dDsM1A/s400/userService.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;por ejemplo, tenemos una clase "&lt;em&gt;User&lt;/em&gt;" que tiene un servicio "&lt;em&gt;UserService&lt;/em&gt;", que a su vez tiene en su constructor un parametro que permitirá setear (inyectar...) el DAO con el que trabajará. (&lt;em&gt;si.., tambien podriamos haberlo hecho en una propiedad&lt;/em&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Luego, definimos en un archivo xml de config. (app.config o web.config) , donde se define un objeto "&lt;em&gt;userService&lt;/em&gt;" con un parámetro para su constructor ("&lt;em&gt;dao&lt;/em&gt;") , que será otro objeto llamado "&lt;em&gt;userDao&lt;/em&gt;".&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5337594706267499170" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 401px; CURSOR: hand; HEIGHT: 256px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_iGJtoWG_NkY/ShLyGwYUaqI/AAAAAAAAAR0/JDl30iJwmFU/s400/constructor-dao.jpg" border="0" /&gt;A continuación se muestra la definición del object id "&lt;em&gt;userDao&lt;/em&gt;", que como ven es de tipo SpringApp.Data.NHibernate, &lt;span style="color:#663366;"&gt;efectivamente Spring no reinventa la rueda y usa como ORM a NHibernate.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5337597397423234610" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 143px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_iGJtoWG_NkY/ShL0jZt2HjI/AAAAAAAAAR8/VlnbwyeWRqw/s400/userDao-object.jpg" border="0" /&gt;Este objeto llamado "&lt;em&gt;userDao&lt;/em&gt;" tiene una property llamada "&lt;em&gt;SessionFactory&lt;/em&gt;", que es la definida dentro de la config. de NHibernate dentro del mismo xml.&lt;br /&gt;&lt;br /&gt;Por último para crear un objeto "&lt;em&gt;userService&lt;/em&gt;" con el seteo hecho en el archivo xml (mi DI):&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5337599214761422962" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 41px; TEXT-ALIGN: center" alt="" src="http://3.bp.blogspot.com/_iGJtoWG_NkY/ShL2NL1CMHI/AAAAAAAAASE/m9wJlUPc4oY/s400/usoDI.jpg" border="0" /&gt;En la 1er. linea debo cargar el contexto de lo definido con Spring (IApplicationContext) y luego le pido a ese contexto que me dé un objeto cuyo id es "&lt;em&gt;userService&lt;/em&gt;".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-3126650571113078618?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/3126650571113078618/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=3126650571113078618' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/3126650571113078618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/3126650571113078618'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2009/05/aop-y-di-con-spring-net.html' title='AOP y DI con Spring Net'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_iGJtoWG_NkY/ShLwovQSuTI/AAAAAAAAARs/E7NK6dDsM1A/s72-c/userService.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-953016750137288256</id><published>2008-06-14T15:23:00.009-03:00</published><updated>2008-06-14T17:03:22.421-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spring.net'/><category scheme='http://www.blogger.com/atom/ns#' term='aspect'/><category scheme='http://www.blogger.com/atom/ns#' term='aop'/><category scheme='http://www.blogger.com/atom/ns#' term='concerns'/><title type='text'>AOP - Que es la prog. orientada a aspectos?</title><content type='html'>Orientar la programaciòn al uso de "aspectos", que extraño suena no?; tratemos de explicar su uso en la POO.&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;Definiciòn de AOP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Aspect_oriented_programming"&gt;Segùn Wikipedia &lt;/a&gt;: "&lt;/span&gt;&lt;span style="color:#993300;"&gt;intenta ayudar a los programadores en la separaciòn de incumbencias (&lt;em&gt;soc-separation of concerns&lt;/em&gt;), especificamente las incumbencias cruzadas (&lt;em&gt;cross-cutting concerns&lt;/em&gt;), como un avance en el uso de la modularizaciòn."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;En la POO la modularizaciòn implica el uso del encapsulamiento, ya sea a nivel de clases, paquetes, componentes, capas. Siempre buscamos asignar responsabilidades y aislarlas en su propio mòdulo funcional, logrando diseños de caja negra que nos permitan reusabilidad y fàcil mantenimiento.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Aunque, existen ciertas incumbencias ò àreas de interès (concerns) que son generales a varios mòdulos, por lo que, al incluìr esta funcionalidad en ellos, estarìamos repitiendo còdigo; el cual en caso de tener que modificarlo implicarìa hacerlo en todos los mòdulos que lo contengan. Por ejemplo: &lt;span style="color:#ff0000;"&gt;la seguridad, el "logging", el "debugging", sincronizaciòn y administraciòn de transacciones, cacheo&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Entonces existen caracterìsticas como las mencionadas que no son modularizables, son incumbencias que no pueden ser aisladas dentro de un solo mòdulo, ya que es su naturaleza estar distribuida su implementaciòn en varios mòdulos.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5211816414860822498" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/SFQXanpUR-I/AAAAAAAAALA/PdWCoDuoyq4/s400/aop-sin+y+con+aop.jpg" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;En este punto debe quedar claro que nuestro &lt;strong&gt;sistema &lt;/strong&gt;està formado por un cojunto de "concerns", donde algunos de ellos no pueden formar parte de un solo mòdulo, a estos los llamaremos "cross-cutting concerns".&lt;br /&gt;&lt;br /&gt;EL AOP esta diseñado para manejar estos "cross-cutting concerns", proveyèndonos de un mecanismo conocido como "Aspecto" (&lt;em&gt;aspect&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;Aspecto&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;"Modularizaciòn de un "concern", sin el cual deberìa implementarse a travès de mùltiples objetos con distintas responsabilidades."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;"Funcionalidad que se quiere aplicar a otras partes del còdigo (autorizaciones, logging, transacciones,...)"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;Como implemento AOP en .NET? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;Hay varios frameworks que permiten trabajar con AOP en .NET, entre ellos es de destacar &lt;a href="http://www.springframework.net/"&gt;Spring.NET&lt;/a&gt; que nos da esta funcionalidad con el uso de su componente &lt;a href="http://www.springframework.net/docs/1.1-RC1/reference/html/aop.html#aop-introduction-defn"&gt;Spring.AOP &lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Para comprender el funcionamiento de los Aspectos, debemos definir algunos conceptos AOP:&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5211826700283342370" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/SFQgxT1I7iI/AAAAAAAAALI/-sWJCY8fm6c/s400/aspect.jpg" border="0" /&gt;&lt;br /&gt;&lt;span style="color:#006600;"&gt;Advice : &lt;/span&gt;&lt;span style="color:#000000;"&gt;cada una de las cosas que puede hacer un Aspect&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#009900;"&gt;Join Point: &lt;/span&gt;&lt;span style="color:#000000;"&gt;Punto del programa en el que se ejecutarà un Advice&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#009900;"&gt;Point Cut: &lt;/span&gt;&lt;span style="color:#000000;"&gt;Conjunto de Join Points, un conj. de mètodos donde se ejecutarà un Aspect.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#009900;"&gt;Target: &lt;/span&gt;&lt;span style="color:#000000;"&gt;El objeto sobre el que se aplicarà el/los aspecto/s. Es el obj. que contiene el Join Point.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#009900;"&gt;Introduction: &lt;/span&gt;&lt;span style="color:#000000;"&gt;Manipular un Target para añadirle còdigo. Permite introducir nuevas interfaces a cualquier "obj. advised" (&lt;span style="color:#009900;"&gt;Target&lt;/span&gt;).  Por ej.: un obj. puede implementar "IAuditable" para simplificar el rastreo de cambios en su estado. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#33cc00;"&gt;&lt;span style="color:#006600;"&gt;Weaver:&lt;/span&gt; &lt;span style="color:#000000;"&gt;Caract.&lt;/span&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;de ensamblado &lt;/span&gt;&lt;span style="color:#000000;"&gt;para crear los "objs. advised". Puede ser hecho en tiempo de ejecuciòn (como Spring.Net) ò en tiempo de compilaciòn (usando el compilador &lt;a href="http://www.dcl.hpi.uni-potsdam.de/research/loom/"&gt;Gripper-Loom-Net&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Algunos tipos de &lt;span style="color:#006600;"&gt;Advice&lt;/span&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;&lt;em&gt;Before : Justo antes de un Join Point&lt;/em&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;After: Despuès de terminar un Join Point (haya o no excepciòn)&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Around: envuelve la ejecuciòn del Join Point, pudiendo ejecutar còd. antes y despues, incluso evitar su ejecuciòn.&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;En un pròximo post entrare en detalle sobre el uso de AOP de Spring con un ejemplo concreto.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-953016750137288256?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/953016750137288256/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=953016750137288256' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/953016750137288256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/953016750137288256'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/06/aop-que-es-la-prog-orientada-aspectos.html' title='AOP - Que es la prog. orientada a aspectos?'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_iGJtoWG_NkY/SFQXanpUR-I/AAAAAAAAALA/PdWCoDuoyq4/s72-c/aop-sin+y+con+aop.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-8267999409290602043</id><published>2008-05-11T11:38:00.013-03:00</published><updated>2008-05-18T23:36:10.371-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patrones de persistencia'/><category scheme='http://www.blogger.com/atom/ns#' term='DAO'/><category scheme='http://www.blogger.com/atom/ns#' term='Componentes software'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='objetos de negocio'/><category scheme='http://www.blogger.com/atom/ns#' term='DataMapper'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='modelo de negocio'/><category scheme='http://www.blogger.com/atom/ns#' term='procesos de negocio'/><title type='text'>Desarrollando Software con un Modelo de Negocio</title><content type='html'>Aquí les dejo la presentación que dicté en la UTN Mar del Plata, en el marco de las "&lt;em&gt;Jornadas sobre Desarrollo Software&lt;/em&gt;" (Mayo/08).&lt;br /&gt;La temática gira alrededor de los siguientes conceptos: Componentes software, Modelo de negocio (&lt;em&gt;Trans.Script y Domain Model&lt;/em&gt;) , Persistencia de objetos de neg. y acceso a datos con NHib. (&lt;em&gt;DataMapper y ActiveRecord&lt;/em&gt;), DAO.&lt;br /&gt;&lt;br /&gt;Cualquier problema con la visualización de la presentación pulsar en opción "View" de Slideshare.&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_398629" style="WIDTH: 425px; TEXT-ALIGN: left"&gt;&lt;br /&gt;&lt;embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=desarrollo-en-capas-con-net-1210513786895759-8" width="425" height="355" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 11px; PADDING-TOP: 2px; FONT-FAMILY: tahoma,arial; HEIGHT: 26px"&gt;&lt;a href="http://www.slideshare.net/?src=embed"&gt;&lt;img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; MARGIN-BOTTOM: -5px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" alt="SlideShare" src="http://static.slideshare.net/swf/logo_embd.png" /&gt;&lt;/a&gt; &lt;a title="View 'Desarrollo en Capas con .Net' on SlideShare" href="http://www.slideshare.net/jercoli/desarrollo-en-capas-con-net?src=embed"&gt;View&lt;/a&gt; &lt;a href="http://www.slideshare.net/upload?src=embed"&gt;Upload your own&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;La aplicación Web que demuestra estas tecnologías (&lt;em&gt; desarrollada con AspNet 2 y NHib&lt;/em&gt;.), se encuentra aquí : &lt;a href="http://www.freedrive.com/file/336565,capasconnet2.zip"&gt;ConferenciaWeb&lt;/a&gt;.&lt;br /&gt;Dentro del zip tienen una carpeta con las instrucciones para instalar y ejecutar; tener en cuenta que necesitan el VS 2005 y en lo posible SqlServer 2005, si necesitan probar con otra BD deben cambiar los drivers del NHibernate en el web.Config. Espero les sea de utilidad.&lt;br /&gt;&lt;br /&gt;Por ultimo les dejo el enlace a la filmaciòn del seminario que realizò la gente de TecnoTV de Canal 10 de MdP : &lt;a href="http://www.youtube.com/watch?v=RxHe_ZRAYuo"&gt;seminario de capas con NET&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-8267999409290602043?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/8267999409290602043/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=8267999409290602043' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/8267999409290602043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/8267999409290602043'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/05/desarrollando-un-software-con-un-modelo.html' title='Desarrollando Software con un Modelo de Negocio'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-6451880802563805592</id><published>2008-04-27T17:25:00.008-03:00</published><updated>2008-05-13T14:17:11.833-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jornadas desarrollo de software'/><category scheme='http://www.blogger.com/atom/ns#' term='NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Mar del Plata'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby On Rails'/><category scheme='http://www.blogger.com/atom/ns#' term='JAVA'/><title type='text'>Jornadas sobre Desarrollo de Software (MdP) - MAYO/08</title><content type='html'>Los dias sabados 10,24 y 31 de Mayo de 10 a 13.30 hs, se dictaràn 3 seminarios orientados a desarrolladores de software : .NET+NHibernate, RubyOnRails y Java con EJB-Struts (reprog. del dia 17/5) respectivamente.&lt;br /&gt;&lt;br /&gt;Estas jornadas se haràn en el aula Magna del Centro de Estudios Mar del Plata de la UTN.&lt;br /&gt;Para ampliar sobre las mismas ver &lt;a href="http://www.youtube.com/watch?v=oCuCmtyAeRA"&gt;la entrevista que me efectuaron en el programa Mercados &amp;amp; Empresas&lt;/a&gt; de Canal 10 del cable de MdP.&lt;br /&gt;&lt;br /&gt;Cualquier interesado de la zona (estudiante o profesional) con conocimientos en POO puede inscribirse gratuitamente en el sitio de la UTN: &lt;a href="http://www.mdp.utn.edu.ar/"&gt;http://www.mdp.utn.edu.ar/&lt;/a&gt; (ver folleto)&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5194025542470798562" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 299px; CURSOR: hand; HEIGHT: 431px; TEXT-ALIGN: center" height="416" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/SBTitjVHDOI/AAAAAAAAAKg/1T3E2TEjsQU/s400/FolletoJornadasDesarrolloUTN.jpg" width="286" border="0" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-6451880802563805592?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/6451880802563805592/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=6451880802563805592' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/6451880802563805592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/6451880802563805592'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/04/jornadas-sobre-desarrollo-de-software.html' title='Jornadas sobre Desarrollo de Software (MdP) - MAYO/08'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_iGJtoWG_NkY/SBTitjVHDOI/AAAAAAAAAKg/1T3E2TEjsQU/s72-c/FolletoJornadasDesarrolloUTN.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-4193428663027539787</id><published>2008-04-05T20:10:00.009-03:00</published><updated>2008-04-05T20:40:08.033-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='marshaling'/><category scheme='http://www.blogger.com/atom/ns#' term='managed code'/><category scheme='http://www.blogger.com/atom/ns#' term='application domains'/><category scheme='http://www.blogger.com/atom/ns#' term='proxy'/><title type='text'>Dominios de aplicaciòn en .NET (App Domains)</title><content type='html'>&lt;a href="http://bp0.blogger.com/_iGJtoWG_NkY/R_gLJn7s6MI/AAAAAAAAAKQ/tSAEJpHuOLk/s1600-h/fig3-app+domain.png"&gt;&lt;/a&gt;Todos sabemos que .NET ejecuta &lt;strong&gt;còdigo administrado&lt;/strong&gt; a travès de&lt;strong&gt; Dominios de aplicaciòn&lt;/strong&gt;, pero conceptualmente no son muchos los desarrolladores .Net que comprenden en profundidad esta arquitectura y sus implicancias.&lt;br /&gt;Por este motivo he decidido compilar un capìtulo interesante del libro "&lt;a href="http://www.amazon.com/Programming-NET-Components-Juval-Lowy/dp/0596102070"&gt;Programming .Net Components 2nd. Ed.&lt;/a&gt;" que trata sobre este tema.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="color:#000099;"&gt;Còdigo administrado en .NET y dominios de aplicación&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Todas las aplicaciones y componentes .NET requieren de un ambiente administrado para ejecutarse. Para esto .NET utiliza un “Dominio de Aplicación” (Application Domain), que permite la ejecución de còdigo administrado de parte de los “Ensamblados” (Assemblies).&lt;br /&gt;&lt;/span&gt;El “Dominio de Aplicación” serìa el equivalente en .NET al concepto de Proceso del S.O., con una gran diferencia: dentro de un proceso fìsico del S.O. pueden hostearse mùltiples de estos “Application Domains” . Podrìamos entonces considerarlos como “procesos lògicos” dentro de un proceso real del S.O.&lt;br /&gt;( &lt;em&gt;figura 1)&lt;/em&gt; &lt;img id="BLOGGER_PHOTO_ID_5185907016134879394" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R_gK9H7s6KI/AAAAAAAAAKA/K4XMTXZ2h6A/s400/fig1-app+domain.png" border="0" /&gt;&lt;br /&gt;Esta arquitectura de “&lt;strong&gt;Application Domains&lt;/strong&gt;” posee grandes ventajas con respecto a la tradicional de poseer cada aplicación(exe) y c/u de sus componentes(dlls) dentro de su propio y exclusivo proceso. Los procesos tradicionales son denominados en .NET como “còdigo no administrado”.&lt;br /&gt;&lt;p&gt;&lt;em&gt;Algunas desventajas de esta arq. de multiples procesos son:&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Crear y Destruir un proceso del S.O. consume mucho tiempo.&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Mantener un proceso en ejecución es costoso en tèrminos de memoria y de los recursos que el S.O. debe ubicar en ellos.&lt;/em&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Realizar llamadas entre procesos resulta en penalidades de tiempo, ya que cruzar los lìmites de un proceso es mucho màs costoso que realizar un llamado directo dentro del mismo. Esto es porque se necesitan mecanismos especiales para efectuar los llamados inter-proceso (por ej.: pipes, sockets, LPC/RPC) . &lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;El còdigo en los procesos clientes se vuelve complejo para realizar llamados a otros procesos y obviamente difiere de los llamados internos. &lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;em&gt;Venta&lt;/em&gt;&lt;em&gt;jas de los “Application Domains”:&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Baja sobrecarga en el S.O. por permitir que mùltiples “procesos lògicos” se hosteen en el mismo proceso real que administra el S.O. &lt;/em&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Los tiempos que requiere Crear o destruir un “App.Domain”, y mantenerlo en ejecución con sus recursos asignados, es una fracciòn del requerido por un proceso fìsico. &lt;/em&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Los llamados entre “App. Domains” que estàn dentro del proceso fìsico son mucho màs ràpidos que los llamados entre diferentes procesos del S.O. &lt;/em&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;.NET mantiene un lìmite de seguridad estricto entre “App.Domains”, por lo cual los objs. del “App.Domain A” no pueden interferir con los objetos del “App.Domain B”; a menos que estos objs. decidan cooperar usando .Net Remoting.&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Es importante destacar que para mantener las 2 grandes ventajas de la arq. tradicional de “mùltiples procesos”: “&lt;strong&gt;Aislamiento ante fallas&lt;/strong&gt;” y “&lt;strong&gt;Seguridad&lt;/strong&gt;”, cada “App.Domain” carga y mantiene su propio juego de Assemblies. En la figura 1 , la librerìa de clases llamada “Assembly 1” se carga 2 veces, una en cada App.Domain (B y C), los cuales poseen su propia copia independiente.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="color:#000099;"&gt;La plataforma .NET y los “App. Domains”&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;El RunTime de .Net es un juego de Windows DLLs, implementadas en còdigo no administrado con C++; estas proveen : administración del Heap, recolector de basura (GC), compilador JIT (JustInTime), Cargador y adm. de assemblies, y otras herramientas que hacen posible el “còdigo administrado”.&lt;br /&gt;El “App.Domain” habilita a los Assemblies que carga, a acceder a estos servicios del RunTime .Net. &lt;span style="color:#cc0000;"&gt;Por este motivo se dice que los App.Domains son el puente que une el Mundo de còd. administrado con el Mundo de còd. no administrado.&lt;br /&gt;&lt;/span&gt;( &lt;em&gt;figura 2)&lt;/em&gt; &lt;img id="BLOGGER_PHOTO_ID_5185907140688930994" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R_gLEX7s6LI/AAAAAAAAAKI/wwyi9O9M6Ks/s400/fig2-app+domain.png" border="0" /&gt;&lt;br /&gt;Es importante notar en la figura 2 que todos los App.Domain del mismo proceso comparten el mismo “administrador de Heap”.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="color:#000099;"&gt;Threads (Hilos) y App.Domains&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;Los Threads en .Net no son afines a los App.Domains, esto implica que un thread puede entrar y salir en cualquier Dominio que se ejecute en el mismo proceso subyacente. Por lo tanto nada previene que un Thread creado en un App Domain acceda a los objs. de otro App Domain en el mismo proceso.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="color:#000099;"&gt;App Domains y Remoting&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;.Net usa la misma arq. de llamados Remotos entre App Domains para:&lt;br /&gt;· &lt;em&gt;2 App Domains en el mismo proceso&lt;br /&gt;· 2 App Domains en 2 procesos distintos del S.O.&lt;br /&gt;· 2 App Domains en 2 màquinas fìsicas distintas.&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;(&lt;em&gt;figura 3&lt;/em&gt;) &lt;img id="BLOGGER_PHOTO_ID_5185908961755064530" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R_gMuX7s6NI/AAAAAAAAAKY/7cdUosWghT8/s400/fig3-app+domain.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Los clientes que estàn en el mismo App.Domain del obj. llamado pueden tener una referencia directa al obj. En cambio los clientes que estàn en diferentes App.Domains usan un &lt;strong&gt;Proxy&lt;/strong&gt; para conectarse al objeto.&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Un Proxy es un obj. que provee exactamente las mismas interfaces, mètodos pùblicos, propiedades y miembros que el obj. real, aunque el Proxy no puede servir al cliente debido a que el còdigo del objeto llamado y su estado residen donde el obj. estè.&lt;br /&gt;&lt;/span&gt;Todos los proxys saben como ligarse al obj. y enviarle los llamados hechos por el cliente, esta operación es denominada “&lt;strong&gt;marshaling&lt;/strong&gt;”.&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;El marshaling cumple con el objetivo de darle al cliente la ilusiòn de que està llamando a un objeto local y darle al servidor la ilusiòn de que està sirviendo a un cliente local&lt;/span&gt;. Ni cliente, ni servidor usan mecanismos remotos (pipes, RPC, sockets), debido a que estos detalles estàn encapsulados en el Proxy.&lt;br /&gt;.Net requiere que si un obj. es accedido por un Proxy, la clase del obj. debe derivar de la clase abstracta “&lt;strong&gt;MarshallByRefObject&lt;/strong&gt;”.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-4193428663027539787?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/4193428663027539787/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=4193428663027539787' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/4193428663027539787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/4193428663027539787'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/04/dominios-de-aplicacin-en-net-app.html' title='Dominios de aplicaciòn en .NET (App Domains)'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_iGJtoWG_NkY/R_gK9H7s6KI/AAAAAAAAAKA/K4XMTXZ2h6A/s72-c/fig1-app+domain.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-6599871273856169251</id><published>2008-02-28T09:03:00.014-02:00</published><updated>2008-03-05T23:22:53.777-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patrones de persistencia'/><category scheme='http://www.blogger.com/atom/ns#' term='DDD'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='DataMapper'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='modelo de dominio'/><category scheme='http://www.blogger.com/atom/ns#' term='ORM'/><title type='text'>Estrategias para persistir objetos : ActiveRecord vs DataMapper</title><content type='html'>&lt;span style="font-size:130%;"&gt;&lt;span style="color:#990000;"&gt;Persistencia&lt;/span&gt;&lt;span style="color:#cc0000;"&gt; : procedimiento que es ejecutado para lograr que los datos sobrevivan a la ejecución de un determinado programa. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Porque es necesario el uso de frameworks ORM (&lt;em&gt;&lt;span style="font-size:85%;"&gt;object relational mapping&lt;/span&gt;&lt;/em&gt;) para crear una capa de persistencia que acceda a los datos de nuestra aplicación?, si esta pregunta no tiene respuesta para ti, es aconsejable que vayas &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/10/que-es-un-orm-object-relational-mapping.html"&gt;aquí&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Si en .Net tengo AdoNet 2.0, que me da la posibilidad de comunicarme con la BD, permitiendome recuperar los datos y copiarlos a un DataSet local, ligarlos a mis controles en la IU, y luego persistir los cambios, via SqlCommands ó DataAdapters que realizan las operaciones CRUD de Insert,Update, Select y Delete; no puedo generar una capa de persistencia con esta tecnología?.&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Por supuesto que SI&lt;/span&gt;&lt;span style="color:#000000;"&gt;, y esta fue la apuesta de la gente de Microsoft hasta la version 2.0 de NET; seguir desarrollando software donde mis &lt;span style="color:#990000;"&gt;entidades de negocio&lt;/span&gt; son directamente las filas de las tablas de una BDR (&lt;em&gt;&lt;span style="font-size:85%;"&gt;Base de datos relacional&lt;/span&gt;&lt;/em&gt;). Para esto MS ha desarrollado una artillería de controles (datagrids, combobox, listviews, etc) drag and drop con wizards que facilitan enormemente la programación ligando mis entidades de negocio con mis IU (Win y WebForms). Lamentablemente este tipo de tecnología implica comenzar cada aplicación de software como si se tratase de la 1ra que realizamos, osea : casi nula reutilización de código aunque rapidez en el desarrollo y testeo. &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;Esto ha permitido que miles de personas puedan estar "capacitadas?" como programadores con un curso intensivo de 3 meses; los cuales sólo podrán seguir desarrollando con las tecnologías MS del tipo "WizarDragAndDropHappyProgramming" salvo que logren ver "más allá" y comiencen a investigar como funcionan los frameworks de desarrollo (&lt;a href="http://struts.apache.org/"&gt;Struts de Java&lt;/a&gt;, &lt;a href="http://www.rubyonrails.org/"&gt;RubyOnRails&lt;/a&gt;, &lt;a href="http://www.cakephp.org/"&gt;CakePhp&lt;/a&gt;) que triunfan en la actualidad y que implican mayor conocimiento de programación y arquitecturas de software, especialmente en aplicaciones Web donde ha triunfado largamente el uso del patrón de &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/11/introduccin-los-frameworks-mvc.html"&gt;arquitectura MVC&lt;/a&gt;, no es casualidad que en la nueva versión 3.5 de NET se haya desarrollado un &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/11/el-futuro-mvc-de-asp-net.html"&gt;framework que aplique esta arquitectura &lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hablabamos de reutilización, la cual es imposible sin un diseño previo que tenga en cuenta los patrones de arquitectura, donde el &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/05/diseo-en-3-capas-fisicas-lgicas-es.html"&gt;3 capas lógicas &lt;/a&gt;es el punto por donde comenzar; donde ubicar la persistencia?, pues en la capa de acceso a datos. Ahora si lo que queremos es trabajar con "objetos de negocio" (&lt;span style="font-size:85%;"&gt;business objects ó BOs&lt;/span&gt;) en las otras 2 capas superiores y no con los DataSets como "entidades de negocio" que representan a las filas de una determinada tabla, deberemos usar algún framework ORM para que haga de intermediario entre los campos de las tablas relacionadas y nuestros objetos de negocios que responden a un Modelo del dominio.&lt;br /&gt;&lt;br /&gt;Estos objetos de negocio deben representar el mayor esfuerzo de diseño en el desarrollo de un software (la M de Modelo en un MVC), si lo que deseamos es aplicar un enfoque DDD (Domain Driven Design).&lt;br /&gt;DDD propone que el aspecto más complejo en los proyectos de software no es la implementación, sino el dominio del mundo real al cual el software le da servicio. Lograr que el objetivo principal del proyecto sea el modelo del negocio y mantener un modelo de software que refleje una profunda comprensión del mismo. Esta visión fue desarrollada por &lt;em&gt;Eric Evans&lt;/em&gt; en su libro "&lt;a href="http://www.domaindrivendesign.org/books/index.html"&gt;Domain Driven Design&lt;/a&gt;".&lt;br /&gt;Volviendo a la persistencia, podría NO utilizar ningún fwk y codificar mi propias clases ORM?, por supuesto, aunque si desarrollas con .NET ya existen varias posibilidades open source que son excelentes, entre las cuales son de destacar &lt;a href="http://www.hibernate.org/343.html"&gt;NHibernate&lt;/a&gt; y &lt;a href="http://www.castleproject.org/activerecord/index.html"&gt;ActiveRecord de Castle&lt;/a&gt;; que aplican 2 patrones de persistencia distintos que son el motivo de este post.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5172024860925806466" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 406px; CURSOR: hand; HEIGHT: 135px; TEXT-ALIGN: center" height="161" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R8a5NVz4x4I/AAAAAAAAAIo/Qxq5EDNJNaA/s400/persistence-ar+vs+dm.jpg" width="430" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#cc0000;"&gt;Active Record&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Propone tener &lt;strong&gt;los métodos que me brindan la persistencia en el mismo objeto de negocio&lt;/strong&gt;, y normalmente &lt;strong&gt;las instrucciones del mapeo atributo del objeto-campo de la tabla en la definición del objeto de negocio&lt;/strong&gt;. Por ej. en el ActiveRecord de Castle:&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5172065237913356178" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R8bd7lz4x5I/AAAAAAAAAIw/dnGCb3eFn0c/s400/activeRecordExample.png" border="0" /&gt;De esta forma podria crear un objeto Blog y persistirlo así:&lt;/p&gt;&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5172069588715227042" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R8bh41z4x6I/AAAAAAAAAI4/8c3pp5rZwfI/s400/activeRecordExampleDeUso.png" border="0" /&gt;Como vemos el uso del motor de persistencia es muy natural y sencillo de usar. El único problema que se plantea es que, desde el pto. de vista de la &lt;strong&gt;separación de responsabilidades&lt;/strong&gt; de las capas; en este caso; estamos acoplando los BOs de la capa de negocios con la persistencia que debería estar en la capa de acceso a datos. &lt;em&gt;Porque esto no es bueno?,&lt;/em&gt; porque perdemos &lt;strong&gt;independencia&lt;/strong&gt; y será más costoso el cambio a otra tecnología de persistencia. &lt;/p&gt;&lt;p&gt;Esto es debido a que son nuestros objetos de negocio los que conocen como acceder a los datos persistidos mediante, en este caso, ActiveRecord de Castle; estos métodos de manejo de persistencia no deberían ser conocidos por nuestra capa de negocios, y suele decirse que estamos ensuciando nuestro código. Si a esto le sumamos las instrucciones de mapeo (&lt;span style="font-size:85%;"&gt;ej: [PrimaryKey]),&lt;/span&gt; nuestras clases que crearán los BOs dejarán de ser POCO (&lt;span style="font-size:85%;"&gt;plain old c# objects&lt;/span&gt;), y estarán influenciadas por cualquier cambio en la tecnología de acceso a datos subyacente.&lt;/p&gt;&lt;p&gt;Por último cabe aclarar que muchos de estos ActiveRecord, como por ejemplo el &lt;a href="http://www.blogger.com/www.mygenerationsoftware.com/dOOdads/dOOdads.aspx"&gt;DooDads&lt;/a&gt; (&lt;em&gt;cuyo código se crea desde MyGeneration&lt;/em&gt;), generan el modelo de clases a partir de las tablas y relaciones de la BDR ya creada, lo cual desde mi pto. de vista no es lo correcto, debido a que un modelo de clases es mucho más rico en posibilidad de asociaciones y navegabilidad que un esquema de tablas relacionadas.&lt;/p&gt;&lt;p&gt;&lt;span style="color:#cc0000;"&gt;Data Mapper&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Propone que nuestros objetos de negocio sean POCO (ó POJO en Java), o sea que no tengan nada de código que los acople a una tecnología dada de persistencia, ya que no es su función manejarla. Los objetos de negocio solo deben preocuparse de cumplir con el modelo del dominio vía diseño del diagrama de clases con las asociaciones pertinentes.&lt;/span&gt;&lt;/p&gt;&lt;img id="BLOGGER_PHOTO_ID_5172084509431613362" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R8bvdVz4x7I/AAAAAAAAAJA/_lpSkHnruUE/s400/dataMapper-ExamplePocoBO.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Este es el caso de NHibernate, que propone manejar la persistencia a través de una clase administradora de la misma: Session. Esta clase es la que se encarga de hacer las operaciones CRUD a la BDR. Por ej. para persistir nuestro objeto de tipo Salon:&lt;img id="BLOGGER_PHOTO_ID_5172088280412899266" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R8by41z4x8I/AAAAAAAAAJI/YFkuJARv-xs/s400/dataMapper-ExampleSession.png" border="0" /&gt;&lt;/p&gt;&lt;p&gt;Para ver un tutorial sencillo y completo sobre NHibernate ver este &lt;a href="http://darioquintana.com.ar/articles/tutorial-de-nhibernate-primeros-pasos"&gt;post de Dario Quintana&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;De esta forma todo lo que tenga que ver con el DataMapper (NHibernate) puede quedar aislado en su propia capa, fuera de la capa de negocio que posee nuestros BOs. Para poder realizar esta tarea en forma más transparente es necesaria la creación de clases DAO (data access objects) que implementen los métodos más comunes que realiza la capa de persistencia.&lt;br /&gt;Por ej: (DAO del Salon)&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5172164803845212114" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R8c4fFz4x9I/AAAAAAAAAJQ/FHOC4tdxQN4/s400/nhibernateDAO-ejemplo.png" border="0" /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Con los DAOs de cada BO trabajarìamos con el sig. còdigo en la implementaciòn de nuestros procesos:&lt;/p&gt;&lt;img id="BLOGGER_PHOTO_ID_5172168433092577250" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R8c7yVz4x-I/AAAAAAAAAJY/D_1Qi0628sI/s400/dao-ejemplo2.png" border="0" /&gt; &lt;p&gt;&lt;/p&gt;&lt;p&gt;Por supuesto que aprovechando Generics podriamos armar un &lt;em&gt;HibernateDAOAbstracto&lt;/em&gt; que realice todas las operaciones comunes de persistencia y de esta forma nuestros DAO especìficos de cada BO heredarìan de èste. Para màs informaciòn al respecto ver el excelente &lt;a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx"&gt;ejemplo de Billy McCafferty&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;&lt;span style="color:#cc0000;"&gt;En Resúmen...&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Esta visto que con NHibernate debemos codificar màs, aunque logramos mayor independencia para poder cambiar los DAOs que se implementan con NHibernate por otro que se implemente con Linq Sql por ejemplo. Tambien es importante destacar que NHibernate es un framework con muchisimas funcionalidades (manejos de transacciòn, lazy loadings, Queries tipo HQL, Criterias, interceptores, etc), esto ha hecho que en el caso del ActiveRecord de Castle, se haya implementado usando NHibernate como API base ("&lt;em&gt;&lt;span style="font-size:85%;"&gt;no reinventar la rueda", no?&lt;/span&gt;&lt;/em&gt;). &lt;/p&gt;&lt;p&gt;Desde el punto de vista teórico de los 2 patrones (&lt;a href="http://martinfowler.com/"&gt;&lt;span style="font-size:85%;"&gt;Martin Fowler.&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt; &lt;em&gt;Patterns of enterprise application architecture&lt;/em&gt; &lt;/span&gt;), el uso de un Data Mapper nos permite manejar toda la carga y almacenamiento entre el modelo de dominio y la base de datos, logrando que ambos varien independientemente. En el Active Record se mantiene una relacion de uno a uno entre clases y tablas, siendo más dificil la implementacion de modelos de negocio complejos.&lt;/p&gt;&lt;p&gt;Por último, el objetivo de este post no ha sido mostrar una tecnologìa de persistencia en particular, sino revisar los 2 patrones principales que se usan para implementarla y el porque de los beneficios de usarla en un diseño que se guie por un buen diagrama de clases del modelo de dominio de la aplicaciòn a desarrollar; en definitiva promover que los programadores dejemos de lado el uso directo de los registros de las BDR y usemos objetos de negocio en nuestros desarrollos, aprovechando una arquitectura que separa las responsabilidades y posibilite mayor reusabilidad y menor mantenimiento. &lt;/p&gt;&lt;p&gt;&lt;em&gt;Me gustaria que este post sirva para concentrar comentarios sobre el tema de persistencia, y que puedan brindar aqui sus experiencias y dudas en su uso. Nos leemos..&lt;br /&gt;&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-6599871273856169251?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/6599871273856169251/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=6599871273856169251' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/6599871273856169251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/6599871273856169251'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/02/estrategias-para-persistir-objetos.html' title='Estrategias para persistir objetos : ActiveRecord vs DataMapper'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_iGJtoWG_NkY/R8a5NVz4x4I/AAAAAAAAAIo/Qxq5EDNJNaA/s72-c/persistence-ar+vs+dm.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-4635888505632320562</id><published>2008-02-12T09:03:00.000-02:00</published><updated>2008-02-12T17:21:59.445-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patrones de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='fabrica'/><category scheme='http://www.blogger.com/atom/ns#' term='gof'/><category scheme='http://www.blogger.com/atom/ns#' term='simple factory'/><category scheme='http://www.blogger.com/atom/ns#' term='factory method'/><title type='text'>Fabricas (GoF) - Creando objetos sin "new" - Factory method</title><content type='html'>Este patrón define una interfaz para crear un objeto, y deja a las subclases decidir cual clase instanciar.&lt;img id="BLOGGER_PHOTO_ID_5166054456952407730" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R7GDKFz4xrI/AAAAAAAAAHA/NOYndYm9ZdQ/s320/Factory_Method_UML_class_diagram.png" border="0" /&gt;&lt;br /&gt;&lt;div&gt;&lt;strong&gt;&lt;span style="color:#cc0000;"&gt;Programar para las interfaces, NO para la implementación...&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;Que hay de malo en esta instrucción? : &lt;/span&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;Auto a= new Sedan();&lt;/span&gt;&lt;/em&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;Al usar &lt;strong&gt;new()&lt;/strong&gt; estamos instanciando de una clase concreta, por lo que estaremos programando contra la implementación. Es importante recordar que al &lt;em&gt;acoplar &lt;/em&gt;nuestro código a una clase concreta, obtenemos una programación menos flexible y más frágil; o sea con más mantenimiento (y dolor de cabeza incremental) en un futuro propenso al cambio.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;Ejemplifiquemos un modelo de nuestro auto:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5166063476383729346" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R7GLXFz4xsI/AAAAAAAAAHI/NMS9z2J6gqs/s320/factory-1.bmp" border="0" /&gt; Ante la creación de objetos de las subclases, es muy común que nuestro código se vea así:&lt;img id="BLOGGER_PHOTO_ID_5166067015436781266" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R7GOlFz4xtI/AAAAAAAAAHQ/AUBaz3m-tM0/s320/factory-codigoSinPatron.png" border="0" /&gt;Y si tuvieramos que agregar nuevos subtipos de auto, ó eliminar otros?? --&gt; &lt;strong&gt;Mayor mantenimiento y código propenso a errores !!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;Identificar los aspectos que varían y separarlos de nuestro código...&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Esto nos lleva a crear una nueva clase que llamaremos FabricaAutos que tendrá un método CrearAuto(int tipo) :&lt;/span&gt;&lt;/p&gt;&lt;img id="BLOGGER_PHOTO_ID_5166125968157886226" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R7HEMlz4xxI/AAAAAAAAAHw/pWWRMHB6Ygk/s400/factory-codigoConPatron-fabrica+simple.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://bp2.blogger.com/_iGJtoWG_NkY/R7HFJ1z4xyI/AAAAAAAAAH4/XJmWoouzi1k/s1600-h/factory+simple-clases-autos.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5166127020424873762" style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R7HFJ1z4xyI/AAAAAAAAAH4/XJmWoouzi1k/s320/factory+simple-clases-autos.png" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con este desarrollo llegamos a un tipo de fábrica que llamaremos "&lt;em&gt;Fábrica simple&lt;/em&gt; (simple factory), que si bien no es un patrón de diseño GoF, es una buena técnica creacional de objetos que nos acerca al siguiente patrón : &lt;strong&gt;Factory method&lt;/strong&gt;&lt;/p&gt;&lt;span style="color:#990000;"&gt;&lt;strong&gt;Nuestro modelo se complica...&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nuestro cliente de venta de autos (AutoShop) decide expander sus horizontes comerciales fuera de Argentina, específicamente a nuestro hermano pais de Brasil. &lt;img id="BLOGGER_PHOTO_ID_5166136383453579058" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R7HNq1z4xzI/AAAAAAAAAIA/JjZwbHIT_Us/s320/2fabricasdeautos.png" border="0" /&gt;Resulta que allí los tipos de modelos de auto difieren de los de nuestro pais; por ejemplo supongamos que los autos Rural poseen sólo 2 puertas en Brasil y 4 en Argentina, y las camionetas son doble cabina en Brasil y en Argentina no, etc, etc.&lt;br /&gt;Veamos algunos cambios en nuestro código, comencemos con nuestra clase AutoShop, que ahora será abstracta:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5166142997703214930" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R7HTr1z4x1I/AAAAAAAAAIQ/ht5thLcAvys/s400/factory+method-autoShop+cambiado.png" border="0" /&gt;                                   &lt;em&gt;(* &lt;strong&gt;protected&lt;/strong&gt; abstract Auto CrearAuto(...))&lt;/em&gt;&lt;/span&gt;&lt;em&gt; &lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Nuestro diagrama de clases con los AutoShops de cada pais:&lt;/span&gt;&lt;/p&gt;&lt;img id="BLOGGER_PHOTO_ID_5166147919735736162" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/R7HYKVz4x2I/AAAAAAAAAIY/O7gHo78mx_0/s400/factory+method-productosConcretos.png" border="0" /&gt;Como usamos este código para entregar un Auto Sedan de nuestro AutoShop de Argentina?&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5166151024997091186" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R7Ha_Fz4x3I/AAAAAAAAAIg/cRlDQJumyk0/s400/factorymethod-codigo+cliente-Main.png" border="0" /&gt; &lt;div&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color:#990000;"&gt;&lt;strong&gt;Simple Factory vs Factory Method&lt;/strong&gt;&lt;/span&gt; &lt;strong&gt;&lt;span style="color:#cc0000;"&gt;(GoF)&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;Simple factory decide e instancia, no tiene ninguna idea sobre que hacer con el objeto creado.&lt;/div&gt;&lt;div&gt;Factory method delega la creación de la instancia a las subclases, pero sabe que hacer con el objeto creado.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-4635888505632320562?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/4635888505632320562/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=4635888505632320562' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/4635888505632320562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/4635888505632320562'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/02/fabricas-gof-creando-objetos-sin-new.html' title='Fabricas (GoF) - Creando objetos sin &quot;new&quot; - Factory method'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_iGJtoWG_NkY/R7GDKFz4xrI/AAAAAAAAAHA/NOYndYm9ZdQ/s72-c/Factory_Method_UML_class_diagram.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-837534458269195762</id><published>2008-02-04T10:42:00.000-02:00</published><updated>2008-02-04T13:53:09.139-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patrones de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='gof'/><category scheme='http://www.blogger.com/atom/ns#' term='estrategia'/><title type='text'>Estrategia (GoF) - Encapsulemos los algoritmos que varíen</title><content type='html'>Definamos este útil patrón: &lt;span style="color:#000000;"&gt;"&lt;/span&gt;&lt;span style="color:#990000;"&gt;Define una familia de algoritmos, encapsula cada uno y los hace intercambiables. La Estrategia deja que el algoritmo varíe independientemente de los clientes que lo usen".&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;Su diagrama:&lt;/span&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5163143313860792658" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R6crfQsbEVI/AAAAAAAAAGw/GwuuF1bT_2Q/s320/strategy+gof.png" border="0" /&gt; &lt;div&gt;&lt;span style="color:#000000;"&gt;Vamos a nuestro ejemplo de uso, tenemos que modelar el comportamiento de un jugador de fútbol:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5163117952078909682" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/R6cUbAsbEPI/AAAAAAAAAGA/q5h2NThnAYY/s320/strategy-futbolista-1.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Luego de modelar esto, se nos pide agregar la función de &lt;em&gt;atajar , &lt;/em&gt;obviamente no para todos los subtipos, sólo el Arquero. Nuestra solución pasaría por agregar la subclase "&lt;em&gt;Arquero&lt;/em&gt;" y el método "&lt;em&gt;Atajar()&lt;/em&gt;" en mi clase &lt;em&gt;Futbolista.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ahora bien, le daríamos la posibilidad de atajar a todos los subtipos de futbolistas?, pues no, por lo que deberíamos también sobreescribir el método &lt;em&gt;Atajar()&lt;/em&gt; en los demás subtipos, poniendo algún mensaje como "función no disponible" ó retornando null.&lt;br /&gt;Y que pasaría si un futbolista "MedioCentral" decide defender en algún momento como DefensorLateral y atacar como Delantero??, difícil de solucionar con nuestro primer modelo, no?.&lt;br /&gt;&lt;strong&gt;&lt;span style="color:#990000;"&gt;Un poco de diseño OO...&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;La herencia nos trae varios problemas asociados a la extensibilidad y al mantenimiento del código de nuestro modelo.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Nuestro principio básico a recordar aquí es : &lt;span style="color:#990000;"&gt;&lt;strong&gt;Encapsular lo que varía&lt;/strong&gt;.&lt;/span&gt;&lt;span style="color:#000000;"&gt; Identifica los aspectos de tu aplicación que puedan variar y sepáralos del resto de tu código que no cambiará; de esta forma podremos alterar ó extender aquellas partes sin afectar al resto.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Todos los patrones de diseño aplican este concepto de una u otra forma, brindando un camino que nos permita variar una parte del sistema independientemente del resto.&lt;/p&gt;&lt;p&gt;&lt;span style="color:#660000;"&gt;&lt;strong&gt;Volvamos a nuestro futbolista...&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Separemos los comportamientos que varían, sacando los métodos : atajar, defender y atacar, de la clase Futbolista. Luego creamos un grupo de clases que representarán cada comportamiento:&lt;/span&gt;&lt;/p&gt;&lt;img id="BLOGGER_PHOTO_ID_5163130321584722194" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/R6cfrAsbERI/AAAAAAAAAGQ/LEHI7s7pAV4/s400/strategy-futbolista-2-interfaces.png" border="0" /&gt;En nuestra clase futbolista, defin&lt;a href="http://bp2.blogger.com/_iGJtoWG_NkY/R6ckKgsbETI/AAAAAAAAAGg/s4g2IYkXBjA/s1600-h/strategy-futbolista-3.png"&gt;&lt;/a&gt;imos el comportamiento via atributos del tipo de las interfaces definidas, y métodos de seteo (ó propiedades de escritura en C#) para poder configurar el comportamiento del futbolista en cualquier momento de la ejecución.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5163142661025763650" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R6cq5QsbEUI/AAAAAAAAAGo/Wp2KhAHNpos/s320/strategy-futbolista-3.png" border="0" /&gt;Por último hagamos un testing, generando un futbolista con cierto comportamiento :&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_iGJtoWG_NkY/R6cv9wsbEWI/AAAAAAAAAG4/sU5dpGUV8Z4/s1600-h/strategy-futbolista-codigoDeUso.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5163148235893313890" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R6cv9wsbEWI/AAAAAAAAAG4/sU5dpGUV8Z4/s400/strategy-futbolista-codigoDeUso.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#993399;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#993399;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div align="left"&gt;&lt;/div&gt;&lt;div align="left"&gt;Con la explicación de este patrón, termino esta miniserie de GoF (Decorador y Estrategia). En próximos post veremos algunos GoF creacionales.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-837534458269195762?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/837534458269195762/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=837534458269195762' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/837534458269195762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/837534458269195762'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/02/estrategia-gof-encapsulemos-los.html' title='Estrategia (GoF) - Encapsulemos los algoritmos que varíen'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_iGJtoWG_NkY/R6crfQsbEVI/AAAAAAAAAGw/GwuuF1bT_2Q/s72-c/strategy+gof.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-5176787735209394222</id><published>2008-02-02T13:49:00.000-02:00</published><updated>2008-02-06T09:52:36.563-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NET'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='3 capas'/><title type='text'>Desarrollar en 3 capas con .Net+NHibernate</title><content type='html'>Para facilitarles la lectura de los posts referentes al &lt;span style="color:#cc0000;"&gt;desarrollo en 3 capas con .Net+NHibernate&lt;/span&gt;, les he realizado una versión en pdf que esta almacenada aquí (dentro de un .zip): &lt;a href="http://www.orbitfiles.com/download/id2523464813.html"&gt;http://www.orbitfiles.com/download/id2523464813.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-5176787735209394222?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/5176787735209394222/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=5176787735209394222' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/5176787735209394222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/5176787735209394222'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/02/desarrollar-en-3-capas-con.html' title='Desarrollar en 3 capas con .Net+NHibernate'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-5113168715920147316</id><published>2008-01-22T13:07:00.000-02:00</published><updated>2008-01-25T10:06:02.551-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patrones de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='decorador'/><title type='text'>Decorador (GoF) ó agregando responsabilidades a un objeto de forma dinámica</title><content type='html'>Las clases que componen la estructura del patrón decorador:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp2.blogger.com/_iGJtoWG_NkY/R5YI-L86FLI/AAAAAAAAAFY/jEGgm7x5Q-o/s1600-h/decorador+gof.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5158320287652648114" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 322px; CURSOR: hand; HEIGHT: 182px; TEXT-ALIGN: center" height="206" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R5YI-L86FLI/AAAAAAAAAFY/jEGgm7x5Q-o/s320/decorador+gof.JPG" width="343" border="0" /&gt;&lt;/a&gt;Comencemos por recordar un principio básico de diseño (&lt;span style="color:#990000;"&gt;abierto-cerrado&lt;/span&gt;): “&lt;span style="color:#990000;"&gt;las clases deben ser abiertas para la extensión pero cerradas para la modificación&lt;/span&gt;”.&lt;br /&gt;Nuestro patrón GoF se basa en este principio (como tantos otros); para entender su implementación veamos una problemática para ejemplificar.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Tenemos una heladería, la cual además de vender variados gustos en distintos envases (copón, cucuruchos, vasitos), permite agregar diversos dulces al helado, por ej.: bañado de cobertura de chocolate, pasas de uva, almendras, nueces, granolas, rocklets, etc.&lt;br /&gt;Por lo tanto el precio del producto variará en función de los adicionales agregados, por ej.: un cucurucho con nueces y rocklets se vende a 6$ (4$ del producto en sí + 2$ de agregados), un vasito con cobertura de chocolate se vende a 4$ (3$ del producto y 1$ la cobertura).&lt;br /&gt;&lt;/em&gt;&lt;br /&gt;Nuestro diseño rígido:&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5158321833840874690" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R5YKYL86FMI/AAAAAAAAAFg/2p0-ciCwLkI/s320/decorador1-paraBlog.bmp" border="0" /&gt;Cada método Costo() necesita calcular el costo del tipo de producto y luego agregar los adic. llamando a la implementación de Costo() de la superclase.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Problemas de este diseño?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Al tener que agregar ó sacar adicionales, nos forzará a cambiar el método Costo() en la superclase y también agregar ó sacar las propiedades respectivas.&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Podríamos tener que en sólo alguno de los tipos de productos como el “Copón” , se pudiera agregar un determinado adicional, como por ej.: “ensalada de frutas”. &lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Que pasaría si alguien quiere doble porción de “rocklets”?&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Como se ve, la problemática para obtener el precio del producto, resulta interesante para diseñar, debido a las posibilidades de cambio en el algortimo que debe determinar su valor. Ante esta “&lt;strong&gt;posibilidad de cambio en el código&lt;/strong&gt;” actual ó a futuro, debemos comenzar a pensar en alguna solución de diseño que nos permita la &lt;strong&gt;flexibilidad necesaria para incorporar los cambios sin tener que recodificar lo ya hecho&lt;/strong&gt;, o sea con el menor impacto en nuestro código.&lt;br /&gt;&lt;br /&gt;Apliquemos el patron para flexibilizar nuestro diseño:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5158335384462693586" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R5YWs786FNI/AAAAAAAAAFo/U9wztsG3Rkk/s320/decorador2-paraBlog.bmp" border="0" /&gt;&lt;br /&gt;Este diseño implica que cualquiera de nuestros productos concretos (copón, cucurucho,etc), puede tener 1 ó más objetos decoradores (Granola, Rocklet, etc.). De esta forma podría comprar un copón con doble ración de rocklets y nueces, ó cualquier combinación que desee, para luego solicitar su costo; el cual iría sumando los precios de los agregados hasta llegar al precio del producto concreto.&lt;/p&gt;&lt;p&gt;Veamos un ejemplo en código C#:&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;** nuestro producto Copón tiene una descrip. apropiada y un costo de 4.50$&lt;br /&gt;&lt;em&gt;&lt;span style="color:#006600;"&gt;public class Copon: Producto&lt;br /&gt;{&lt;br /&gt;public Copon()&lt;br /&gt;{ descripcion=”Copón helado”;&lt;br /&gt;precio=4.50;}&lt;br /&gt;&lt;br /&gt;public decimal Costo()&lt;br /&gt;{ return this.precio; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;** nuestro agregado de Rocklets hereda de Decorador&lt;br /&gt;** debemos pasarle el producto a decorar en su constructor&lt;br /&gt;** El costo de agregar rocklets a los helados es de 0.80$, y&lt;br /&gt;** lo sumamos al costo del producto a decorar...&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#006600;"&gt;public class Rocklet: Decorador&lt;br /&gt;{&lt;br /&gt;Producto producto;&lt;br /&gt;&lt;br /&gt;public Rocklet(Producto prod)&lt;br /&gt;{ this.producto=prod;&lt;br /&gt;this.precio=0.80;}&lt;br /&gt;&lt;br /&gt;public decimal Costo()&lt;br /&gt;{ return this.precio + this.producto.Costo();}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;&lt;span style="font-size:85%;"&gt;(** Supongamos que el adicional de nueces tiene un costo de 1$.)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Veamos como usarlo en un código cliente:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#006600;"&gt;.....&lt;br /&gt;Producto prod1=new Copon();&lt;br /&gt;prod1=new Rocklet(prod1);&lt;br /&gt;prod1=new Nuez(prod1);&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#006600;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;** podemos agregar una nueva ración de rocklets?, claro&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;span style="color:#006600;"&gt;prod1=new Rocklet(prod1);&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;/span&gt;&lt;em&gt;&lt;span style="color:#006600;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;** mostramos el costo total del Copon con doble rocklets y nuez&lt;br /&gt;&lt;em&gt;&lt;span style="color:#006600;"&gt;System.out.println(prod1.Costo());&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;.....&lt;br /&gt;Debería mostrar: 6.30$ (4.50+0.80+1), cabe aclarar que el método Costo() de prod1 se ejecuta &lt;strong&gt;recursivamente&lt;/strong&gt; para ir capturando el precio del producto a decorar. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-5113168715920147316?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/5113168715920147316/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=5113168715920147316' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/5113168715920147316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/5113168715920147316'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2008/01/decorador-gof-agregando.html' title='Decorador (GoF) ó agregando responsabilidades a un objeto de forma dinámica'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_iGJtoWG_NkY/R5YI-L86FLI/AAAAAAAAAFY/jEGgm7x5Q-o/s72-c/decorador+gof.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-3306758561248055332</id><published>2007-11-30T13:39:00.000-03:00</published><updated>2007-11-30T15:21:08.698-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='aplicacion web'/><category scheme='http://www.blogger.com/atom/ns#' term='code behind'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='WebForms'/><category scheme='http://www.blogger.com/atom/ns#' term='2 capas'/><title type='text'>Arquitectura ASP Net clásica, modelo de WebForms</title><content type='html'>&lt;a href="http://bp1.blogger.com/_iGJtoWG_NkY/R1BAitf9kdI/AAAAAAAAAEA/XLeh-ScZxaw/s1600-R/aplicacion+web+asp+net.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5138678139903119826" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" height="258" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R1BAitf9kdI/AAAAAAAAAEA/9elATnU5ZKw/s320/aplicacion+web+asp+net.JPG" width="361" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Una aplicación web creada con &lt;strong&gt;Asp Net&lt;/strong&gt; de la forma en la que nuestros amigos de &lt;em&gt;Microsoft&lt;/em&gt; la han ideado, implica una arquitectura de 2 capas como la siguiente: &lt;/div&gt;&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5138676056843981250" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 336px; CURSOR: hand; HEIGHT: 92px; TEXT-ALIGN: center" height="106" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/R1A-pdf9kcI/AAAAAAAAAD4/I1_64oxNCgU/s320/arq+webform+clasica+-+tabla+de+capas.JPG" width="367" border="0" /&gt;&lt;br /&gt;En el caso de la &lt;em&gt;capa de aplicación&lt;/em&gt;, Asp.Net 2.0 no requiere que se ubique necesariamente código de la lógica de la aplicac. en el archivo &lt;em&gt;code-behind&lt;/em&gt;, ya que también se puede agregar el mismo en el código de presentación (.aspx). De todas formas siempre es aconsejable mantener separado las lógicas de aplicación y presentación.&lt;br /&gt;&lt;br /&gt;En el caso de la capa de acceso a datos, no es aconsejable acceder desde la capa de aplicación directamente a la BD ( &lt;span style="font-size:85%;"&gt;ya sea a través del llamado a &lt;em&gt;procedimientos almacenados&lt;/em&gt; ó vía &lt;/span&gt;&lt;em&gt;&lt;span style="font-size:85%;"&gt;ejecución de comandos SQL&lt;/span&gt;) &lt;/em&gt;, siempre es mejor crear clases que accedan a la tecnología usada en el acceso a datos; &lt;strong&gt;porque ?&lt;/strong&gt;&lt;br /&gt;Porque con esta decisión de diseño, tendremos las siguientes ventajas: &lt;ul&gt;&lt;li&gt;El código de acceso a datos se aísla en una clase separada, por lo cual podemos poner a trabajar a nuestros expertos en BD, mientras los analistas y programadores de lógica de aplicación trabajan en la otra capa.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Podemos afinar la perfomance de la BD (tiempos de acceso, pruebas de stress, etc) sin afectar el resto de la aplicación con nuestros cambios.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Podemos migrar de tecnología de acceso a datos, por ej.: de SqlServer a Oracle, ó a un ORM (Nhibernate ó Linq, etc); sin afectar las otras capas. (capas como módulos pluggables)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;OK, me convencí, voy a generar mis clases de acceso a datos con las operaciones básicas de persistencia (&lt;em&gt;&lt;span style="font-size:85%;"&gt;CRUD: Create-Retrieve-Update-Delete&lt;/span&gt;&lt;/em&gt;), aunque tener esta flexibilidad, no posee ningún costo asociado?&lt;br /&gt;&lt;strong&gt;SI&lt;/strong&gt; lo posee, debido a que Asp.Net está diseñado para trabajar con &lt;em&gt;los controles de las fuentes de datos embebidos en nuestras páginas .aspx&lt;/em&gt;, soluciones?: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;No usar las fuentes de datos (DataSources) de Asp.Net, lo cual significa que no podremos usar “data-binding” en nuestras presentaciones, por lo cual debemos escribir el código que conecta la interfaz de usuario (IU) a las clases de acceso a datos.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Usar la nueva fuente de datos de objetos (ObjectDataSource) de Asp.Net 2.0, la cual está diseñada para ligar los controles Asp.Net a clases de acceso a datos, aunque esto agrega una capa de complejidad que en algunos casos tampoco soluciona el problema.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;strong&gt;Como es una aplicación web Asp Net??&lt;/strong&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Los sitios web Asp Net son desarrollados via el uso de los &lt;em&gt;&lt;strong&gt;Web Forms&lt;/strong&gt;&lt;/em&gt; (.aspx), éstos brindan la funcionalidad web a los clientes. Un request a un recurso .aspx, como por ej.: &lt;span style="color:#996633;"&gt;http://miWeb.com.ar/CarritoCompras/default.aspx&lt;/span&gt;, resulta que sea ejecutado el archivo default.aspx (junto con su archivo code-behind) en el server, luego el resultado será una página html que se enviará al cliente.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;En la siguiente imagen podemos ver una pantalla completa de ejemplo de desarrollo con la ide Visual Studio 2005, donde se aprecia una ventana con el "&lt;span style="color:#009900;"&gt;explorador de soluciones&lt;/span&gt;" (&lt;span style="font-size:85%;"&gt;ver las extensiones .aspx de los WebForms y .aspx.cs del code behind&lt;/span&gt;), una ventana "&lt;span style="color:#009900;"&gt;toolbox&lt;/span&gt;" donde se ven la gran cantidad de &lt;em&gt;controles Web server&lt;/em&gt; de AspNet que pueden agregarse al &lt;em&gt;WebForm&lt;/em&gt;; y una página que aparece en &lt;span style="color:#009900;"&gt;modo de diseño&lt;/span&gt;, mostrando un &lt;em&gt;&lt;span style="color:#cc0000;"&gt;control GridView&lt;/span&gt;&lt;/em&gt; que es usado para mostrar y editar los datos del carrito de compras. &lt;img id="BLOGGER_PHOTO_ID_5138683079115510274" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" height="335" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R1BFCNf9kgI/AAAAAAAAAEY/sfOxQs-kOvI/s400/VS2005-ejemplo+de+web+asp+net+2.JPG" width="431" border="0" /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;Existen además otros archivos para el diseño de la IU como &lt;em&gt;Web User controls&lt;/em&gt; y &lt;em&gt;Master Pages&lt;/em&gt;, los cuales son similares a los &lt;em&gt;Web Forms&lt;/em&gt; (&lt;span style="font-size:85%;"&gt;están compuestos de HTML y código c# ó vb.Net en su code-behind&lt;/span&gt;), aunque no pueden ser accedidios de forma directa por los clientes. Estos son usados para componer el contenido de los&lt;em&gt; Web Forms&lt;/em&gt;.&lt;br /&gt;Los &lt;em&gt;Web User controls (.ascx&lt;/em&gt;) se incluyen en los Web Forms y permiten la reutilización de código en la capa de presentación.&lt;br /&gt;Los &lt;em&gt;Master Pages (.master)&lt;/em&gt; son templates que pueden ser aplicados a gran número de Web Forms , para asegurar consistencia visual y funcionalidad a través de varias páginas del sitio. Normalmente usados para encabezado y pie de nuestro sitio, mapa del sitio, columnas con menúes.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Controles del lado del servidor&lt;/strong&gt;&lt;/em&gt;, existen 2 categorías: &lt;/div&gt;&lt;ul&gt;&lt;li&gt;Html, permiten acceder a los elementos HTML de la página a través del código (en el code-behind). Se transforma un control Html (Button, TextBox, RadioButton,...) a un Html server agregandole el atributo “runat=server”. La mayoría de los controles Html están duplicados con mayor funcionalidad en los controles Web server, aunque a veces ud. deberá usarlos.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Web server, son clases .NET compiladas que, al ser ejecutadas, generan código Html como salida, eventualmente pueden incluír scripts del lado del cliente.&lt;br /&gt;Pueden ser usados en los Web Forms en forma directa ó a través de la creación de Web User controls. Estos incluyen controles simples como TextBox ó Button, y otros más complejos como el GridView (el viejo DataGrid) que permite mostrar datos de la BD en forma de tabla con manejo de muchas propiedades de diseño y eventos.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;A continuación les muestro algunas pantallas que fueron obtenidas del VS 2005 para ejemplificar características importantes que hacen al desarrollo de páginas Asp Net (WebForms)&lt;br /&gt;&lt;/div&gt;&lt;div&gt;El VS me permite visualizar las páginas en 2 modos: &lt;strong&gt;el de diseño&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img id="BLOGGER_PHOTO_ID_5138689736314819090" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R1BLFtf9khI/AAAAAAAAAEg/V6q9hTb0PC0/s400/Web+form+-+modo+dise%C3%B1o.JPG" border="0" /&gt;que me permite visualizar como se verá la página en el Browser, en el ejemplo se ve "deshabilitado" el acceso a la cabecera y pie del sitio que son parte del &lt;em&gt;master page&lt;/em&gt; al cual pertenece esta página.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Y el &lt;strong&gt;modo de "código fuente&lt;/strong&gt;":&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5138691368402391602" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/R1BMktf9kjI/AAAAAAAAAEw/kUPx9OFgsg0/s400/Web+form+-+modo+fuente.JPG" border="0" /&gt;Aquí se puede editar el código html y los controles Web de asp net que han sido agregados en modo de diseño (&lt;span style="font-size:85%;"&gt;encapsulados en los tags &lt;asp&gt;&lt;/asp&gt;).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Por último un ejemplo del &lt;em&gt;code behind&lt;/em&gt; (.aspx.cs) de esta página, donde normalmente generamos nuestro código de manejo de eventos de la página y de los controles :&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5138694984764854850" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R1BP3Nf9kkI/AAAAAAAAAE4/UKOvfOSiJs0/s400/Web+form+-+code+behind.JPG" border="0" /&gt;Con este post he intentado demostrar a aquellos que no han programado con AspNet, las principales características de la arquitectura clásica de desarrollo web, así el lector podrá comprender mejor las diferencias existentes contra la nueva propuesta del &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/11/el-futuro-mvc-de-asp-net.html"&gt;MVC para AspNet &lt;/a&gt;posteada anteriormente.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-3306758561248055332?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/3306758561248055332/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=3306758561248055332' title='5 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/3306758561248055332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/3306758561248055332'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/11/arquitectura-asp-net-clsica-modelo-de.html' title='Arquitectura ASP Net clásica, modelo de WebForms'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_iGJtoWG_NkY/R1BAitf9kdI/AAAAAAAAAEA/9elATnU5ZKw/s72-c/aplicacion+web+asp+net.JPG' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-1185752851701909448</id><published>2007-11-27T10:05:00.000-03:00</published><updated>2007-11-27T14:37:00.375-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='vista'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='controladora'/><category scheme='http://www.blogger.com/atom/ns#' term='modelo'/><title type='text'>EL futuro MVC de Asp Net</title><content type='html'>&lt;a href="http://bp0.blogger.com/_iGJtoWG_NkY/R0xRKdf9kbI/AAAAAAAAADw/3RaorNcgb2w/s1600-h/Project-MVC-Asp.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5137570515082121650" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/R0xRKdf9kbI/AAAAAAAAADw/3RaorNcgb2w/s320/Project-MVC-Asp.jpg" border="0" /&gt;&lt;/a&gt;Luego de haber leído los artículos de &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx"&gt;Scott Guthrie&lt;/a&gt; y &lt;a href="http://dotnetslackers.com/articles/aspnet/AnArchitecturalViewOfTheASPNETMVCFramework.aspx"&gt;Dino Esposito&lt;/a&gt; voy a realizar un resúmen de la propuesta MVC para ASP NET.&lt;br /&gt;&lt;br /&gt;Para crear una aplicación de este tipo con VS, elegimos un nuevo proyecto de tipo “ASP.NET MVC Web Application”, de esta forma se creará una nueva solución y se añadirán dos proyectos: un proyecto web en el que implementaremos nuestra aplicación y un proyecto de testing que usaremos para escribir test unitarios (&lt;a href="http://es.wikipedia.org/wiki/Tdd"&gt;TDD&lt;/a&gt;...)&lt;br /&gt;La estructura por defecto de un ASP.NET MVC tiene 3 directorios:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;/Controllers&lt;/li&gt;&lt;li&gt;/Models&lt;/li&gt;&lt;li&gt;/Views&lt;/li&gt;&lt;/ul&gt;Por lo cual, crear las clases controladoras en el directorio &lt;em&gt;/Controllers&lt;/em&gt;, las de modelo de datos en &lt;em&gt;/Models&lt;/em&gt;, y las vistas en el directorio &lt;em&gt;/Views&lt;/em&gt;.&lt;br /&gt;Cabe aclarar que el Framework no te obliga a usar esta estructura, pero el template usa este patrón. Consultando a Scott sobre el uso de ensamblados (dll) para la controladora y el modelo (mis capas de negocio y acceso a datos), dijo no existir problemas en agregar las referencias a los mismos y usarlos en el MVC en vez de las carpetas creadas por default; si no fuera así no podríamos usar nuestras controladoras y modelos de un proyecto a otro, debiendo reescribir código en cada solución. &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Por defecto los proyectos MVC tienen unas reglas de enrutado de urls preconfiguradas, de esta forma podemos empezar a escribir el código usando un conjunto de convenciones para nombrar las urls que van a usarse en nuestra aplicación.&lt;a href="http://bp0.blogger.com/_iGJtoWG_NkY/R0w-hdf9kXI/AAAAAAAAADQ/nBf1UxeoHYE/s1600-h/productsController-mvc-asp.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5137550019498185074" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/R0w-hdf9kXI/AAAAAAAAADQ/nBf1UxeoHYE/s320/productsController-mvc-asp.jpg" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;em&gt;&lt;strong&gt;Las Controladoras...&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;El convenio por defecto es &lt;em&gt;mapear el path de la url de una petición HTTP (&lt;span style="font-size:85%;"&gt;por ejemplo: /Products/&lt;/span&gt;) a una clase cuyo nombre siga el patrón UrlPathController&lt;/em&gt; (&lt;span style="font-size:85%;"&gt;por ejemplo: una url que termine con /Products/ se mapeará a la clase ProductsController&lt;/span&gt;).&lt;br /&gt;Por lo tanto si agregamos la clase “&lt;em&gt;ProductsController&lt;/em&gt;” (&lt;span style="font-size:85%;"&gt;que herede de System.Web.MVC.Controller&lt;/span&gt;) a nuestro proyecto, el framework ASP.NET MVC la usará para procesar todas las peticiones cuya url contenga la cadena “/Products”. Es decir, será llamada para procesar las urls “/Products/Categories”, “/Products/List/Beverages”, “/Products/Detail/3″ (&lt;span style="font-size:85%;"&gt;donde 3 será el id. del producto&lt;/span&gt;), etc.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;El framework MVC nos permite definir “&lt;em&gt;métodos de acción&lt;/em&gt;” en nuestro controladora, y la clase base Controller invocará el método apropiado, así que cuando recibimos una petición de la forma "/Products/Categories”, la regla de enrutado tratará la parte “Categories” como el nombre de la acción, y se invocará el método Categories() para procesar la petición, si recibimos una petición a la url "/Products/Detail/5", la regla tomará el nombre “Detail” como el nombre de la acción y se invocará al método Detail(), etc.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;em&gt;&lt;strong&gt;Como accedemos a los parámetros de las urls?&lt;/strong&gt;&lt;/em&gt;&lt;/div&gt;&lt;div&gt;La clase base &lt;em&gt;Controller&lt;/em&gt; expone un conjunto de objetos &lt;em&gt;Request&lt;/em&gt; y &lt;em&gt;Response&lt;/em&gt; que podemos usar. Estos objetos tienen la misma estructura que los objetos HttpRequest/HttpResponse a los que estamos acostumbrados en ASP.NET, la diferencia es que estos objetos están basados en interfaces en lugar de en clases selladas (sealed) (MVC trae las interfaces System.Web.IHttpRequest y System.Web.IHttpResponse), esto nos da la posibilidad de poder implementarlos como queramos, uno de sus usos será crear test unitarios para clases controlador.&lt;a href="http://bp3.blogger.com/_iGJtoWG_NkY/R0xC2Nf9kYI/AAAAAAAAADY/1AV2POM6l8Q/s1600-h/productsControllerMetodos-mvc-asp.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5137554774026981762" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 311px; CURSOR: hand; HEIGHT: 271px" height="271" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R0xC2Nf9kYI/AAAAAAAAADY/1AV2POM6l8Q/s320/productsControllerMetodos-mvc-asp.jpg" width="462" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;En la acción &lt;em&gt;List&lt;/em&gt; , aparece un parámetro de la categoría, que es parte de la URL, y un índice de página opcional (implementaremos paginado en el servidor y usaremos ese valor para indicar qué página de categoría mostrar en la petición).&lt;br /&gt;Los &lt;em&gt;parámetros opcionales&lt;/em&gt; se manejan usando tipos de datos &lt;em&gt;nullables&lt;/em&gt; en los métodos de acción de las controladoras. El parámetro “int?” de nuestra acción List es nullable.&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;em&gt;&lt;strong&gt;Construyendo las clases del Modelo&lt;/strong&gt; &lt;/em&gt;&lt;/div&gt;&lt;div&gt;Para crear nuestras clases que accedan a la información de la BD, Scott lo realiza mediante "Linq to Sql" (ORM), &lt;a href="http://bp0.blogger.com/_iGJtoWG_NkY/R0xJVdf9kZI/AAAAAAAAADg/RUmTIIJ2vMk/s1600-h/modelo-linqToSql-mvc-asp.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5137561907967660434" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/R0xJVdf9kZI/AAAAAAAAADg/RUmTIIJ2vMk/s320/modelo-linqToSql-mvc-asp.jpg" border="0" /&gt;&lt;/a&gt;el cual me permite obtener como resultados listas de objetos. También podría usar NHibernate o cualquier otro tipo de ORM, ó Ado.Net (no recomendado, ya que debo mapear registros a listas de objetos) para construir mis clases del Modelo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Volviendo a nuestra controladora, vemos el uso que se hace del modelo creando un objeto de tipo "&lt;em&gt;NorthwindDataContext&lt;/em&gt;" (&lt;span style="font-size:85%;"&gt;clase creada con la utilidad de Linq&lt;/span&gt;), y llamando a sus métodos, como por ej.: en el método "&lt;em&gt;Detail(int id)"&lt;/em&gt; donde llamamos a "&lt;em&gt;northwind.GetProductById(id)"&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Y la Vista??&lt;br /&gt;&lt;/strong&gt;&lt;/em&gt;Cuando implementamos los tres métodos de acción del controlador en la clase &lt;em&gt;ProductsController&lt;/em&gt;, usamos los parámetros de la URL para obtener los objetos adecuados de nuestra BD, para luego seleccionar una vista adecuada para generar una resputesta HTML. Usaremos uno de los métodos &lt;em&gt;RenderView()&lt;/em&gt; de la clase base &lt;em&gt;Controller&lt;/em&gt; para espcificar la vista que queramos usar, así como explicitamente le pasaremos los datos específicos que queremos que la vista use para renderizar la respuesta. Por ej: RenderView("Detail", product), donde &lt;em&gt;product&lt;/em&gt; es el objeto de tipo &lt;em&gt;Product&lt;/em&gt; obtenido del llamado al Modelo.&lt;br /&gt;Para crear la vista a la cual hacemos referencia en el ej. ("Detail"), podemos usar cualquier motor de templates para ayudarnos a generar la interfaz de usuario (incluyendo motores como NVelocity, Brail - y cualquiera que escribamos ). Por defecto ASP.NET MVC usa las páginas ASP.NET (.aspx), Master Pages (.master) y UserControls (.ascx).&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Conclusiones&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;Este framework no reemplaza el modelo basado en WebForms de Asp.Net, sólo nos agrega la posibilidad de crear nuestras aplicaciones bajo este paradigma, aplicando a la perfección este viejo patrón de arquitectura (MVC).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;En el &lt;a href="http://dotnetslackers.com/articles/aspnet/AnArchitecturalViewOfTheASPNETMVCFramework.aspx"&gt;post de Dino&lt;/a&gt;, se le pregunta a los lectores si han escuchado hablar de &lt;a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm" target="_blank" rel="nofollow"&gt;REST&lt;/a&gt; (&lt;em&gt;Representational State Transfer&lt;/em&gt;) , el cual es otro patrón de arquitectura que encaja perfectamente en el proceso del MVC AspNet, que describimos anteriormente.&lt;br /&gt;REST define cómo los recursos de la red deberían ser definidos y direccionados con el objetivo de: obtener menores tiempos de respuesta y separar las responsab. entre front-end y back-end. Se basa en los sig. principios:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Una aplicación expresa su estado e implementa su funcionalidad actuando sobre recursos lógicos.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Cada recurso es direccionado usando una URL específica.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Todas las ventajas que poseen esos recursos direccionables se agrupan en un juego de operaciones.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Por lo tanto el framework MVC de AspNet usa un modelo REST que compite con el modelo clásico de "postback" de AspNet.&lt;/p&gt;&lt;a href="http://bp3.blogger.com/_iGJtoWG_NkY/R0xQUNf9kaI/AAAAAAAAADo/Bmu6AAWVHKg/s1600-h/MVCvsASPclasico.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5137569583074218402" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R0xQUNf9kaI/AAAAAAAAADo/Bmu6AAWVHKg/s320/MVCvsASPclasico.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Cada página se separa en 2 componentes (controladora y vista) que operan sobre el mismo modelo de datos; esto es opuesto al clásico modelo "code-behind" donde no existen barreras que nos fuercen a separar las responsab. entre controladoras y vistas.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Aunque manteniendo las clases "code-behind" (nuestras aspx.cs) lo más ligeras que sea posible y diseñando la capa de negocios de forma apropiada (&lt;span style="font-size:85%;"&gt;ver &lt;/span&gt;&lt;a href="http://metodologiasdesistemas.blogspot.com/2007/11/desarrollo-en-3-capas-parte-2-la.html"&gt;&lt;span style="font-size:85%;"&gt;ejemplo de capa de negocio&lt;/span&gt;&lt;/a&gt;), un buen desarrollador logra separar estas responsabilidades manteniendo la lógica de la aplicación en la capa que corresponda.&lt;br /&gt;&lt;br /&gt;Bueno, en este post se ha intentado aclarar un poco de que trata un framework MVC, tomándolo como una opción más a la hora de desarrollar software para Web. Cualquier extensión al tema leer los posts de Scott y Dino que están referenciados al principio.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-1185752851701909448?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/1185752851701909448/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=1185752851701909448' title='7 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/1185752851701909448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/1185752851701909448'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/11/el-futuro-mvc-de-asp-net.html' title='EL futuro MVC de Asp Net'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_iGJtoWG_NkY/R0xRKdf9kbI/AAAAAAAAADw/3RaorNcgb2w/s72-c/Project-MVC-Asp.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-3485289592524027562</id><published>2007-11-23T13:53:00.001-03:00</published><updated>2008-05-08T19:30:56.242-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='framework'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='WebForms'/><title type='text'>Introducción a los frameworks MVC</title><content type='html'>Ya hemos visto una arquitectura de &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/11/desarrollar-en-3-capas-con-net-y.html"&gt;3 capas lógicas&lt;/a&gt;, ahora investiguemos como desarrollar un MVC (model-view-controller) , que fue explicado muy someramente en este &lt;a href="http://metodologiasdesistemas.blogspot.com/2007_05_01_archive.html"&gt;post&lt;/a&gt;.&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_iGJtoWG_NkY/R0cP7df9kUI/AAAAAAAAAC4/cj6Fe8aKlTk/s1600-h/MVC-interactions.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5136091414244725058" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/R0cP7df9kUI/AAAAAAAAAC4/cj6Fe8aKlTk/s320/MVC-interactions.gif" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sin lugar a dudas estos frameworks han ganado terreno en el desarrollo de sitios Web, donde &lt;a href="http://es.wikipedia.org/wiki/Ruby_on_Rails"&gt;RubyOnRails&lt;/a&gt; ha sido la inspiración de otros desarrolladores de frameworks de este tipo. En el caso del mundo .NET, la creación de &lt;a href="http://www.castleproject.org/monorail/index.html"&gt;MonoRail&lt;/a&gt; sumó muchos adeptos en la comunidad de desarrolladores y todos comenzamos a mirar de reojo para cuando Microsoft sumaría una propuesta de desarrollo que rompiera con el modelo basado en WebForms (.aspx), ó al menos agregara la posibilidad del MVC.&lt;br /&gt;&lt;br /&gt;El modelo actual de MS impone que los &lt;em&gt;request&lt;/em&gt; de los clientes son solicitudes a páginas (WebForms) aspx que contienen controles Web ASP.Net, los cuales disparan eventos a una controladora de esa página. Esta controladora es normalmente código C# ó VB.Net agregado al WebForm, y conocido como "code behind" (aspx.cs ó aspx.vb). En este tipo de arquitectura el cliente hace &lt;em&gt;Request&lt;/em&gt; a objetos de la capa de presentación (WebForms aspx), que luego llaman a su objeto controlador para pedirle funciones, estas luego harán solicitudes sobre el Modelo (mi acceso a datos en el 3 capas lógicas).&lt;br /&gt;&lt;br /&gt;En el caso de un MVC, el &lt;em&gt;Request&lt;/em&gt; se realiza a un objeto de tipo Controlador que crea una presentación como &lt;em&gt;Response&lt;/em&gt; a esa solicitud. Si se fijan en el diagrama MVC dice que la "Controladora selecciona la Vista que irá como respuesta".&lt;br /&gt;&lt;br /&gt;Pues bien, Microsoft responde a la comunidad de desarrolladores .NET con la siguiente sorpresa (quizás no tanto...) el dia 13/11/2007 : The Asp.Net MVC framework. Ver el extenso &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx"&gt;post&lt;/a&gt; que publicó el gran Scott Guthrie (&lt;em&gt;&lt;span style="font-size:85%;"&gt;jefe de proyectos de MS: IIS, ASP.NET, Atlas, CLR, Compact Framework, Windows Forms, etc, etc.).&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;Allí se aclara que será agregado al VS 2008 como una ventaja opcional, a través de un template para la creación de proyectos de tipo MVC, también que este modelo fuerza a una limpia separación de responsabilidades de la aplicación, que permite realizar testeos de los componentes soportando TDD (desarrollo manejado por el testing), y que provee mayor control sobre las URLs que se publican en su aplicación, y mayor control sobre el código HTML que se emite desde ellas.&lt;br /&gt;&lt;br /&gt;Esta es una vista de como las URLs se mapean a clases Controladoras:&lt;br /&gt;&lt;a href="http://bp2.blogger.com/_iGJtoWG_NkY/R0cVPNf9kVI/AAAAAAAAADA/CM0Aa1ChtFw/s1600-h/urlsMapControllers.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5136097251105280338" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 290px; CURSOR: hand; HEIGHT: 137px" height="137" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/R0cVPNf9kVI/AAAAAAAAADA/CM0Aa1ChtFw/s320/urlsMapControllers.jpg" width="277" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;En el post de Scott, se aclara que en la mayoría de los frameworks Web (&lt;span style="font-size:85%;"&gt;ASP Net WebForms,PHP,JSP,...)&lt;/span&gt; las URLs se mapean con archivos template almacenados en el disco del servidor web, por ej: un url "/Productos.aspx" tiene un archivo subyacente Productos.aspx en disco que maneja el procesamiento de la misma.&lt;br /&gt;&lt;br /&gt;En cambio, en los frameworks MVC las URLs se mapean directamente a clases, estas son denominadas "Controladoras" y son las que procesan los &lt;em&gt;Request&lt;/em&gt; entrantes, manejando las entradas del usuario, sus interacciones y ejecutando la lógica apropiada para el proceso. Una clase controladora llama a una vista, la cual genera la salida HTML que se enviará como &lt;em&gt;Response&lt;/em&gt;.&lt;br /&gt;En prox. posts entraré en más detalles sobre este ASP.Net MVC y en el modelo de WebForms.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-3485289592524027562?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/3485289592524027562/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=3485289592524027562' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/3485289592524027562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/3485289592524027562'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/11/introduccin-los-frameworks-mvc.html' title='Introducción a los frameworks MVC'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_iGJtoWG_NkY/R0cP7df9kUI/AAAAAAAAAC4/cj6Fe8aKlTk/s72-c/MVC-interactions.gif' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-7376200957185772529</id><published>2007-11-20T09:39:00.000-03:00</published><updated>2007-11-20T13:14:13.442-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cohesion'/><category scheme='http://www.blogger.com/atom/ns#' term='acoplamiento'/><category scheme='http://www.blogger.com/atom/ns#' term='patrones de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='arquitectura'/><title type='text'>Arquitectura del software?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_iGJtoWG_NkY/R0MDZtf9kSI/AAAAAAAAACo/5gZMJsn4XSY/s1600-h/soft+architecture.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp0.blogger.com/_iGJtoWG_NkY/R0MDZtf9kSI/AAAAAAAAACo/5gZMJsn4XSY/s320/soft+architecture.png" alt="" id="BLOGGER_PHOTO_ID_5134951740377764130" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Muchas veces nos hablan de la &lt;span style="font-weight: bold;"&gt;arquitectura &lt;/span&gt;en el desarrollo de sistemas.  Palabrita de moda quizás...; ingenieros, analistas y programadores que se hacen llamar "Arquitectos de software" como si de un título se tratase.  Hasta yo la he puesto como título en mi Blog, entonces, cual es el significado de la &lt;span style="font-weight: bold;"&gt;Arquitectura&lt;/span&gt; en el desarrollo de un sistema?, tratemos de averiguarlo.&lt;br /&gt;&lt;br /&gt;En setiembre de este año se realizaron las 36 jornadas de la Jaiio en mi ciudad (Mar del Plata), y al ver el temario de los seminarios, me informo de un curso especial de 8 hs. seguidas, llamado "&lt;span style="font-style: italic;"&gt;Introducción a la arquitectura del software&lt;/span&gt;", dictado por el Gerente de relac. académicas de Microsoft y profesor de la UBA Pablo Michelis.  Por supuesto para entender mejor este concepto y para agregar valor a mis clases me inscribí;  esto intenta ser un breve resúmen del mismo.&lt;br /&gt;&lt;br /&gt;Comencemos por definir "&lt;span style="font-weight: bold;"&gt;Arquitectura del soft&lt;/span&gt;":&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(102, 102, 0);"&gt;"Estructura de sistemas o sistema de estructuras que consisten en elementos, sus propiedades externamente visibles y la relación entre ellos"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="color: rgb(102, 102, 0);"&gt;"Propiedades externamente visibles: qué es lo que debe saber/suponer un componente sobre otro?"&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Por último  :&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Toda la arquitectura es diseño, pero no todo el diseño es arquitectura. La arquitectura representa las &lt;span style="font-weight: bold;"&gt;decisiones de diseño significativas&lt;/span&gt; que le dan forma a un sistema, donde lo significativo puede ser medido por el costo del cambio&lt;/span&gt;". (Grady Booch)&lt;/span&gt;&lt;br /&gt;Creo que es la más simple y directa definición de arquitectura.&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Basándonos en esta última definición podemos suponer que lo que distingue a la arquitectura de otro tipo de diseño es la significancia expresada en la dificultad ó costo del cambio.&lt;br /&gt;La arquitectura del soft mantiene unidas las nociones de : diseño, estructura, estilo, racionalidad,  proceso y costo.&lt;br /&gt;Ahora bien,  como podemos evaluar la&lt;span style="font-weight: bold;"&gt; calidad&lt;/span&gt; de una determinada arquitectura para nuestra solución de software? , quizás una buena arquitectura sea aquella en la que las &lt;span style="font-weight: bold;"&gt;decisiones de diseño significativas se lograron minimizar&lt;/span&gt;, evitando riesgos de cambio futuros.  De esta forma estaríamos libres de cambiar varios aspectos del sistema sin el miedo a que tales cambios produzcan cascada de errores y cambios en el diseño que nos llevarían a altos costos de mantenimiento. Una buena arquitectura debe ser sustentable.&lt;br /&gt;&lt;br /&gt;Como se relaciona esta visión de la arquitectura con la estructura del sistema?, pues construyamos componentes, clases, paquetes, ensamblados, etc. que sean altamente cohesivos y con bajo acoplamiento (&lt;span style="font-style: italic;font-size:85%;" &gt;nuestro ying y yang recuerdan?&lt;/span&gt;).&lt;br /&gt;En una arquitectura con bajo acoplamiento, donde los puntos de variación futuras estén bien encapsulados, los efectos del cambio estarán bien aislados y el costo será relativamente bajo.&lt;br /&gt;Por esto es que a nivel de arquitectura hablamos de los patrones de diseño, que nos permiten el desarrollo de mejores arquitecturas de software como por ejemplo la &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/11/desarrollar-en-3-capas-con-net-y.html"&gt;3 capas explicada y ejemplificada&lt;/a&gt; en previos posts.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-7376200957185772529?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/7376200957185772529/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=7376200957185772529' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/7376200957185772529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/7376200957185772529'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/11/arquitectura-del-software.html' title='Arquitectura del software?'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_iGJtoWG_NkY/R0MDZtf9kSI/AAAAAAAAACo/5gZMJsn4XSY/s72-c/soft+architecture.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-5684086464336025547</id><published>2007-11-19T13:57:00.000-03:00</published><updated>2007-11-19T15:56:03.574-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DAO'/><category scheme='http://www.blogger.com/atom/ns#' term='presentación'/><category scheme='http://www.blogger.com/atom/ns#' term='NET'/><category scheme='http://www.blogger.com/atom/ns#' term='casos de uso'/><category scheme='http://www.blogger.com/atom/ns#' term='3 capas'/><category scheme='http://www.blogger.com/atom/ns#' term='controladora'/><title type='text'>Desarrollar en 3 capas con .NET (parte 2) - La controladora y la presentación</title><content type='html'>&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;Antes de mostrar el manejo de la capa de negocio, les aclaro el concepto de &lt;span style="font-weight: bold;"&gt;Viatico&lt;/span&gt;:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"es una retribución diaria que cobra un &lt;span style="font-weight: bold;"&gt;empleado&lt;/span&gt; cuando la empresa lo envía a realizar alguna tarea fuera de su ámbito normal de trabajo (normalmente a otra ciudad)&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;este importe diario depende de la &lt;span style="font-weight: bold;"&gt;categoría&lt;/span&gt; del mismo.&lt;/span&gt;  &lt;span style="font-style: italic;"&gt;A esto se le suman todos los gastos extras que surjan por movilidad, inscripción a cursos, etc.  Normalmente se genera una &lt;span style="font-weight: bold;"&gt;Solicitud&lt;/span&gt; que , en caso de ser aprobada por un superior genera el &lt;span style="font-weight: bold;"&gt;Viático&lt;/span&gt; correspondiente." &lt;/span&gt;&lt;span style="font-size:85%;"&gt;(los sustantivos marcados en negrita corresponden a algunos de los &lt;span style="font-weight: bold;"&gt;objetos de negocio&lt;/span&gt; de nuestro sistema).&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Aclarado este punto importante para poder entender mínimamente el objetivo del sistema, a  continuación veremos como desarrollar nuestra capa de negocio. &lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;La capa de negocio (&lt;span style="font-size:85%;"&gt;ó dominio del problema&lt;/span&gt;) de nuestro sistema, estará compuesta de todos los procesos que fueron analizados como &lt;a href="http://es.wikipedia.org/wiki/Caso_de_uso"&gt;casos de uso&lt;/a&gt;, por lo que es común denominar a estas clases : &lt;span style="font-style: italic;"&gt;controladora del caso de uso XX&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Capa de negocio (&lt;span style="font-style: italic;"&gt;componente ViaticoProcesos&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;En mi caso de ejemplo tengo una clase &lt;span style="font-weight: bold;"&gt;CSolicitud &lt;/span&gt;&lt;span&gt;que posee la responsabilidad de controlar todos los procesos inherentes al man&lt;/span&gt;&lt;span&gt;ejo de Solicitudes de viáticos.  &lt;/span&gt;&lt;br /&gt;Si quisiéramos darle más flexibilidad (&lt;span style="font-size:85%;"&gt;y en consecuencia mayor reutilización futura&lt;/span&gt;) al sistema,  deberíamos desarrollar una interfaz  que agrupe  los métodos comunes a todos los  posibles sistemas de Viáticos  (&lt;span style="font-weight: bold;"&gt;IViaticoSolicitud&lt;/span&gt;) .&lt;br /&gt;Logrando cierta abstracción defino los contratos de mi interfaz:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;public interface IViaticoSolicitud&lt;/span&gt; &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;br /&gt;{&lt;br /&gt;&lt;/span&gt;  &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;void CrearSolicitud(Solicitud nueva);&lt;/span&gt; &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;br /&gt;Viatico AutorizarSolicitud(Solicitud s);&lt;br /&gt;&lt;/span&gt;  &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;void ImprimirSolicitud(Solicitud s);&lt;br /&gt;&lt;/span&gt;  &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt; List&lt;solicitud&gt; &lt;solicitud&gt; BuscarSolicitud(Solicitante s);&lt;/solicitud&gt;&lt;/solicitud&gt;&lt;/span&gt; &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;br /&gt;      List&lt;solicitud&gt; &lt;/solicitud&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;solicitud&gt; &lt;/solicitud&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;solicitud&gt;BuscarSolicitud(Solicitante s, DateTime Desde);&lt;br /&gt;&lt;/solicitud&gt;&lt;/span&gt;  &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt; List&lt;solicitud&gt; &lt;/solicitud&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;solicitud&gt; &lt;/solicitud&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;solicitud&gt;BuscarSolicitud(Solicitante s, DateTime Desde, Boolean Aprobadas);&lt;/solicitud&gt;&lt;/span&gt; &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;br /&gt;      Solicitud BuscarSolicitud(int id);&lt;br /&gt;&lt;/span&gt; &lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Asi que entonces mi clase&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;CSolicitud&lt;/span&gt;&lt;span&gt; implementará mi &lt;span style="font-weight: bold;"&gt;IViaticoSolicitud:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;public class CSolicitud:IViaticoSolicitud&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;{&lt;br /&gt; // Declaro los DAOs con los que va a trabajar mi controladora &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;ISolicitudDao solicitudDao;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;IViaticoDao viaticoDao;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        IEmpleadoDao empleadoDao;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;IMovilidadDao movilidadDao;&lt;/span&gt;  &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;&lt;br /&gt;public CSolicitud()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            // Creo la fabrica y los DAOs que usaré&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;      &lt;br /&gt;NHibDAOFabrica fabricaDAO = new NHibDAOFabrica();&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;      &lt;br /&gt;this.solicitudDao =  fabricaDAO.GetSolicitudDao();&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;this.viaticoDao = fabricaDAO.GetViaticoDao();&lt;/span&gt;   &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;this.empleadoDao=fabricaDAO.GetEmpleadoDao();&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;this.movilidadDao = fabricaDAO.GetMovilidadDao();&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;#region IViaticoSolicitud Members&lt;/span&gt;  &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;&lt;br /&gt;public void CrearSolicitud(Solicitud nueva)&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;{&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            if (nueva.Solicitante != null)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;{&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                try { this.solicitudDao.Save(nueva); }&lt;br /&gt;&lt;/span&gt;   &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;catch { thro&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;w; }&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;      &lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;}&lt;/span&gt;  &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;&lt;br /&gt;public Viatico AutorizarSolicitud(Solicitud s)&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;{&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            try&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;{&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                // Marco como aprobada la Solicitud&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;s.Aprobada = true;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;          &lt;br /&gt;// Creo Viatico basado en la Solicitud aprobada&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                Viatico v = new Viatico();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;v.Estado =   Viatico.estado_viatico.Creado;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;          &lt;br /&gt;v.Solicitud = s;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;v.Numero = this.viaticoDao.DarUltimoNro()+1; // Verificar concurrencia...&lt;br /&gt;&lt;/span&gt;    &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;// Persisto cambios en Solicitud y Grabo nuevo viatico&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;          &lt;br /&gt;this.solicitudDao.SaveOrUpdate(s);&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;          &lt;br /&gt;this.viaticoDao.Save(v);&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;          &lt;br /&gt;return v;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;catch &lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            { throw ; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;public void ImprimirSolicitud(Solicitud s)&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;{&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            throw new Exception("The method or operation is not implemented.");&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;public List&lt;solicitud&gt; BuscarSolicitud(Solicitante s)&lt;/solicitud&gt;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;{&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            try&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;             {&lt;br /&gt;             List&lt;solicitud&gt; lista = this.solicitudDao.DarSolicitudesXSolicitante(s,null,null);&lt;/solicitud&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;return lista;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;   }&lt;br /&gt;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt; catch &lt;/span&gt;  &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            { throw ; }&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;public List&lt;solicitud&gt; BuscarSolicitud(Solicitante s, DateTime Desde)&lt;/solicitud&gt;&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;{&lt;br /&gt;try&lt;br /&gt;{ &lt;/span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;               List&lt;solicitud&gt; lista = this.solicitudDao.DarSolicitudesXSolicitante(s, Desde, null);&lt;/solicitud&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;return lista;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;   }&lt;br /&gt;&lt;/span&gt;  &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;catch &lt;/span&gt;  &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            { throw ; }&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;  &lt;br /&gt;}&lt;/span&gt; &lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;// etc, etc ..............&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;#endregion&lt;/span&gt; &lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Como verán muchos de los métodos solicitan objetos a la capa de acceso a datos (clases DAO), por lo que termina siendo un llama&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;do a un método similar en el DAO.  Aquí es donde mis alumnos dicen " &lt;span style="font-style: italic;"&gt;porqué debemos hacer las cosas por duplicado?, y si llamamos desde la capa de presentación al método del DAO directamente ? "&lt;/span&gt;.&lt;br /&gt;OK, el tema es que la Controladora posee métodos como &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;AutorizarSolicitud(Solicitud s),  &lt;/span&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;donde debemos desarrollar código que sólo es inherente al proceso de negocio y además trabajar en una transacción con varios objetos DAO.&lt;br /&gt;En este ejemplo se cambia un atributo del objeto Solicitud, se crea un objeto Viatico, se pide un nro. de viático a un método estático de Viatico, y se persisten ambos objetos, vía llamado a los métodos de sus DAOs.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Capa de presentación Web  (&lt;span style="font-style: italic;"&gt;componente ViaticoWeb&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;Por último, veamos un ejemplo de mi Capa de presentación Web, que permite la autorización de determinada solicitud de viático.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_iGJtoWG_NkY/R0HTtdf9kRI/AAAAAAAAACg/QygnDhkNCKU/s1600-h/3+capas-presentacion-viaticosWeb.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 447px; height: 140px;" src="http://bp1.blogger.com/_iGJtoWG_NkY/R0HTtdf9kRI/AAAAAAAAACg/QygnDhkNCKU/s400/3+capas-presentacion-viaticosWeb.JPG" alt="" id="BLOGGER_PHOTO_ID_5134617828145336594" border="0" /&gt;&lt;/a&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;La página web muestra una lista de las solicitudes a autorizar por este usuario (jefe).&lt;br /&gt;Selecciona una, y pulsa el botón "Autorizar".&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Al pulsar este botón lo captura el evento "click" del mismo y este es el código:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;protected void ButtonAutorizar_Click(object sender, EventArgs e)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        Solicitud elegida=(Solicitud)Session["SolicitudBuscada"];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        if (elegida!= null)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            // &lt;span style="font-weight: bold;"&gt;creo controladora de Proceso de Solicitudes&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            CSolicitud cSolicitud = new CSolicitud();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            try &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                Viatico v=cSolicitud.AutorizarSolicitud(elegida);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                this.CargarGrid((Usuario)Session["Usuario"]);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                this.LabelError.Text = "Viatico"+v.Numero.ToString()+" CREADO";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            catch&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                Exception ex = new Exception();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                this.LabelError.Text = ex.Message;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            Response.Redirect("~/Admin/Autorizar.aspx"); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            this.LabelError.Text = "Seleccione una Solicitud para Autorizar...";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Como ven , se crea un objeto de tipo CSolicitud y se llama a su método AutorizarSolicitud pasándole como parámetro la solicitud seleccionada por el usuario.  Cualquier error en el proceso llamado será capturado (catch), mostrándose el mensaje de error pertinente.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Capa de Objetos de negocio (&lt;span style="font-style: italic;"&gt;componente ViaticoBO&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;br /&gt;Mis objetos de negocio son clases independientes de la tecnología que se use para persistencia.&lt;br /&gt;Ejemplo: mi BO Solicitud.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;public class Solicitud&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public Solicitud()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        { }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        int id;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public int Id&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return id; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { id = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        Solicitante solicitante;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public Solicitante Solicitante&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return solicitante; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { solicitante = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        System.DateTime fecha_soli;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public System.DateTime Fecha_soli&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return fecha_soli; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { fecha_soli = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        string motivo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public string Motivo&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return motivo; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { motivo = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        int numero;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public int Numero&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return numero; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { numero = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        string origen;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public string Origen&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return origen; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { origen = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        string destino;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public string Destino&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return destino; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { destino = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        System.DateTime desde;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public System.DateTime Desde&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return desde; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { desde = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        System.DateTime hasta;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public System.DateTime Hasta&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return hasta; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { hasta = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        Movilidad ida;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public Movilidad Ida&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return ida; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { ida = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        Movilidad vuelta;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public Movilidad Vuelta&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return vuelta; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { vuelta = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        Boolean aprobada;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        public Boolean Aprobada&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            get { return aprobada; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;            set { aprobada = value; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;                &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En este componente también poseo los archivos de mapeo XML que necesita NHibernate (1 por clase BO),  ya que recomiendan que estén en la misma .dll que las clases que mapean.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;&lt;many-to-one name="Solicitante" class="ViaticosBO.Solicitante,ViaticosBO"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;&lt;many-to-one name="Ida" class="ViaticosBO.Movilidad,ViaticosBO"&gt;&lt;span style="color: rgb(153, 0, 0);"&gt;&lt;many-to-one name="Vuelta" class="ViaticosBO.Movilidad,ViaticosBO"&gt;&lt;hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"&gt;&lt;class name="ViaticosBO.Solicitud, ViaticosBO" table="Solicitud" lazy="false"&gt;&lt;/class&gt;&lt;/hibernate-mapping&gt;&lt;/many-to-one&gt;&lt;/span&gt;&lt;/many-to-one&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Bueno, hasta aquí, esta breve explicación de mi desarrollo con la arquitectura 3 capas usando .NET y NHibernate; no quise profundizar en el uso de ninguna herramienta, sólo mostrar ejemplos del desarrollo a nivel de arquitectura y componentes de soft.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Quedo a las órdenes de cualquiera que desee aportar comentarios sobre mejoras, experiencias, ó preguntas sobre la forma de trabajo; que quizás no hayan quedado del todo claras en este post.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/many-to-one&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-style: italic; color: rgb(153, 51, 153);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 51, 153); font-style: italic;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-5684086464336025547?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/5684086464336025547/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=5684086464336025547' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/5684086464336025547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/5684086464336025547'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/11/desarrollo-en-3-capas-parte-2-la.html' title='Desarrollar en 3 capas con .NET (parte 2) - La controladora y la presentación'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_iGJtoWG_NkY/R0HTtdf9kRI/AAAAAAAAACg/QygnDhkNCKU/s72-c/3+capas-presentacion-viaticosWeb.JPG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-7752634567638687323</id><published>2007-11-15T10:09:00.000-03:00</published><updated>2007-11-15T16:09:34.651-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='objetos de negocio'/><category scheme='http://www.blogger.com/atom/ns#' term='NET'/><category scheme='http://www.blogger.com/atom/ns#' term='desarrollo'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='3 capas'/><title type='text'>Desarrollar en 3 capas con .NET y NHibernate - Parte 1 (Acceso a datos)</title><content type='html'>Luego de haber posteado que es el &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/05/diseo-en-3-capas-fisicas-lgicas-es.html"&gt;diseño en 3 capas&lt;/a&gt;, y &lt;a href="http://metodologiasdesistemas.blogspot.com/2007/10/que-es-un-orm-object-relational-mapping.html"&gt;que es un ORM &lt;/a&gt;con ejemplos de NHibernate, estamos en condiciones de comprender el desarrollo de software mediante esta arquitectura con el framework .NET.&lt;br /&gt;Echemos un vistazo a este diagrama de componentes que aplica esta arquitectura de 3 capas (para el desarrollo de un sistema de viáticos):&lt;br /&gt;&lt;a href="http://bp1.blogger.com/_iGJtoWG_NkY/RzxHJtf9kKI/AAAAAAAAABo/UDbwX387wM0/s1600-h/3capas+BO.JPG"&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://bp2.blogger.com/_iGJtoWG_NkY/RzyUZ9f9kLI/AAAAAAAAABw/XorjRbb-yk4/s1600-h/3capas+BO.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5133140849021784242" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp2.blogger.com/_iGJtoWG_NkY/RzyUZ9f9kLI/AAAAAAAAABw/XorjRbb-yk4/s320/3capas%2BBO.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Podemos ver que además de las capas de presentación, procesos del negocio y acceso a datos, tenemos los objetos de negocio aparte como si de otra capa se tratase. Aunque en la realidad debería estar en la capa del medio, esto presenta problemas en la capa de acceso a datos que pasaría a desconocer los objetos con los que debe trabajar NHibernate en nuestras clases DAO. Para comprender claramente de que estoy hablando debemos ver las clases que se encuentran en cada componente de software.&lt;br /&gt;&lt;br /&gt;Empezando por el &lt;strong&gt;acceso a datos&lt;/strong&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp0.blogger.com/_iGJtoWG_NkY/RzyWjdf9kOI/AAAAAAAAACI/7aicjj2NEdQ/s1600-h/acceso+a+datos-viatico.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5133143211253797090" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/RzyWjdf9kOI/AAAAAAAAACI/7aicjj2NEdQ/s320/acceso+a+datos-viatico.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;NHibernateCore&lt;br /&gt;&lt;br /&gt;Aqui estan : una interfaz para los DAO (data access object) genérica (IDAO), una clase abstracta que implementa IDAO (NHibDAOAbstracto), y manejo de sesiones y transacciones de NHibernate. Su contenido responde al excelente trabajo de Billy McCafferty: &lt;a href="http://www.codeproject.com/aspnet/NHibernateBestPractices.asp"&gt;NHibernate best practices with ASP.Net&lt;/a&gt;, cuya lectura recomiendo, antes de comenzar a desarrollar una capa de acceso a datos.&lt;br /&gt;&lt;br /&gt;Por ej. &lt;em&gt;IDAO:&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public interface IDAO&lt;t,&gt; // maneja Generics de Net 2.0&lt;br /&gt;{&lt;br /&gt;T GetById(IdT id, bool shouldLock);&lt;br /&gt;List&lt;t&gt; GetAll();&lt;br /&gt;List&lt;t&gt; GetByExample(T exampleInstance, params string[] propertiesToExclude);&lt;br /&gt;T GetUniqueByExample(T exampleInstance, params string[] propertiesToExclude);&lt;br /&gt;List&lt;t&gt; Find(string consulta);&lt;br /&gt;IList FindRetLista(string consulta);&lt;br /&gt;T Save(T entity);&lt;br /&gt;T SaveOrUpdate(T entity);&lt;br /&gt;void Delete(T entity);&lt;br /&gt;void CommitChanges();&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;li&gt;ViaticoDAO&lt;/li&gt;&lt;p&gt;&lt;/p&gt;Aquí se encuentran : la fábrica de DAOs, y los DAO de cada objeto de negocio.&lt;br /&gt;Por ej. la clase &lt;em&gt;SolicitudDAO&lt;/em&gt; :&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public class SolicitudDAO : NHibDAOAbstracto&lt;solicitud,int&gt;&lt;solicitud,&gt;, ISolicitudDao &lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;// Hereda del DAO abstracto definido en NHibernateCore e implementa ISolicitudDao &lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;// para no hacer uso directo del DAO abstracto&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;public List&lt;solicitud&gt; DarSolicitudesXSolicitante(Solicitante s, Nullable&lt;datetime&gt; Desde, Nullable&lt;boolean&gt; Aprobadas)&lt;br /&gt;{&lt;br /&gt;string criterios = "FROM Solicitud a WHERE a.Solicitante.ID = " + s.ID.ToString();&lt;br /&gt;&lt;br /&gt;if (Desde != null)&lt;br /&gt;criterios += " and Fecha_soli &gt;=" + ((DateTime)Desde.Value).ToShortDateString();&lt;br /&gt;if (Aprobadas != null)&lt;br /&gt;{&lt;br /&gt;if (Aprobadas == true)&lt;br /&gt;criterios += " and Aprobada=1";&lt;br /&gt;else&lt;br /&gt;criterios += " and Aprobada=0";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;IDaoFabrica daoFabrica = new DAOFabrica();&lt;br /&gt;ISolicitudDao soliDao = daoFabrica.GetSolicitudDao();&lt;br /&gt;&lt;br /&gt;List&lt;solicitud&gt; solicitudes;&lt;br /&gt;solicitudes = soliDao.Find(criterios);&lt;br /&gt;return solicitudes;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Solicitud DarSolicitudXid(int id)&lt;br /&gt;{&lt;br /&gt;IDaoFabrica daoFabrica = new DAOFabrica();&lt;br /&gt;ISolicitudDao soliDao = daoFabrica.GetSolicitudDao();&lt;br /&gt;&lt;br /&gt;Solicitud s = soliDao.GetById(id, false);&lt;br /&gt;return s;&lt;br /&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;ISolicitudDao:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public interface ISolicitudDao : IDAO&lt;solicitud,&gt;&lt;br /&gt;{&lt;br /&gt;List&lt;solicitud&gt; DarSolicitudesXSolicitante(Solicitante s, Nullable&lt;datetime&gt; Desde, Nullable&lt;boolean&gt; Aprobadas);&lt;br /&gt;&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;Solicitud DarSolicitudXid(int id);&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;}&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Por último un ejemplo de DAOFabrica:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public class DAOFabrica : IDaoFabrica&lt;br /&gt;{&lt;br /&gt;public IEmpleadoDao GetEmpleadoDao()&lt;br /&gt;{&lt;br /&gt;return new EmpleadoDAO();&lt;br /&gt;}&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public ICategoriaDao GetCategoriaDao()&lt;br /&gt;{&lt;br /&gt;return new CategoriaDAO();&lt;br /&gt;}&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public ISolicitudDao GetSolicitudDao()&lt;br /&gt;{&lt;br /&gt;return new SolicitudDAO();&lt;br /&gt;}&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;...&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;}&lt;/span&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#000000;"&gt;Lo destacable en esta capa de acceso a datos es su independencia del motor de NHibernate, gracias al uso de la Fábrica de DAOs. Por ej. si quisiera reemplazar el NHibernate por Linq for Sql (del Net 3.0), cambiaría en mis DAOs la herencia de la clase abstracta que implementa los métodos contra el motor de acceso a datos:&lt;/span&gt;&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public class SolicitudDAO : &lt;strong&gt;&lt;span style="color:#663366;"&gt;NHibDAOAbstracto&lt;solicitud,int&gt;&lt;/span&gt;&lt;/strong&gt;, ISolicitudDao &lt;/span&gt;&lt;/em&gt;por&lt;br /&gt;&lt;em&gt;&lt;span style="color:#993399;"&gt;public class SolicitudDAO : &lt;strong&gt;&lt;span style="color:#663366;"&gt;LinqDAOAbstracto&lt;solicitud,int&gt;&lt;/span&gt;&lt;/strong&gt;, ISolicitudDao&lt;/span&gt;&lt;/em&gt; &lt;span style="color:#993399;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#993399;"&gt;&lt;/span&gt;&lt;span style="color:#993399;"&gt;&lt;span style="color:#330033;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#330033;"&gt;Por supuesto deberé desarrollar mi clase LinqDAOAbstracto para que implemente los métodos de la interfaz IDAO.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;En parte 2 veremos la capa de negocio (procesos y reglas; ó controladoras de los casos de uso) y ejemplos de los objetos de negocio, cuyas clases están implementadas en su propio componente.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-7752634567638687323?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/7752634567638687323/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=7752634567638687323' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/7752634567638687323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/7752634567638687323'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/11/desarrollar-en-3-capas-con-net-y.html' title='Desarrollar en 3 capas con .NET y NHibernate - Parte 1 (Acceso a datos)'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_iGJtoWG_NkY/RzyUZ9f9kLI/AAAAAAAAABw/XorjRbb-yk4/s72-c/3capas%2BBO.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-1234704334574076907</id><published>2007-10-31T15:12:00.000-03:00</published><updated>2007-11-16T15:22:13.441-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mapeo objeto relacional'/><category scheme='http://www.blogger.com/atom/ns#' term='ActiveRecord'/><category scheme='http://www.blogger.com/atom/ns#' term='DataMapper'/><category scheme='http://www.blogger.com/atom/ns#' term='NHibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='ORM'/><title type='text'>Que es un ORM (object-relational mapping)</title><content type='html'>El ORM es un componente de software que me permite trabajar con los datos persistidos como si ellos fueran parte de una base de datos orientada a objetos (en este caso virtual). Debido a que lo standard es trabajar con BD relacionales, se deben realizar operaciones que permitan transformar un registro en objeto y viceversa. A esta funcionalidad se la llama &lt;span style="FONT-WEIGHT: bold"&gt;Mapeo objeto-relacional (ORM)&lt;/span&gt;.&lt;br /&gt;Uno de los componentes ORM más utilizado (&lt;span style="FONT-STYLE: italic"&gt;sino el más...&lt;/span&gt;) es el &lt;span style="FONT-WEIGHT: bold"&gt;Hibernate&lt;/span&gt;, surgido del ambiente Java y llevado al uso del framework .NET con la versión NHibernate&lt;br /&gt;Para poder explicar el porqué de la existencia de esta tecnología, nada mejor que un ppt que preparé para una clase sobre este tema a los alumnos del último año de TSSI, que les dejo disponible a continuación.&lt;br /&gt;&lt;br /&gt;&lt;div id="__ss_151705" style="WIDTH: 425px; TEXT-ALIGN: left"&gt;&lt;br /&gt;&lt;embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=persistencia-de-un-modelo-de-objetos-1193856714425414-1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="FONT-SIZE: 11px; PADDING-TOP: 2px; FONT-FAMILY: tahoma,arial; HEIGHT: 26px"&gt;&lt;a href="http://www.slideshare.net/?src=embed"&gt;&lt;img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; MARGIN-BOTTOM: -5px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" alt="SlideShare" src="http://static.slideshare.net/swf/logo_embd.png" /&gt;&lt;/a&gt; &lt;a title="Mira 'Persistencia de un modelo de objetos' en SlideShare" href="http://www.slideshare.net/jercoli/persistencia-de-un-modelo-de-objetos"&gt; Ver ppt &lt;/a&gt; &lt;a href="http://www.slideshare.net/upload"&gt;Upload your own&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;*(Si les aparece el mensaje que "ha sido removido o es privado" pulsen en "VER" &lt;br /&gt;al lado del logo de "slideshare", gracias)&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-1234704334574076907?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/1234704334574076907/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=1234704334574076907' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/1234704334574076907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/1234704334574076907'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/10/que-es-un-orm-object-relational-mapping.html' title='Que es un ORM (object-relational mapping)'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-1604668291979021540</id><published>2007-09-22T19:44:00.000-03:00</published><updated>2007-11-16T09:25:59.251-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patrones de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='herencia'/><category scheme='http://www.blogger.com/atom/ns#' term='interfaces'/><category scheme='http://www.blogger.com/atom/ns#' term='delegacion'/><category scheme='http://www.blogger.com/atom/ns#' term='composicion'/><title type='text'>Sigamos solucionando nuestro diseño con los patrones</title><content type='html'>Siguiendo con nuestra charla de diseño, &lt;strong&gt;determinemos la granularidad de los objetos intervinientes&lt;/strong&gt; .&lt;br /&gt;Los objetos varían enormemente en tamaño y número, y representan cualquier cosa desde hard a sistemas completos, por lo que como decidir que debería ser un objeto?&lt;br /&gt;Veamos algunos patrones:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Fachada (GoF) describe como representar subsistemas ó procesos completos como objetos.&lt;/li&gt;&lt;li&gt;FlyWeight(GoF) describe como permitir un gran número de granularidad muy fina.&lt;/li&gt;&lt;li&gt;Abstract Factory (GoF) produce objetos cuya única resp. es crear otros objetos.&lt;/li&gt;&lt;li&gt;Visitor y Command (GoF) generan objetos cuya resp. es implementar una petición en otros objs. ó grupo de objs.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Especificar las interfaces de los objs.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Los patrones nos ayudan a definir interfaces identificando sus elementos clave y los tipos de datos que se envían a la interfaz. También especifican relaciones entre interfaces, ya que: requieren que algunas clases tengan interfaces parecidas ó les imponen restricciones; por ej:&lt;/p&gt;&lt;p&gt;&lt;em&gt;Decorador y Proxy (GoF) requieren que las interfaces de sus objs. sean idénticos a los objs. deocrado y representado, respectivamente.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Especificar las implementaciones&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Herencia de clases vs. herencia de interfaces&lt;/em&gt;, muchos de los patrones de diseño dependen de esta distinción. Por ej:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Los objs. de una cadena en Chain of Responsability (GoF) deben tener un tipo en común, pero normalmente no comparten la misma implementación.&lt;/li&gt;&lt;li&gt;En Composite (GoF), el componente define una interfaz común mientras que el compuesto suele definir una implementación en común.&lt;/li&gt;&lt;li&gt;Command, Observer, State y Strategy (GoF) suelen implementarse con clases abstractas que son interfaces puras.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;En este tema, debemos tener en mente uno de los principios fundamentales del diseño OO: &lt;strong&gt;&lt;span style="color:#cc0000;"&gt;programar para interfaces, no para una implementación. &lt;/span&gt;&lt;/strong&gt;Por que?&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Ventajas de manipular objs. solamente en términos de la interfaz definida por las clases abstractas. Los clientes no tienen que conocer los tipos específicos de los objs. que usan, basta con que estos adhieran a la interfaz que esperan que esperan los clientes.&lt;/li&gt;&lt;li&gt;Reducción del acoplamiento entre subsistemas.&lt;/li&gt;&lt;li&gt;No se deben declarar variables como instancias de clases concretas, se ajustan simplemente a la interfaz definida por una clase concreta.&lt;/li&gt;&lt;li&gt;Para crear instancias de clases concretas usamos los patrones de creación; estos ofrecen distintos modos de asociar una interfaz con su implementación de manera transparente, y aseguran que el sistema se codifique en términos de interfaces, no de implementación.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Por último, pongamos a &lt;strong&gt;funcionar los mecanismos de reutilización&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Herencia vs. Composición&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Son las 2 técnicas más comunes para reutilizar funcionalidad en sistemas OO. &lt;/p&gt;&lt;p&gt;La &lt;strong&gt;composición&lt;/strong&gt; requiere que los objs. tengan en cta. las interfaces de otros, lo cual requiere interfaces cuidadosamente diseñadas, que no impidan que un obj. sea utilizado por otros. Optar por la composición ayuda a mantener cada clase encapsulada y centrada en una sola tarea. En los patrones de diseño veremos esta técnica aplicada una y otra vez...otro principio fundamental: &lt;span style="color:#cc0000;"&gt;&lt;strong&gt;favorecer la composición de objetos frente a la herencia de clases&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Pero qué es la &lt;strong&gt;composición?&lt;/strong&gt;: método por el cual una nueva funcionalidad se obtiene mediante la creación de un objeto compuesto por otros objetos, ésta se logra delegando funcionalidad a uno de los objs. de la composición.&lt;/p&gt;&lt;p&gt;Mientras que la &lt;strong&gt;Herencia&lt;/strong&gt; es un método por el cual la nueva funcionalidad se obtiene mediante la extensión de la implementación de un objeto existente. La superclase (generalización) captura los métodos y atributos comunes, y las subclases (especializadas) extienden la implementación con métodos y atrib. adicionales. Es más sencilla de llevar a cabo que la composición, pero...&lt;/p&gt;&lt;p&gt;&lt;em&gt;Desventajas de la herencia:&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Rompe la encapsulación, ya que expone la subclase a los detalles de implementación de su superclase&lt;/li&gt;&lt;li&gt;Reutilización de caja blanca, porque los detalles internos de la superclase son visibles a las subclases&lt;/li&gt;&lt;li&gt;Las subclases han de cambiar si la implementación de la superclase cambia&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Entonces que usamos?, según &lt;strong&gt;Coad&lt;/strong&gt;, solo utilizar herencia cuando:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;una subclase expresa "es un tipo de" y no "es un rol desempeñado por".&lt;/li&gt;&lt;li&gt;una instancia de una subclase nunca necesita convertirse en un obj. de otra clase&lt;/li&gt;&lt;li&gt;una subclase extiende las resp. de su superclase, no las redefine ni las anula.&lt;/li&gt;&lt;li&gt;para una clase del problema del dominio actual, la subclase especializa un rol ó una transacción.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Por último utilicemos la &lt;strong&gt;Delegación &lt;/strong&gt;cuando no existan relaciones estáticas entre clases, cuando la herencia no tenga sentido, por ej. para gestionar Roles.&lt;/p&gt;&lt;p&gt;Bien, como vemos obtener un buen diseño es difícil; lo primero que deberíamos saber es : que es un buen diseño?, los conceptos que detallamos antes nos ayudan a dilucidar esta pregunta. Lo segundo será aplicar los principios de diseño de forma sistemática, una buena solución es copiar a los que saben: aplicar los patrones, donde puedan aplicarse.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-1604668291979021540?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/1604668291979021540/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=1604668291979021540' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/1604668291979021540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/1604668291979021540'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/09/sigamos-solucionando-nuestro-diseo-con.html' title='Sigamos solucionando nuestro diseño con los patrones'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-100063774693943396</id><published>2007-09-08T22:43:00.000-03:00</published><updated>2007-09-09T00:12:19.810-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patrones de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='responsabilidad'/><category scheme='http://www.blogger.com/atom/ns#' term='patrones'/><title type='text'></title><content type='html'>&lt;a href="http://bp0.blogger.com/_iGJtoWG_NkY/RuNjXsOdglI/AAAAAAAAAAs/2JZbhtbvTyM/s1600-h/robot+y+patrones.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5108035661028229714" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/RuNjXsOdglI/AAAAAAAAAAs/2JZbhtbvTyM/s200/robot+y+patrones.jpg" border="0" /&gt;&lt;/a&gt; &lt;div&gt;&lt;div&gt;Siguiendo con nuestra charla sobre como los patrones pueden socorrernos en nuestros difíciles momentos de diseño, veamos como &lt;em&gt;"encontrar los objs. apropiados para asignarles responsabilidades".&lt;/em&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Coincidamos en que lo más complicado del DOO es descomponer un sistema en objetos. &lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Para lograr este objetivo, resumamos las &lt;em&gt;tareas del análisis&lt;/em&gt;:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Partimos de encontrar los conceptos de nuestro dominio de problema y así efectuar un modelo conceptual donde identificamos las clases que surgen del negocio (nuestros objs. de negocio) y sus asociaciones.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Luego deberíamos obtener diag. de secuencia del sistema (basados en nuestros CU) donde determinemos los eventos y operaciones del sistema&lt;br /&gt;&lt;/li&gt;&lt;li&gt;En este punto sería importante obtener los "contratos" de los CU, donde se responderá: que hacen las operaciones del sistema?. Mediante la descripción de las postcondiciones de los contratos podemos describir cómo cambia el sistema tras cada operación; esta descripción se realiza en términos de : creación y destrucc. de objetos, asociac. formadas y canceladas y modificac. de atributos.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Con toda esta documentación podremos comenzar nuestra tarea creativa más importante en el desarrollo de un sistema: el DISEÑO. &lt;/div&gt;&lt;img id="BLOGGER_PHOTO_ID_5108035300250976834" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp0.blogger.com/_iGJtoWG_NkY/RuNjCsOdgkI/AAAAAAAAAAk/qYU7urfJM0A/s200/guru.gif" border="0" /&gt; Ahora asignemos responsabilidad a nuestros objetos, aunque aclaremos que existen 2 categorías de responsabilidades: de Conocer y de Hacer. &lt;p&gt;&lt;em&gt;Conocer&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;los datos privados encapsulados&lt;/li&gt;&lt;li&gt;los objetos relacionados&lt;/li&gt;&lt;li&gt;las cosas que puedan derivarse ó calcular&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Hacer&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;algo el mismo: crear un obj. ó hacer un cálculo&lt;/li&gt;&lt;li&gt;iniciar una acción en otros objs.&lt;/li&gt;&lt;li&gt;controlar y coordinar actividades en otros objs.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Para asignar responsabilidad a nuestros objs. , hablemos de 3 patrones Grasp: &lt;span style="color:#336666;"&gt;Experto en información, Creador y Controlador. (&lt;span style="font-size:85%;"&gt;es.wikipedia.org/wiki/Grasp&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#336666;"&gt;&lt;em&gt;experto en informac.&lt;/em&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;: asignar la resp. a la clase que tiene la informac. necesaria para realizarla. Esto debe hacerse sin generar nuevos acoplamientos, manteniendo la cohesión alta. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#336666;"&gt;&lt;em&gt;creador:&lt;/em&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; asignar a la clase B la resp. de crear un obj. de la clase A si se cumple que: &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;B agrega objs. de A&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;B contiene objs. de A&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;B registra objs. de A&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;B usa objs. de A cercanamente (directa)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;B tiene los datos de inicialización que se pasan a un obj. A cuando es creado&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Debemos agregar que muy a menudo la creación de un obj. es de alta complejidad, por lo que sería aconsejable delegar la creación a clases auxiliares llamadas "&lt;strong&gt;Fábricas&lt;/strong&gt;" (factorys)&lt;/p&gt;&lt;p&gt;&lt;span style="color:#336666;"&gt;&lt;em&gt;controlador: &lt;/em&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;asignar la resp. de recibir ó gestionar un mensaje de evento del sistema a una clase que:&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;represente el sistema global ó subsistema (&lt;strong&gt;Fachada&lt;/strong&gt;)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;represente un escenario de CU en el que tiene lugar el evento (&lt;strong&gt;controladora de CU&lt;/strong&gt; ó sesión)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Tener en cuenta que un controlador debería delegar en otros objs. el trabajo que se necesita hacer, sólo coordina y controla la actividad (compuesta de varias tareas).&lt;/p&gt;Seguimos en el próximo....&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-100063774693943396?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/100063774693943396/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=100063774693943396' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/100063774693943396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/100063774693943396'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/09/siguiendo-con-nuestra-charla-sobre-como.html' title=''/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_iGJtoWG_NkY/RuNjXsOdglI/AAAAAAAAAAs/2JZbhtbvTyM/s72-c/robot+y+patrones.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-8623145617007963767</id><published>2007-09-07T14:13:00.000-03:00</published><updated>2007-11-21T09:07:40.941-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cohesion'/><category scheme='http://www.blogger.com/atom/ns#' term='abierto-cerrado'/><category scheme='http://www.blogger.com/atom/ns#' term='acoplamiento'/><category scheme='http://www.blogger.com/atom/ns#' term='patrones de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='principios de diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='Diseño OO'/><title type='text'>Principios de diseño - Como llegamos a los Design Patterns??</title><content type='html'>&lt;a href="http://bp3.blogger.com/_iGJtoWG_NkY/RuKxQsOdgjI/AAAAAAAAAAc/0cgKLD2_9SM/s1600-h/yingyang.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5107839827699401266" style="margin: 0px 10px 10px 0px; float: left;" alt="" src="http://bp3.blogger.com/_iGJtoWG_NkY/RuKxQsOdgjI/AAAAAAAAAAc/0cgKLD2_9SM/s200/yingyang.gif" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;En una charla con mis alumnos de último año, intenté describir el proceso de pensamiento que nos lleva a la aplicación de los patrones de diseño.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Para empezar debemos recordar los conceptos básicos del diseño (no exclusivos del DOO), nuestro &lt;strong&gt;ying y yang&lt;/strong&gt; : &lt;strong&gt;&lt;em&gt;Acoplamiento y Cohesión&lt;/em&gt;&lt;/strong&gt;, el 1ro. que determina el nivel de dependencia y el 2do. el nivel de unión interno (realizar una única función)&lt;/p&gt;&lt;p&gt;OK, teniendo en mente aquello, intentemos comprender los términos: &lt;strong&gt;Responsabilidad e independencia, &lt;/strong&gt;con un diagrama UML de paquetes.&lt;/p&gt;Por ej.:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_iGJtoWG_NkY/R0QepNf9kTI/AAAAAAAAACw/doW9p2nvYyw/s1600-h/Dependencia+en+paquetes.bmp"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp3.blogger.com/_iGJtoWG_NkY/R0QepNf9kTI/AAAAAAAAACw/doW9p2nvYyw/s320/Dependencia+en+paquetes.bmp" alt="" id="BLOGGER_PHOTO_ID_5135263168456397106" border="0" /&gt;&lt;/a&gt;Un paquete X del cual dependen muchos paquetes debe ser muy estable. No debe cambiar porque es &lt;strong&gt;Responsable&lt;/strong&gt; de los 3 paquetes que dependen de él.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;X es &lt;strong&gt;Independiente&lt;/strong&gt;, no depende de nadie.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Su &lt;strong&gt;Estabilidad&lt;/strong&gt; = Responsabilidad + Independencia&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;&lt;br /&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Existe alguna medida sencilla para saber que tan estable es un paquete?&lt;/em&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Factor de Inestabilidad (I) =&gt; &lt;strong&gt;I=(Ce / (Ca + Ce)).&lt;/strong&gt; Si I[0,1]=0 será totalmernte estable.&lt;/p&gt;&lt;p&gt;Donde : &lt;em&gt;Ca&lt;/em&gt; (&lt;span style="font-size:85%;"&gt;cuan responsable soy?)&lt;/span&gt; son clases fuera del paquete que dependen del él. &lt;em&gt;Ce &lt;/em&gt;&lt;span style="font-size:85%;"&gt;(cuan dependiente soy) &lt;/span&gt;&lt;em&gt;&lt;/em&gt;son clases del paquete que dependen de clases externas a él.&lt;/p&gt;&lt;p&gt;"La estabilidad de un paquete debe ser proporcional a su nivel de &lt;strong&gt;Abstracción" &lt;span style="font-size:85%;"&gt;(R.Martin-1996)&lt;/span&gt;;&lt;/strong&gt; esto implica que los paquetes con máxima estabilidad deben ser abstractos; y los inestables concretos.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;Esto nos lleva a entender que aquellas decisiones de diseño y arquitectura de alto nivel de abstracción no suelen cambiar, así que los situaremos en paquetes estables. Aquí surge una pregunta interesante: &lt;em&gt;como puede un paquete totalmente estable (I=0) ser lo suficientemente flexible como para soportar los cambios?&lt;/em&gt;. O sea, mejorarlo sin cambiarlo.&lt;br /&gt;Respuesta, otro principio : &lt;strong&gt;Abierto-Cerrado&lt;/strong&gt;. Clases que puedan ser extendidas sin modificar lo ya existente: &lt;em&gt;clases abstractas.&lt;/em&gt;&lt;br /&gt;&lt;p&gt;Ahora bien, cuando intentamos seguir estos principios básicos del diseño, descubrimos que las estructuras que desarrollamos para cumplirlos, se repiten una y otra vez; esto es lo que conocemos como &lt;strong&gt;"Patrón de diseño". &lt;/strong&gt;Estos deben ser soluciones probadas a los problemas de diseño más comunes, resolviéndonos los sig. puntos:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Encontrar los obj. apropiados para asignarles responsabilidad.&lt;/span&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Determinar la granularidad (su nivel de abstracción) de los objetos.&lt;/span&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Especificar sus interfaces.&lt;/span&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Especificar las implementaciones que deben tener los objs. involucrados.&lt;/span&gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Poner a funcionar los mecanismos de reutilización&lt;/span&gt;&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Ahora debemos diferenciar 2 viejas categorías de patrones de diseño: GRASP y GoF&lt;/p&gt;&lt;p&gt;Los GRASP no implementan las soluciones, más bien nos llevan a pensar en el diseño, a nivel de principios generales &lt;span style="font-size:85%;"&gt;(más principios de DOO...); &lt;/span&gt;&lt;span style="font-size:100%;"&gt;mientras que los GoF nos dan una solución implementable con su propio diagrama de clases que nos muestra la forma en que debemos usarlos.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;En próximas notas iremos viendo los patrones relacionados con cada uno de los 5 puntos que nos resuelven los patrones (patterns).&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-8623145617007963767?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/8623145617007963767/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=8623145617007963767' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/8623145617007963767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/8623145617007963767'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/09/principios-de-diseo-como-llegamos-los.html' title='Principios de diseño - Como llegamos a los Design Patterns??'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_iGJtoWG_NkY/RuKxQsOdgjI/AAAAAAAAAAc/0cgKLD2_9SM/s72-c/yingyang.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3703334709787879039.post-2101662999970811708</id><published>2007-05-28T15:37:00.000-03:00</published><updated>2007-11-16T09:27:32.432-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='3 capas'/><category scheme='http://www.blogger.com/atom/ns#' term='3 tiers'/><title type='text'>Diseño en 3 capas? fisicas ó lógicas? es igual a patrón MVC?</title><content type='html'>Diseñar en &lt;span style="color:#000099;"&gt;3 capas&lt;/span&gt;...trata sobre no poner todo tu código en las interfaces de usuario de tu sistema (IU). Para subsanar esto, la idea es tener 3 niveles de funcionalidad bien definidos :&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="COLOR: rgb(255,0,0)"&gt;&lt;span style="color:#000099;"&gt;Capa de presentación&lt;/span&gt;, &lt;span style="COLOR: rgb(0,0,0)"&gt;con nuestras IU (formularios windows, páginas HTML,..) y sus controles visuales (textBox, comboBox, dataGrids) junto con sus eventos (los click y etc.)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="COLOR: rgb(255,0,0)"&gt;&lt;span style="COLOR: rgb(0,0,0)"&gt;&lt;span style="COLOR: rgb(153,102,51)"&gt;&lt;span style="color:#000099;"&gt;Capa de negocio&lt;/span&gt; &lt;span style="color:#000099;"&gt;(lógica del dominio),&lt;/span&gt;&lt;span style="COLOR: rgb(0,0,0)"&gt; aqui ira todo el código que define las reglas de negocio (cálculos, validaciones). Surge de los procesos que hemos encontrado en el análisis.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="COLOR: rgb(255,0,0)"&gt;&lt;span style="COLOR: rgb(0,0,0)"&gt;&lt;span style="COLOR: rgb(153,102,51)"&gt;&lt;span style="COLOR: rgb(0,0,0)"&gt;&lt;span style="COLOR: rgb(0,102,0)"&gt;&lt;span style="color:#000099;"&gt;Capa de acceso a datos&lt;/span&gt;, &lt;span style="COLOR: rgb(0,0,0)"&gt;el código que permite acceder a las fuentes de datos. Esencialmente trata sobre 4 operaciones básicas, llamadas CRUD (por Create-Retrieve-Update y Delete), que se realizan sobre cualquier fuente de datos (normalmente alguna base de datos relacional).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Debajo de esta última se encontrará la FUENTE de DATOS que permite la persistencia de los mismos en algún medio físico.&lt;br /&gt;&lt;br /&gt;Este diseño corresponde a las &lt;span style="COLOR: rgb(204,0,0)"&gt;&lt;span style="color:#000099;"&gt;3 capas lógicas (3 layers)&lt;/span&gt;&lt;span style="COLOR: rgb(0,0,0)"&gt;. No confundir con las capas físicas ó parte &lt;span style="color:#663366;"&gt;(3 tiers)&lt;/span&gt; que corresponden al lugar donde se instalan los componentes de software.&lt;br /&gt;&lt;br /&gt;En &lt;span style="color:#cc0000;"&gt;&lt;span style="color:#663366;"&gt;3 tiers&lt;/span&gt; &lt;span style="color:#000000;"&gt;la ejecución está distribuida:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR: rgb(204,0,0)"&gt;&lt;span style="COLOR: rgb(0,0,0)"&gt;&lt;span style="color:#cc0000;"&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#663366;"&gt;Front-End&lt;/span&gt;, donde se ejecutan las IU del cliente. Los Browsers.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#663366;"&gt;MiddleWare&lt;/span&gt;, recibe solicitudes de las IU a través de la red. Estos son mensajes (XML, SOAP,...) que se envían mediante protocolos de transporte (HTTP,TCP,UDP,..). El Servidor Web.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#663366;"&gt;BackEnd&lt;/span&gt;, nuestra base de datos ó algún proceso externo a nuestro software.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Por último "&lt;span style="color:#006600;"&gt;Modelo-Vista-Controlador&lt;/span&gt;" es un patrón de diseño de arquitectura que está asociado a la idea de 3 capas (3 layers), aunque su objetivo es aún más fino. El mismo se centra en la secuencia de ejecución, desde que se produce un evento en la capa de presentación hasta que el mismo es atendido en forma completa.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp1.blogger.com/_iGJtoWG_NkY/Rl8EveabmoI/AAAAAAAAAAM/u_8gqGEU58s/s1600-h/MVC-interactions.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5070776919106755202" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp1.blogger.com/_iGJtoWG_NkY/Rl8EveabmoI/AAAAAAAAAAM/u_8gqGEU58s/s320/MVC-interactions.gif" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Las partes que lo componen son:&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#006600;"&gt;Vista&lt;/span&gt;: componente que recibe el estímulo y genera un evento, que puede involucrar a otros objetos de la IU. Corresponde a la capa de presentación, y al Front-End(en Web:Html, JavaScript,...), aunque suele haber parte en el MiddleWare (controles ASP,PHP,...)&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#006600;"&gt;Modelo&lt;/span&gt;: componente asociado a las entidades de negocio (cliente, factura, pago,...). En 3 capas incluye parte de la capa de negocio (entidades, pero no lógica de procesos) y toda la capa de acceso a datos. En 3 tiers se instala en el BackEnd (la BD) y parte en el MiddleWare (entidades de negocio y acceso a datos).&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#006600;"&gt;Controlador&lt;/span&gt;: componente asociado a la lógica de procesos del negocio. En 3 capas la parte que faltaba y en 3 tiers en el MiddleWare.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="color:#000000;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3703334709787879039-2101662999970811708?l=metodologiasdesistemas.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://metodologiasdesistemas.blogspot.com/feeds/2101662999970811708/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3703334709787879039&amp;postID=2101662999970811708' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/2101662999970811708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3703334709787879039/posts/default/2101662999970811708'/><link rel='alternate' type='text/html' href='http://metodologiasdesistemas.blogspot.com/2007/05/diseo-en-3-capas-fisicas-lgicas-es.html' title='Diseño en 3 capas? fisicas ó lógicas? es igual a patrón MVC?'/><author><name>Jorge Ercoli</name><uri>http://www.blogger.com/profile/02715540175040996960</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://bp3.blogger.com/_iGJtoWG_NkY/R9q3h2Mg-VI/AAAAAAAAAJ4/4JuJ2_i_eXw/S220/fotoParaBlog.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_iGJtoWG_NkY/Rl8EveabmoI/AAAAAAAAAAM/u_8gqGEU58s/s72-c/MVC-interactions.gif' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
