domingo, 21 de febrero de 2010

Acceso a datos

¿Cómo acceder a nuestra Base de Datos? ¿Cómo organizar las clases?

Empezare por comentar que la creación de nuestras clases y componentes debe buscar seguir un principio “alta cohesión y bajo acoplamiento”. Esto quiere decir que no debemos tener clases que sean todologas, por el contrario deben aislar la responsabilidad de una funcionalidad especifica. ¿Han manejado código con sentencias DML en el front End, les suena? Bueno eso es exactamente una de las cosas que no debemos hacer .
¿Tres capas, como es? Es separar la responsabilidad de nuestra aplicación en tres grandes bloques:
1)Acceso a datos
2)Capa de negocio
3)Front-End , que es nuestra interfaz.

Han manejado reglas de negocio directamente en un formulario Windows o Web? Eso es lo que debemos evitar. ¿Y si un día nos piden que hagamos un proceso Batch que involucran a nuestras clases o una aplicación Windows cuando era Web y tenemos reglas del negocio en todas partes? A eso me refiero con aislar responsabilidades.

Capa de Acceso a datos
Crearemos un proyecto de librería de clases , para el ejemplo usare el proveedor de datos de SQL, existe EnterpriseLibrary 4 que nos da otras bondades pero eso lo veremos en otra entrega
Agregar el espacio de nombres a la clase
Agregar la referencia a System.Configuration
Por ahora a nuestro componente de acceso a Datos solo le agregare un método para la ejecución de store procedure (executeNonQuery).
Las clases que deben agregar son :

NOTA , TODAS LA IMAGENES SE AGRANDAN AL DAR CLICK SOBRE ELLAS


Clase Parameter ,esta clase nos permitira "envolver" lo que normalmente hariamos con objectos de tipo SqlParameter, esto lo hice asi, pensando en un futuro modificar el componente de acceso a datos para cualquier proveedor, es decir al consumidor le damos un objecto de tipo parametro pero generico.

Clase DataAcces : Tendra metodos para realizar peticiones a la Base de datos (executeNonQuery, ExecuteScalar,etc..), habiamos platicado de los parametros que requerimos pasar a una petición a la BD,¿como pasarlos?Finalmente es una colección, recurriremos a Generics usando un diccionario personalizado del tipo la clase parametro.

La clase la prepararemos de tal forma que nos permita manejar transacciones. exhibiendo un metodo para iniciar una transacción, un metodo para confirmarla, y un metodo para rechazarla, nuestra clase ademas nos permitira establecer el nivel de aislamiento con el que queremos que se efectuen nuestras peticiones a la Base de Datos, en otra entrega hablaremos de los diferentes niveles de aislamiento.

Tambien implementaremos la interfaz IDisposable para prevenir que nuestro componente deje conexiones abiertas en la Base de Datos




Capa de Negocio

Agregaremos otro proyecto de clases a nuestra solución que nos servirá como capa de negocio. El cual deberá tener una referencia a nivel proyecto del componente de acceso a datos.

Nuestra capa de negocio debe tener implementadas todas las reglas de negocio, si con el tiempo nos pidieran hiciéramos un proceso Batch por ejemplo de facturas , imaginen el costo de tener en el front-end las reglas de cómo hacer una factura (por poner un ejemplo) .


En nuestro componente de acceso a datos implementaremos una práctica denominada “Inversor de control”, que nos permite “acoplar” fuertemente dos clases ,se que suena a contradicción con lo que escribir arriba pero les explicare: Hemos mencionado que no queremos crear clases todologas, esta práctica nos permitirá mover la responsabilidad de crear una instancia de una clase concreta a su manejador .


.

Es decir tendremos una clase que exhibe las propiedades de un cliente, y otra clase que sabe grabar, actualizar, abrir un cliente.
1)Agregar una clase que contendra las propiedades del cliente

2)Agregar una clase que contendrá solo los métodos que reciben o devuelven un cliente para operarlo.





El escenario comun cuando tenemos un catalogo(o al menos el que mas he visto) es que se crea una clase con las propiedades, en ella misma los metodos para manipular la información del catalogo, la mayor parte de las veces usando parametros para cada campo en un metodo grabar, eso NO es una buena practica.

¿Como trabaja por citar un ejemplo el proveedor de datos de sql? Con objectos, de esa manera empezamos a garantizar que lo que grabo es un cliente , un objecto cliente.

Espero no hacer confusa esta parte, para que este ejemplo sirva un poco mas , crearemos un método que grabe registros (uno por uno) y otro método que pase un XML con el contenido de lo que deseamos grabar.

3)Crear una tabla (con la que trabajaremos el ejemplo :


4)Crear un store procedure para administrar las excepciones (SQL 2005/2008)


5)Crear un store procedure para grabar registro por registro
5)Crear un store procedure para grabar registro por registro , creamos otro store solo para ejemplificar las transacciones,aunque pudiera ser el mismo.


6)Crear un store procedure para grabar en una sola petición el contenido de un XML



Capa de presentación

La capa de presentación pudiera ser un proyecto Web, windows o cualquier otro que nos ofresca una UI

Agregamos una referencia al componente de negocio
El siguiente paso que tenemos es consumir nuestras clases en el Front-End

private void grabar()
{

try
{
MCliente objMcliente = new MCliente();
ICliente objCliente;
objCliente = objMcliente.Create();
objCliente.Apellido = "MiApellido";
objCliente.Nombre = "MiNombre";
objCliente.Observaciones = "MisObservaciones";
objMcliente.Save(objCliente);
}
catch (Exception)
{

throw;
}
}



Esto es solo el principio, cuando hablamos de capas, lo que queremos es sobre todo aislar resposabilidades. El tema es amplio, este ejemplo solo pretende resumir en breves pasos como debemos ordenar nuestro proyecto en capas.
Si desean descargar el codigo lo pueden bajar de la dirección :

Crisis

Este es un texto que en palabras menos,mas o exactas esta en la red, y me gusta mucho...

"No pretendamos que las cosas cambien, si siempre hacemos lo mismo. La crisis es la mejor bendición que puede sucederle a personas y países, porque la crisis trae progresos. La creatividad nace de la angustia como el día nace de la noche oscura. Es en la crisis que nace la inventiva, los descubrimientos y las grandes estrategias. Quien supera la crisis se supera a sí mismo sin quedar 'superado'.
Quien atribuye a la crisis sus fracasos y penurias, violenta su propio talento y respeta más a los problemas que a las soluciones. La verdadera crisis, es la crisis de la incompetencia. El inconveniente de las personas y los países es la pereza para encontrar las salidas y soluciones.
Sin crisis no hay desafíos, sin desafíos la vida es una rutina, una lenta agonía. Sin crisis no hay méritos. Es en la crisis donde aflora lo mejor de cada uno, porque sin crisis todo viento es caricia. Hablar de crisis es promoverla, y callar en la crisis es exaltar el conformismo. La creatividad nace de la angustia como el día nace de la noche oscura. Es en la crisis que nace la inventiva, los descubrimientos y las grandes estrategias
En vez de esto, trabajemos duro. Acabemos de una vez con la única crisis amenazadora, que es la tragedia de no querer luchar por superarla"

domingo, 7 de febrero de 2010

Clases parciales C#

Las clases parciales vienen a resolver una problemática que a nosotros los desarrolladores se nos presenta cuando trabajamos en un equipo y necesitamos “compartir una clase”. Muchos de ustedes seguramente conocen el concepto de controlador de versiones como el VSS y muchos más gratuitos, básicamente nos permiten atrapar/bloquear un archivo para que solo pueda ser modificado por una persona a la vez, ¿pero qué sucede si más de un programador requiere cambiar alguna funcionalidad de un método en una clase? Anteriormente solo nos quedaba esperar o si la urgencia lo ameritaba nos arriesgábamos a modificar o agregar y al último unir los cambios. Microsoft ha resuelto esta problemática con la aparición de Clases y métodos parciales,los cuales nos permiten cambiar al mismo tiempo en una clase métodos y propiedades y en su caso agregarlos, ¿pero cómo trabaja?

1) Es necesario agregar la palabra reservada partial a la clase : partial class MiClase {}
2) Es necesario crear diferentes archivos físicos de tipo clase (pueden vivir en el mismo, pero entonces no se me ocurre para que la tendríamos parcial)
3) Tener una definición de la clase parcial en cada uno de los archivos
4) Crear el metodo o metodos nuevos en uno de los archivos de la misma clase parcial que no esta atrapada(si tuvieramos este problema en un ambiente con contralador de versiones).

Veamos el ejemplo :
1)La clase inicial

2)Creando otro archivo y agregando otra definición de nuestra clase parcial y un nuevo metodo


Consumiendo la clase :


Finalmente cuando nuestra clase esta siendo consumida nosotros podemos verla como una sola, y los metodos y propiedades que pudieran estar creados en diferentes archivos seran visibles en nuestra clase .

Espero que les sea de utilidad esta información.

El placer de compartir

Hola, es un enorme gusto para mi poder contribuir en algo a los demás, procurare hacer estas entregas lo menos espaciadas, y siempre que quieran contactarme por correo háganlo y encontraran en mi una mano extendida ,aunque quizá no siempre con todas las respuestas.
MCP, MCTS, carlos.nabor@gmail.com

Serialización Parte I C#

¿Qué es serializar? Bueno intentare explicarlo de la forma en que a mí me hubiera gustado aprenderlo.
Me parece que los conceptos deberían ser enseñados a partir de una necesidad primeramente, de un problema, de un escenario. Empecemos…
En muchas de nuestras aplicaciones cuando la funcionalidad que damos se vuelve cada día mayor es necesario intercambiar información digamos más compleja que un simple dato de tipo carácter o numérico, podemos pensar quizá en los datos completos de un empleado (nombre, edad, domicilio, RFC, foto, etc...) o incluso una colección de ellos. Este intercambio puede ser entre aplicaciones, a nivel de Base de datos, usando la misma plataforma que la nuestra o incluso una distinta y con plataforma me refiero no solo al sistema operativo, sino que también a la tecnología con la que estamos desarrollando. ¿Qué sucederá cuando necesitemos comunicarnos con una aplicación echa en Java por poner un ejemplo?





Pues bien, la serialización viene al rescate, ya tenemos el escenario, nuestro problema está en la mesa. Tenemos nuestras clases, instancias concretas de esas clases y necesitamos almacenar y transmitir esa información. Aquí empezare a hacer hincapié que la serialización no es la panacea y que ahora debamos grabar así siempre en la Base de Datos o mandar de esa forma la información a otros sistemas, NO AHÍ COSAS BUENAS O MALAS, existen necesidades especificas y soluciones y está en nosotros saber identificar cuando debemos usar una pistola o un matamoscas.
Empezaremos con la serialización en formato binary, serializar es el proceso de crear un stream de bytes a partir de un objeto (una instancia concreta). Supongamos que tenemos una clase que se llama Empleado.





Si nosotros queremos serializar un objeto de esa clase necesitamos agregar el atributo [Serializable] a nuestra clase, si intentáramos serializar una clase que no tiene este atributo se generara una excepción.







Retomando lo que veníamos platicando si serializar es colocar nuestra instancia concreta en un stream de bytes ¿qué mas necesitamos?


1)Una instancia de nuestra clase Empleado


2)Un objeto de tipo stream que es donde almacenaremos nuestra instancia en un formato diferente, en este caso usaremos un objeto de tipo FileStream, esta clase nos proporciona nada menos que 15 constructores, usaremos lo necesario y eso es solo indicar el nombre del archivo que se generara y el modo en que estamos creando el objecto que es Create.


3)Requerimos por ultimo especificar la forma en que vamos a serializar,para serailizar en formato binary requerimos un objecto de tipo BinaryFormatter, este objecto nos permitira con el metodo “Serialize” serializar nuestra instancia concreta en el archivo stream que creamos, es decir lo vaciamos.





Hasta aquí hemos visto como convertir nuestra información de un objeto , ahora ¿qué sucede cuando necesitamos recuperar el objeto que serializamos?


1) Requerimos una variable del tipo de nuestra clase (NO una instancia).


2) Requerimos nuevamente un objeto de tipo stream para esta vez abrir el archivo que se genero y que contiene nuestra información serializada.


3) Requerimos nuevamente el objeto de tipo BinaryFormatter para esta vez con su metodo “Deserialize” deserealizar nuestra información y por ultimo hacer un cast de la información que hemos deserializado y setearlo a la variable que creamos en el paso 1








Comentarios :

I)BinaryFormatter es la mejor opción para serializar y deserializar objectos que solo seran interpretados por aplicaciones desarrolladas en .NETFrameWork
II)Existen otros "formateadores" XML , SOAP y Custom Serialization que son mas adecuados para ambientes que involucran sistemas operativos y aplicaciones ajenas al NetFrameWork e incluso a Windows y que nos permiten mayor flexibilidad.
III)Es una buena practica hacer nuestras clases serializables, aun cuando no tengamos claro si se usara, el dicho es "si ahi duda haslas serializables".

Los espacios de nombre utilizados fueron :
System.Runtime.Serialization.Formatters
System.Runtime.Serialization.Formatters.Binary
System.IO

Y regresando a la mecanica de plantear problemas dejo la pauta para la parte II con lo siguiente :
¿y si quiero que algunos miembros no sean serializables?
¿Como evitar problemas de compatibilidad entre versiones de mis clases?¿que pasa si agrego una nueva propiedad despues de que las clases ya estan siendo consumidas?
¿cual es la mejor practica para propiedades calculadas?

Como ven esto es solo el comienzo, en entregas posteriores continuaremos hablando de este tema, pues aun tenemos tela de donde cortar. Saludos y ojala les haya sido util esta información