programación en 3 capas

25
Programación en 3 capas Hola a todos: Después de tantos meses de tener abandonado el Blog por fin hoy se libera un espacio en mi agenda, tiempo que he decidido compartir con todos y cada uno de ustedes. En este articulo hablare y tratare de explicar con los detalles mas mínimos que es la arquitectura 3 capas, cuales son sus ventajas, como empezar un proyecto 3 capas, cuales son las diferencias entre cada una de ellas, como comunicarlas y como crear un proyecto con la arquitectura 3 capas utilizando Visual Studio 2012. Antes de comenzar a leer este articulo recuerde que: “El objetivo no es otro mas que el de orientar a los Parvulos .Net sobre la arquitectura de software 3 capas, todo lo escrito en este articulo no es ensayado, no es revisado por nadie mas, por lo cual podría contener errores gramaticales y sintácticos, el articulo y sus conceptos no pretenden ser la verdad absoluta del tema, siéntase en confianza de dejar sus comentarios y opiniones en la sección de comentarios al final del mismo y si lo considera prudente envíeme un correo electrónico por medio del formulario de contacto y por ultimo si el articulo le es de utilidad por favor considere dejar un comentario de agradecimiento. Requisitos: Visual Studio 2012, Framework 4.0, el proveedor de datos SqlCompact 4.0 instalado en su equipo y muchas ganas de aprender. Como siempre recomiendo encarecidamente que antes de descargar los proyectos de ejemplo (que les pondré al final de articulo), traten de hacerlo ustedes mismos siguiendo paso a paso todo lo que se mencionara aquí, si tienen dudas en uno en especifico no duden en contactarme. Dicho todo lo anterior, comencemos… Arquitectura 3 capas en .Net ¿Ha creado usted software?…¿Si?, entonces sabe lo complejo que resulta crear rutinas y funciones para cada uno de los formularios, importar todas las referencias del motor de base de datos en cada uno de los formularios, cambiar código aquí y allá (porque tiene copias del mismo código en muchos lugares), escribir la lógica de validación de campos dentro del evento, corregir los bugs que pudieran presentarse y no se diga de implementarles mejoras al software, etc., ¿No? entonces no se preocupe este es un buen manual de como evitarse muchos dolores de cabeza en diseño de su arquitectura a seguir. Para que se de una mejor idea de que hablo, por favor descargue este proyecto de ejemplo, ejecútelo, analice el código, observe como para realizar una misma funcionalidad en dos lugares diferentes tuvimos que escribir casi las mismas líneas de código. A partir de aquí en adelante estaremos trabajando con el proyecto

Upload: roly-manuico-flores

Post on 02-Dec-2015

45 views

Category:

Documents


2 download

DESCRIPTION

Vb.Net 2010

TRANSCRIPT

Page 1: Programación en 3 Capas

Programación en 3 capasHola a todos:

Después de tantos meses de tener abandonado el Blog por fin hoy se libera un espacio en mi agenda, tiempo que he decidido compartir con todos y cada uno de ustedes.

En este articulo hablare y tratare de explicar con los detalles mas mínimos que es la arquitectura 3 capas, cuales son sus ventajas, como empezar un proyecto 3 capas, cuales son las diferencias entre cada una de ellas, como comunicarlas y como crear un proyecto con la arquitectura 3 capas utilizando Visual Studio 2012.

Antes de comenzar a leer este articulo recuerde que: “El objetivo no es otro mas que el de orientar a los Parvulos .Net sobre la arquitectura de software 3 capas, todo lo escrito en este articulo no es ensayado, no es revisado por nadie mas, por lo cual podría contener errores gramaticales y sintácticos, el articulo y sus conceptos no pretenden ser la verdad absoluta del tema, siéntase en confianza de dejar sus comentarios y opiniones en la sección de comentarios al final del mismo y si lo considera prudente envíeme un correo electrónico por medio del formulario de contacto y por ultimo si el articulo le es de utilidad por favor considere dejar un comentario de agradecimiento.”

Requisitos: Visual Studio 2012, Framework 4.0, el proveedor de datos SqlCompact 4.0 instalado en su equipo y muchas ganas de aprender.

Como siempre recomiendo encarecidamente que antes de descargar los proyectos de ejemplo (que les pondré al final de articulo), traten de hacerlo ustedes mismos siguiendo paso a paso todo lo que se mencionara aquí, si tienen dudas en uno en especifico no duden en contactarme.

Dicho todo lo anterior, comencemos…

Arquitectura 3 capas en .Net

¿Ha creado usted software?…¿Si?, entonces sabe lo complejo que resulta crear rutinas y funciones para cada uno de los formularios, importar todas las referencias del motor de base de datos en cada uno de los formularios, cambiar código aquí y allá (porque tiene copias del mismo código en muchos lugares), escribir la lógica de validación de campos dentro del evento, corregir los bugs que pudieran presentarse y no se diga de implementarles mejoras al software, etc., ¿No? entonces no se preocupe este es un buen manual de como evitarse muchos dolores de cabeza en diseño de su arquitectura a seguir.

Para que se de una mejor idea de que hablo, por favor descargue este proyecto de ejemplo, ejecútelo, analice el código, observe como para realizar una misma funcionalidad en dos lugares diferentes tuvimos que escribir casi las mismas líneas de código. 

A partir de aquí en adelante estaremos trabajando con el proyecto descargado, aplicándole la Arquitectura 3 capas para demostrar como esta Arquitectura de Diseño nos ayuda a: Separar responsabilidades, cada capa tiene una función especifica y no interviene con la de las demás.

Reutilizar código

La separación de roles en tres capas, hace mas fácil reemplazar o modificar a una, sin afectar a los módulos restantes

Page 2: Programación en 3 Capas

El código de la capa intermedia puede ser reutilizado por múltiples

Capacidad de migrar nuestro motor de Base de Datos sin grandes impactos al resto del proyecto.

Poder cambiar el Front de nuestra aplicación sin afectar a la lógica de nuestra aplicación ni a la Base de datos

Bien como ya hemos mencionado La Arquitectura de diseño 3 capas, consiste en dividir el diseño del software en sus tres principales componentes: 1. La Interfaz o UI (User interface): Esta Capa es la encargada de interactuar con el usuario, es decir, son aquellas ventanas, mensajes, cuadros de diálogos o paginas web (en el caso del desarrollo web), que el usuario final utiliza para comunicarse con la aplicación, por medio de esta capa el usuario solicita que se ejecuten las tareas proporcionando parámetros de entrada y recibiendo datos como respuesta. Esta capa se comunica con la capa de Lógica de Negocio, enviando y solicitando información y con la capa de Entidades usando sus objetos para enviar y recibir esta información.

2. La lógica de negocio o Business Logic: Se encarga de implementar, como su nombre lo dice, la lógica del negocio, es decir, todo lo que el Software debe de considerar antes de realizar una acción o el proceso que debe de seguir después de realizar una acción. Por ejemplo: Antes de solicitar a la capa de Datos la inserción de un grupo de registros en una tabla, valida que vayan todos los campos mandatorios dentro de esa solicitud si esta condición no se cumple entonces rechaza la inserción e informa del usuario del status de su solicitud; otro ejemplo podria ser, solicitar a la base de datos que valide la presencia de un registro antes de insertar el siguiente, validar los tipos de datos, etc. esos ejemplos por mencionar los mas básicos y generales. Esta capa recibe de la Capa de Presentación las solicitudes, valida que las condiciones que establece el negocio se cumplan antes de realizar dicha acción o de hacer la respectiva solicitud a la Capa de Acceso a Datos

3. El acceso a Datos o Data Access: Esta capa es la encargada de la comunicación con la base de datos, en esta capa descansaran todas nuestras acciones CRUD (Create, Read, Update y Delete), será la única que “sabrá” que motor de base de datos se esta utilizando pero le será completamente desconocido el “front”, es decir, jamás sabrá si nuestra aplicación es una aplicación web o desktop. Se encarga de recibir las peticiones de la Capa de Lógica de Negocio, ejecutar dichas acciones y devolver el resultado a la misma capa. 

4. Capa de Entidades o Entity Layer: Aunque aparentemente es una cuarta capa realmente no lo es, esta capa se encarga de contener todos aquellos objetos (clases) que representan al negocio, y esta es la única que puede ser instanciada en las 3 capas anteriores, es decir, solo ella puede tener comunicación con el resto pero su función se limita a únicamente ser un puente de transporte de datos. Esta capa complementa a la Capa de Negocio

Page 3: Programación en 3 Capas

Para una mejor compresión de la comunicación de las 3 capas:

Hasta aquí, hemos visto la teoría de lo que representa la Arquitectura 3 Capas, pero…

 ¿Como es que debo representar la Arquitectura 3 Capas en un proyecto de Visual Studio?

Para haya es a donde vamos.

1. Abra el Visual Studio 2012 y cree un proyecto Vacío y nómbrelo “CSharp-3Capas-Primer Entrega”

2. Diríjase al “Explorador de soluciones” y haga click derecho sobre el proyecto que acabamos de crear:

Page 4: Programación en 3 Capas

3. Del menú desplegado seleccione Agregar->Nuevo Proyecto:

4. Seleccione, Instalado –> Visual C# –> Windows –> Aplicación de Windows Forms –> En el campo Nombre escriba, “Tienda-Presentacion” y presione el botón “Aceptar”.

Page 5: Programación en 3 Capas

5. Repita el paso 2, 3 y en el 4°, seleccione un tipo de proyecto “Biblioteca de Clases” y establezca como nombre “Tienda-LogicaNegocio”

6.Repita el paso 2, 3 y en el 4°, seleccione un tipo de proyecto “Biblioteca de Clases”utilice el nombre “Tienda-AccesoDatos”

7. Repita el paso 2, 3 y en el 4°, seleccione un tipo de proyecto “Biblioteca de Clases” utilice el nombre “Tienda-Entidades”

¿Como va nuestro diseño’'?

Observe que cuando creamos el proyecto principal en automático se creo un proyecto vacío, eliminemos ese proyecto para dejar la siguiente estructura:

Ahora ya tenemos nuestra estructura completa, observe que creamos 4 proyectos dentro del principal (que lo iniciamos como proyecto vacío), recuerde que el proyecto de Entidades en este caso “Tienda-Entidades” no es una capa, mas bien, complementa a la capa de Lógica de Negocio.

Continuemos con nuestro diseño…

Page 6: Programación en 3 Capas

Capa de Entidades

Recuerde que en esta capa estarán alojados los objetos (clases) con los cuales estaremos trabajando, con estos objetos estaremos persistiendo las tablas de la base de datos que utilizaremos.

La base de datos que usaremos contiene una sola tabla llamada “Producto” la cual contiene 5 campos (Id ‘int’, Descripción ‘nvarchar’, Marca ‘nvarchar’,  Precio ‘nvarchar’), por lo cual la Capa de Entidades contendrá un Objeto llamado Producto con 5 propiedades publicas cada uno de ellos respetando el tipo de dato con el cual esta declarado en la base de datos.

Para declarar nuestra Entidad Producto:

1. Agregue una clase al proyecto “Tienda-Entidades” y llámela “EProducto” (La letra ‘E’ es por conveción, es decir, todos los objetos de nuestra capa de Entidades llevaran la letra ‘E’ al principio para que desde donde las lleguemos a utilizar sepamos que ese Objeto es una Entidad evitando con esto confusiones con otros objetos), dentro agregue las siguientes líneas de código:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Tienda_Entidades{ public class EProducto { public int Id { get; set; } public string Descripcion { get; set; } public string Marca { get; set; } public decimal Precio { get; set; } }}

Si tuviéramos mas tablas en nuestra base de datos tendríamos que crear la misma cantidad de objetos en nuestra capa de Entidades y dentro contendrían la misma cantidad de propiedades como campos tiene la tabla siempre respetando el tipo de dato con lo que estos campos están declarados.

Capa de acceso a Datos

Recordemos que la capa de datos es usada por la capa de lógica y la capa de lógica es llamada por la capa de presentación, así que usaremos ese mismo orden para crear nuestras configuraciones y nuestras líneas de código.

1. Agreguemos un archivo de configuración (App.Config) a nuestra capa de datos recuerde que una de las características principales del archivo de configuraciones es que podemos establecer una cadena de conexión la cual accederemos fácilmente desde cualquier lugar del proyecto que lo contiene, que es lo que en esta ocasión nos interesa. 

Page 7: Programación en 3 Capas

Nuestro archivo de configuraciones lo tenemos que agregar en nuestro proyecto de presentación, y no porque lo vaya a utilizar sino que nuestro software cada vez que arranque buscara este archivo en el directorio desde donde se este ejecutando la aplicación, para efectos de prueba será en la carpeta “..bin\debug” pero cuando nuestro proyecto este instalado, el archivo quedara desplegado justo en la carpeta raíz de nuestra instalación junto con el “.exe” por tal motivo deberá de estar en el mismo proyecto que esta marcado como proyecto de inicio.

Para agregar un archivo de configuraciones siga estos pasos:

- Click derecho sobre el proyecto “Tienda-AccesoDatos –> Agregar –> Nuevo elemento

2. En el proyecto que descargaron anteriormente si observaron viene embebida un archivo de base de datos llamado DataBase1.sdf que noes otra cosa mas que un archivo de base de datos propios del motor SQlCompact, cree una carpeta en la unidad C y llámela “Proyecto-3Capas”, después copien este archivo en ese path.

3. Abran el archivo de configuraciones desde el Explorador de soluciones, Copien las siguientes líneas de código, borren el contenido del App.Config  y péguenlas en su lugar:

<?xml version="1.0" encoding="utf-8" ?><configuration> <configSections> </configSections> <connectionStrings> <add name="cnnString" connectionString="Data Source=C:\Proyecto-3Capas\Database1.sdf" providerName="Microsoft.SqlServerCe.4.0" /> </connectionStrings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup></configuration>

Page 8: Programación en 3 Capas

Observen que el  DataSource apunta a la carpeta que acabamos de crear en la unidad C “Data Source=C:\Proyecto-3Capas\Database1.sdf", esta cadena en proyetos reales normalmente apuntara a un servidor de datos, pero para fines ilustrativos, este directorio nos servirá muy bien.

Volvamos a nuestra Capa de Datos

4. Agreguemos las referencias a las librerías System.Configuration para esto, Click sobre nuestra capa de datos (proyecto “Tienda-AccesoDatos”) –> Agregar Referencia

5. Agregue una segunda referencia ahora a System.Data.SqlServeCe (esta librería no siempre aparece, si este es su caso presione el botón Examinar localice la Dll dentro de archivos de programa y selecciónela), presione Aceptar.

6. Ya tenemos nuestro App.Config(en el proyecto de arranque) apuntando a nuestra base de datos y tenemos las dos referencias que necesitamos, System.Configuration para poder accesar y leer el archivo de configuraciones y el System.Data.SqlServerCe para poder usar los objetos de acceso a datos propios del motor SQLCOMPACT en nuestra Capa de Datos.

Como nuestra capa de Acceso a Datos, debe de tener la capacidad de Insertar, Leer,

Page 9: Programación en 3 Capas

Actualizar y Eliminar registros de la tabla Productos, requiere de una comunicación directa con la capa de Entidades, para por ejemplo, al momento de que se le solicite la inserción de un Producto en lugar de enviarle 5 parámetros con los datos del producto se le envié un Objeto y ¿Cual será este objeto? nada mas y nada menos que nuestro objeto EProductocreado en la capa de Entidades, de esta manera ya no trabajaremos con datos sino con objetos llenando, enviando y leyendo propiedades.

Para lograr la comunicación entre la Capa de Datos y la Capa de Entidades se requiere de la referencia de una en la otra, en este caso la referencia de la Capa de Entidades dentro de la Capa de Datos, para ello:

7. Click derecho sobre nuestro proyecto “Tienda-AccesoDatos” –> Agregar Referencia

8. Solución –> Proyectos –> Seleccione “Tienda-Entidades”

Observe como se a creado un nuevo elemento en nuestra carpeta de Referencias del proyecto “Tienda-AccesoDatos”

Page 10: Programación en 3 Capas

9. Inserte una clase nueva llamada “ProductoDal”  de donde Dal vendrá de Data Access Layer, dentro de la clase que acaba de crear tiene que declarar el espacio de nombres System.Configuration, System.Data.SqlServerCe y del proyecto de Entidades, además tiene que declarar la clase como publica (para que la Capa de Lógica de Negocio pueda tener acceso a ella)

Ya tenemos el puente de comunicación entre nuestras Entidades y nuestra Capa de Datos. Solo resta comenzar a codificar las acciones que querramos hacer con nuestra tabla Producto, recuerde que el objeto ProductoDalúnicamente tiene como responsabilidad trabajar con todo aquello relacionado con Producto, así que comencemos haciendo la codificación para Insertar, Traer todos los registros existentes en nuestra tabla Producto, Traer, Actualizar y Eliminar por Id. 

Para hacer esta tarea mas sencilla le proporcionare el código que deberá de poner en la clase “ProductoDal”, pero, trate de escribir el código para vaya analizando la estructura del mismo.

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;//nuestras importaciones del Espacio de nombres que estaremos utilizando, //recuerde que estas son las referencias que realizamos hace unos momentos...

Page 11: Programación en 3 Capas

using System.Configuration;using System.Data.SqlServerCe;using Tienda_Entidades;namespace Tienda_AccesoDatos{ //Definimos el acceso de nuestra clase como public, asegurando con esto su accesibilidad desde //otros proyectos. public class ProductoDal { //Primero y siguiendo el orden de las acciones CRUD //Crearemos un Método que se encarga de insertar un nuevo Producto es nuestra tabla Producto /// <summary> /// Inserta un nuevo Producto en la tabla Producto /// </summary> /// <param name="producto">Entidad contenedora de los valores a insertar</param> /// <autor>José Luis García Bautista</autor> public void Insert(EProducto producto) { //Creamos nuestro objeto de conexion usando nuestro archivo de configuraciones using (SqlCeConnection cnx = new SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString())) { cnx.Open(); //Declaramos nuestra consulta de Acción Sql parametrizada const string sqlQuery = "INSERT INTO Producto (Descripcion, Marca, Precio) VALUES (@descripcion, @marca, @precio)"; using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx)) { //El primero de los cambios significativos con respecto al ejemplo descargado es que aqui... //ya no leeremos controles sino usaremos las propiedades del Objeto EProducto de nuestra capa //de entidades... cmd.Parameters.AddWithValue("@descripcion", producto.Descripcion); cmd.Parameters.AddWithValue("@marca", producto.Marca); cmd.Parameters.AddWithValue("@precio", producto.Precio);

cmd.ExecuteNonQuery(); } }

Page 12: Programación en 3 Capas

}

/// <summary> /// Devuelve una lista de Productos ordenados por el campo Id de manera Ascendente /// </summary> /// <returns>Lista de productos</returns> /// <autor>José Luis García Bautista</autor> public List<EProducto> GetAll() { //Declaramos una lista del objeto EProducto la cual será la encargada de //regresar una colección de los elementos que se obtengan de la BD // //La lista substituye a DataTable utilizado en el proyecto de ejemplo List<EProducto> productos = new List<EProducto>();

using (SqlCeConnection cnx = new SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString())) { cnx.Open();

const string sqlQuery = "SELECT * FROM Producto ORDER BY Id ASC"; using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx)) { SqlCeDataReader dataReader = cmd.ExecuteReader(); // //Preguntamos si el DataReader fue devuelto con datos while (dataReader.Read()) { // //Instanciamos al objeto Eproducto para llenar sus propiedades EProducto producto = new EProducto { Id = Convert.ToInt32(dataReader["Id"]), Descripcion = Convert.ToString(dataReader["Descripcion"]), Marca = Convert.ToString(dataReader["Marca"]), Precio = Convert.ToDecimal(dataReader["Precio"]) }; //

Page 13: Programación en 3 Capas

//Insertamos el objeto Producto dentro de la lista Productos productos.Add(producto); } } } return productos; }

/// <summary> /// Devuelve un Objeto Producto /// </summary> /// <param name="idProducto">Id del producto a buscar</param> /// <returns>Un registro con los valores del Producto</returns> /// <autor>José Luis García Bautista</autor> public EProducto GetByid(int idProducto) { using (SqlCeConnection cnx = new SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString())) { cnx.Open();

const string sqlGetById = "SELECT * FROM Producto WHERE Id = @id"; using (SqlCeCommand cmd = new SqlCeCommand(sqlGetById, cnx)) { // //Utilizamos el valor del parámetro idProducto para enviarlo al parámetro declarado en la consulta //de selección SQL cmd.Parameters.AddWithValue("@id", idProducto); SqlCeDataReader dataReader = cmd.ExecuteReader(); if (dataReader.Read()) { EProducto producto = new EProducto { Id = Convert.ToInt32(dataReader["Id"]), Descripcion = Convert.ToString(dataReader["Descripcion"]), Marca = Convert.ToString(dataReader["Marca"]), Precio = Convert.ToDecimal(dataReader["Precio"]) };

return producto; } }

Page 14: Programación en 3 Capas

}

return null; }

/// <summary> /// Actualiza el Producto correspondiente al Id proporcionado /// </summary> /// <param name="producto">Valores utilizados para hacer el Update al registro</param> /// <autor>José Luis García Bautista</autor> public void Update(EProducto producto) { using (SqlCeConnection cnx = new SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString())) { cnx.Open(); const string sqlQuery = "UPDATE Producto SET Descripcion = @descripcion, Marca = @marca, Precio = @precio WHERE Id = @id"; using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx)) { cmd.Parameters.AddWithValue("@descripcion", producto.Descripcion); cmd.Parameters.AddWithValue("@marca", producto.Marca); cmd.Parameters.AddWithValue("@precio", producto.Precio); cmd.Parameters.AddWithValue("@id", producto.Id);

cmd.ExecuteNonQuery(); } } }

/// <summary> /// Elimina un registro coincidente con el Id Proporcionado /// </summary> /// <param name="idproducto">Id del registro a Eliminar</param> /// <autor>José Luis García Bautista</autor> public void Delete(int idproducto) { using (SqlCeConnection cnx = new SqlCeConnection(ConfigurationManager.ConnectionStrings["cnnString"].ToString())) { cnx.Open();

Page 15: Programación en 3 Capas

const string sqlQuery = "DELETE FROM Producto WHERE Id = @id"; using (SqlCeCommand cmd = new SqlCeCommand(sqlQuery, cnx)) { cmd.Parameters.AddWithValue("@id", idproducto);

cmd.ExecuteNonQuery(); } } } }}

Observe como desde nuestros diferentes Métodos y funciones estamos haciendo uso del objeto EProductodeclarado en la capa de Entidades…Observe también como nuestra clase ProductosDal no valida que el valor de las propiedades de EProducto contengan datos o sean del tipo de dato correcto porque ese ¿es trabajo de?…La Capa de Lógica de Negocio

Capa de Lógica de Negocio

Recuerde que la capa de Lógica es la encargada de establecer toda la lógica que el negocio establece para llevar a cabo una acción o después de haber realizado un proceso, y esta se comunica directamente con la Capa de Acceso a Datos, por lo cual tenemos que hacer la referencia al Proyecto “Tienda-AccesoDatos” y para ello:

1. Click derecho sobre nuestro proyecto “Tienda-LogicaNegocio” –> Agregar Referencia

8. Solución –> Proyectos –> Seleccione “Tienda-AccesoDatos” y “Tienda-Entidades”

Page 16: Programación en 3 Capas

Observe como se acaban de agregar nuestras referencias:

9. Agregue una nueva clase y llámela “ProductoBol”, haga los using de las referencias que acabamos de crear, establezca el nivel de acceso como public y copie la siguiente estructura de código:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;////Hacemos las importaciones del espacio de nombres de los dos proyectos que referenciamos//observe como esta capa solo referencio a Tienda-AccessData y no a Tienda-Presentacion//observe también como aquí no es requerida la referencia a System.Data.SqlServerCe

Page 17: Programación en 3 Capas

using Tienda_AccesoDatos;using Tienda_Entidades;namespace Tienda_LogicaNegocio{ public class ProductoBol { //Instanciamos nuestra clase ProductoDal para poder utilizar sus miembros private ProductoDal _productoDal = new ProductoDal(); // //El uso de la clase StringBuilder nos ayudara a devolver los mensajes de las validaciones public readonly StringBuilder stringBuilder = new StringBuilder();

// //Creamos nuestro método para Insertar un nuevo Producto, observe como este método tampoco valida los el contenido //de las propiedades, sino que manda a llamar a una Función que tiene como tarea única hacer esta validación // public void Registrar(EProducto producto) { if(ValidarProducto(producto)) { if (_productoDal.GetByid(producto.Id) == null) { _productoDal.Insert(producto); } else _productoDal.Update(producto); } }

public List<EProducto> Todos() { return _productoDal.GetAll(); }

public EProducto TraerPorId(int idProduct) { stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor proporcione un valor de Id valido");

if(stringBuilder.Length == 0) { return _productoDal.GetByid(idProduct); }

Page 18: Programación en 3 Capas

return null; } public void Eliminar(int idProduct) { stringBuilder.Clear();

if (idProduct == 0) stringBuilder.Append("Por favor proporcione un valor de Id valido");

if (stringBuilder.Length == 0) { _productoDal.Delete(idProduct); } }

private bool ValidarProducto(EProducto producto) { stringBuilder.Clear();

if (string.IsNullOrEmpty(producto.Descripcion)) stringBuilder.Append("El campo Descripción es obligatorio"); if (string.IsNullOrEmpty(producto.Marca)) stringBuilder.Append(Environment.NewLine + "El campo Marca es obligatorio"); if (producto.Precio <= 0) stringBuilder.Append(Environment.NewLine + "El campo Precio es obligatorio");

return stringBuilder.Length == 0; } }}

Analice cada uno de los métodos y funciones que creamos en nuestro primer objeto de nuestra capa de Negocio, observe: Cada uno de ellos tiene una sola responsabilidad

La capa de negocio cumple otras tareas y no solo la de ser un puente entre nuestra Capa de Datos  y nuestra Capa de Presentación

Como es que estamos usando únicamente objetos y no controles, recuerde que esta capa tampoco sabe que tipo de proyecto es el que la estará usando.

Observe que esta capa no tiene referencias a System.Configuration ni mucho menos aSystem.Data.SqlServerCe.

Observe que en esta capa también se utiliza la Capa de Entidades.

Capa de Presentación o User Interface

Le toca el turno a la Capa de Presentación entrar en escena, esta capa será la encargada de interactuar con el usuario, la vista de todo nuestro sistema, la encargada de recoger las peticiones del usuario y de pasar esta misma a la capa de Lógica de Negocio, todo lo que el usuario requiera se la solicitara a esta y todo lo que Lógica de Negocio devuelva esta se la mostrar al usuario en forma de datos.

Page 19: Programación en 3 Capas

Para configurar nuestra Capa de Presentación.

10. Haga las referencias a los proyecto “Tienda-LogicaNegocio” y “Tienda-Entidades”

11. En el formulario que tenemos por default llamado “Form1” diseñe una interfaz como la siguiente:

12. Observe las siguientes líneas de código, genere los eventos involucrados y copie el código de ejemplo:

using System;using System.Collections.Generic;

Page 20: Programación en 3 Capas

using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;////Hacemos las importaciones del espacio de nombres de los dos proyectos que referenciamos//observe como esta capa solo referencio a Tienda-LogicNegocio y a Tienda-Entidades//observe como no se referencia a la clase de acceso a Datosusing Tienda_LogicaNegocio;using Tienda_Entidades;namespace Tienda_Presentacion{ public partial class Form1 : Form { // // //Creamos las instancias de la clase Eproducto y ProductoBol private EProducto _producto; private readonly ProductoBol _productoBol = new ProductoBol();

public Form1() { InitializeComponent(); }

// //Creamos los métodos generales llenando y leyendo objetos // private void Guardar() { try { if (_producto == null) _producto = new EProducto();

_producto.Id = Convert.ToInt32(txtId.Text); _producto.Descripcion = txtDescripcion.Text; _producto.Marca = txtMarca.Text; _producto.Precio = Convert.ToDecimal(txtPrecio.Text);

_productoBol.Registrar(_producto);

if (_productoBol.stringBuilder.Length != 0) { MessageBox.Show(_productoBol.stringBuilder.ToString(), "Para continuar:");

Page 21: Programación en 3 Capas

} else { MessageBox.Show("Producto registrado/actualizado con éxito");

TraerTodos(); } } catch (Exception ex) { MessageBox.Show(string.Format("Error: {0}", ex.Message), "Error inesperado"); } }

private void TraerTodos() { List<EProducto> productos = _productoBol.Todos();

if (productos.Count > 0) { dgvDatos.AutoGenerateColumns = false; dgvDatos.DataSource = productos; dgvDatos.Columns["columnId"].DataPropertyName = "Id"; dgvDatos.Columns["columnDescripcion"].DataPropertyName = "Descripcion"; dgvDatos.Columns["columnMarca"].DataPropertyName = "Marca"; dgvDatos.Columns["columnPrecio"].DataPropertyName = "Precio"; } else MessageBox.Show("No existen producto Registrado"); }

private void TraerPorId(int id) { try { _producto = _productoBol.TraerPorId(id);

if (_producto != null) { txtId.Text = Convert.ToString(_producto.Id); txtDescripcion.Text = _producto.Descripcion; txtMarca.Text = _producto.Marca; txtPrecio.Text = Convert.ToString(_producto.Precio); } else

Page 22: Programación en 3 Capas

MessageBox.Show("El Producto solicitado no existe"); } catch (Exception ex) { MessageBox.Show(string.Format("Error: {0}", ex.Message), "Error inesperado"); } }

private void Eliminar(int id) { try { _productoBol.Eliminar(id);

MessageBox.Show("Producto eliminado satisfactoriamente");

TraerTodos(); } catch (Exception ex) { MessageBox.Show(string.Format("Error: {0}", ex.Message), "Error inesperado"); } }

// // //Usamos nuestros metodos y funciones generales, observe como no hemos repetido codigo en ningun lado //haciendo con esto que nuestras tareas de actualizacion sean mas sencillas para nosotros o para //al asignado en realizarlas... private void btnAgregar_Click(object sender, EventArgs e) { Guardar(); }

private void txtId_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Enter && !string.IsNullOrWhiteSpace(txtId.Text)) { e.SuppressKeyPress = true;

TraerPorId(Convert.ToInt32(txtId.Text)); } }

Page 23: Programación en 3 Capas

private void txtPrecio_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Enter) { e.SuppressKeyPress = true;

Guardar(); } }

private void btbnBuscar_Click(object sender, EventArgs e) { if (!string.IsNullOrWhiteSpace(txtId.Text)) { TraerPorId(Convert.ToInt32(txtId.Text)); } }

private void btnEliminar_Click(object sender, EventArgs e) { if (!string.IsNullOrWhiteSpace(txtId.Text)) { Eliminar(Convert.ToInt32(txtId.Text)); } } }}

De nuevo observe como esta capa desconoce si existe una capa de Datos y mucho menos que motor de base de datos se utiliza, tampoco se encarga de implementar las reglas de validación ni de lógica de negocio, su tarea es interactuar con el usuario pidiendo y desplegando información. 

¿Que es lo que falta?

Solo nos resta probar el proyecto…pero eso, será tarea suya…Ejecute el proyecto, inserte un nuevo registro, busque un registro por id, edite su información, elimine un producto, depure el código línea a línea para viva de paso a paso como es que va pasando de capa de capa enviando y trayendo información.

Aquí termina nuestro articulo sobre Arquitectura 3 Capas, espero haya sido de su agrado y que la explicación haya sido lo bastante clara, en caso de que tenga alguna duda por favor deje su pregunta en la sección de comentarios o escríbame por medio del formulario de contacto.

Escribir este articulo me llevo mas de 4 horas, dejar un comentario de agradecimiento le tomara 5 minutos.