Tag Archive for .net

.NET y Configuraciones – Parte 6

Bueno, miren que lejos hemos llegado con el asunto de las configuraciones :) pero no se preocupen, aún falta mucho más que aprender sobre nuestros amigos los archivos app/web.config y sobre nuestras configuraciones personalizadas, imagínense un mundo con menos y con configuraciones más claras y con mayor significado para el desarrollador. Hasta el momento hemos explorado secciones, grupos de secciones, elementos, colecciones todas personalizadas, hoy aprenderemos un poco acerca de validadores.

Element Validators

Imagínense que en su sistema de configuración necesitan validar que el número ingresado por el usuario en la configuración se encuentre dentro de un rango, o que el texto ingresado cumpla con una expresión regular o cumpla una longitud mínima o máxima (si, ya se, ambos se pueden lograr con un regex, pero para efectos de ejemplo digamos que son dos diferentes). Muchos quizás nos veremos tentados a obtener el valor de la configuración y posteriormente validarlo, bien, en el caso de elementos de configuración es buena idea abstenerse de hacerlo. La buena noticia es que tenemos a nuestra disposición toda una infraestructura de validación de valores de configuración y esta se lleva a cabo en el momento en que el ConfigurationManager lee los valores.

Los Validators son atributos especiales que acompañan a nuestros elementos de configuración, podemos definir nuestros propios validadores (ese será el tema de un post futuro) pero por defecto la framework nos empaca un par de validadores simples y sencillos:

IntegerValidator Valida un entero dentro de un rango
LongValidator Valida un número dentro de un rango
PositiveTimeSpanValidator Valida un timespan dentro de un rango positivo
RegexStringValidator Valida que una cadena cumple con una expresión regular
StringValidator Valida que una cadena debe cumplir una longitud máxima/mínima
TimeSpanValidator Valida un timespan dentro de un rango

Usar los validadores no puede ser más sencillo, simplemente adornamos nuestras propiedades o elementos con el atributo del validador que nos interesa y la framework de configuración se encarga del resto

using System;
using System.Configuration;

namespace Samples {
    public class SampleConfigurationSection : ConfigurationSection {
        [ConfigurationProperty("port", DefaultValue = 80)]
        [IntegerValidator(MaxValue = 100, MinValue = 20)]
        public int Port {
            get { return (int) this["port"]; }
        }

        [ConfigurationProperty("host", IsRequired = true)]
        public string Host {
            get { return (string) this["host"]; }
        }

        [ConfigurationProperty("timeout")]
        [TimeSpanValidator(MinValueString = "00:00:00",
            MaxValueString = "00:01:00")]
        public TimeSpan Timeout {
            get { return (TimeSpan) this["timeout"]; }
        }
    }
}

Para probar la configuración podemos usar este simple app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="sample" type="Samples.SampleConfigurationSection, ValidatorSample"/>
  </configSections>
  <sample host="localhost" port="80" timeout="00:00:30" />
</configuration>

Y este pequeño programa de consola puede servirnos como simple prueba

using System;
using System.Configuration;

namespace Samples {
    internal class Program {
        private static void Main(string[] args) {
            var cfg = ConfigurationManager.GetSection("sample")
                as SampleConfigurationSection;
            if (cfg == null)
                return;

            Console.WriteLine("Host: {0}, Port: {1}, Timeout: {2}",
                cfg.Host, cfg.Port, cfg.Timeout);

            Console.ReadLine();
        }
    }
}

Si algún elemento no cumple con lo esperado por el validador el ConfigurationManager tirará una excepción de tipo ConfigurationErrorsException que a su vez en la propiedad Errors contendrá los ConfigurationException en forma de arreglo.

El espejismo de la separación por “capas”

Algo que comúnmente escucho en el círculo de desarrolladores (especialmente de .Net) es la frase “esto va en la capa de datos” o un “esta regla de negocio esta en la capa de negocio” y hasta un “mira, esta hecho pero aún no están bien separadas las capas”.

Esta palabrita, “capas”, es una de esas buzzwords de arquitectura microsoftica que nos han quedado grabadas en el cerebro, y que debido a que ha sido usada por tanto tiempo, ya la decimos instintivamente y hasta llegamos a creer que si un developer no habla en “capas” no es de respetar.

Comencemos a analizar lo que nos venden cuando hablamos de “capas”. Por lo general la terminología de capas se aplica a la típica arquitectura jerárquica de tres niveles, denotando responsabilidades diferentes y niveles de acceso variables en cada una de ellas, siendo la más conocida de todas la arquitectura de “tres capas”: Data Layer, Business Layer, Presentation Layer.

IC351011

Personalmente creo que este tipo de “ensamblaje” cobra bastante sentido si desarrollabas hace más de 5 años atrás, es decir, los ORM eran “escasamente” conocidos, los DataSet’s reinaban en el mundo de Ado.Net, los webservices no eran más que una extensión de la ASP.NET framework, el desarrollo en Windows y Web se limitaba en su gran extensión a arrastrar y soltar controles sobre un lienzo y crear un test era cosa de escribir en un papel y decirle a alguien que “probara la aplicación”… ¡ahhh, épocas lejanas aquellas! (bueno, creo que mucho de lo que menciono aquí aún esta presente en la lucha hasta el sol de hoy, pero ese es otro tema).

Actualmente muchos siguen desarrollando de esa manera, algunos han llevado esto aún más lejos y se han atrevido a hablar de arquitecturas de dos capas y hasta de n-capas… Hay libros, guías (como esta) y muchísimos posts en internet conversando de como usar Nhibernate o la Entity Framework en un entorno de n capas, como concurso, mientras más capas tenga tu aplicación, mayor será tu “mérito”.

He llegado a entender a aquellos defensores de las arquitecturas por capas, y en base a ello he formulado un conjunto de opciones por las cuales aún hablamos acerca de “capas”

  • Han tanta lógica en la base de datos que hay que distinguir las reglas embebidas en la base de datos de aquellas embebidas en cualquier otro lugar, por lo tanto, hablamos de las reglas de la “capa de datos”
  • La base de datos es mi salvador, por lo tanto debo separarla y distinguirla del resto de código “mortal” de la aplicación
  • La presentación de los datos es tan compleja, que bueno, el codebehind es inmenso y merece tener su propia “capa” debido al tamaño
  • Sigo usando DataSets o procedimientos almacenados que son leídos por DataReaders y al final debo manipularlos para sacar los datos de una factura, consumidor o lo que sea, por lo tanto tengo que distinguir esas responsabilidades en su propia “capsula”
  • No sé que rayos es un Tier y a falta de mejor palabra le llamo Layer

Como sea, pronto conversaremos de porqué el concepto de “capa” está un poco pasado de moda y las opciones que tenemos a la mano para reemplazar la ya vieja arquitectura por capas por una mucho más holística basada en modelos de comportamiento y responsabilidades modeladas a base del dominio y no por imaginación de un arquitecto.

Como siempre, estoy abierto a comentarios en la zona de comentarios, twitter, mail o cualquier otro medio por el cual esporádicamente puedan encontrarme.

¡Hasta la próxima!

Repository, IQueryable y otras hierbas

Desde hace varios días hay una thread muy interesante acerca de separación de responsabilidades, repositorio, validación y otras hierbas en la lista de correo d Alt.Net Hispano, antes de continuar, les recomiendo una merecida lectura.

El punto expuesto por José Romaniello y que a su vez toma como base las enseñanzas de Fabio Maulo no puede estar más cargado de razón. Anteriormente como menciona Carlos Peix, cuando Fowler y Eric Evans en su libro DDD definieron Repository no existía el concepto de IQueryable y creo que no muchos se lo veían venir, así que simplemente si asociamos que Repository es una abstración superior del acceso a datos y este se debe comportar como una colección en memoria (mezclando las definiciones de Fowler y Evans) y coincidimos en que en la .Net Framework las colecciones pueden extenderse a IQueryable, es fácil razonar que por definición un repositorio finaliza implementando IQueryable<T> (mera jalada mi filosofía y asociación, pero para filósofo preguntémosle mejor a @ajlopez!)

Bien, sin embargo exponer IQueryable<T> directamente tiene un par de problemas e implicaciones, principalmente relacionados con la semántica de la colección y el acceso a ella. Estoy desacuerdo que la definición o diferencia entre dao y repository es cada vez más difusa, de hecho, comparto la visión de usar un Dao y exponer el acceso a los datos a través de ella, ahora bien, la pregunta del millón se traduce en la siguiente, cómo debe lucir mi Dao? Quizás algo similar a como lo expone Fabio y José:

public interface IDao<T> {
    IQueryable<T> Retrieve(Expression<Func<T, bool>> predicate);
    IQueryable<T> Count(Expression<Func<T, bool>> predicate);
}

¿Un momento, porqué exponer IQueryable<T> y no IEnumerable<T>? O sea, no estoy dándole a mis consumidores demasiado poder en lo que pueden lograr o hacer?

En el punto de exponer IQueryable<T> y IEnumerable<T> y así evitar problemas posteriores tiene defensores y enemigos por todos lados. Personalmente estoy deacuerdo con exponer IQueryable<T> en el repositorio e inclusive exponer un método para facilitarte el query de los elementos (y no hacerlo “directamente” usando una consulta LINQ inline). Verás, el meollo de todo es evitar andar abriendo clases como si fueramos cirujanos.

Si exponemos métodos como “GetUserById(5)” y este a su vez expone IEnumerable<T> esta bien (para ese uso en *específico*) pero recordemos que por lo general un repositorio será expuesto para múltiples usos (o sea, no solamente para obtener usuarios con ese Id, ¿qué tal si luego quieres obtener la lista de usuarios? ¿y si quieres filtrarla?, ni hablemos del problema eterno del pagineo…

Bien, he aquí cuando se nota la utilidad de la separación de concerns de presentación con todo lo demás, por ejemplo, recordemos que el Controller es un _concern de presentación_ así mismo como es la vista (si, señores, como vengo dicíendolo por mucho tiempo, el controller *no es* la lógica del negocio, simplemente es la lógica del presentador).

Ok, llevemos esto más allá, es probable que tengamos “casos de uso” de lógica relacionada a la presentación, no a la del negocio, por ejemplo, el típico concern de búsqueda de elementos, las opciones de búsqueda, filtrado, son conerns meramente de la lógica relacionada a la presentación, eso involucra entonces que debemos permitir que nuestro controller (o presenter, dependiendo del patrón de presentación usado) directamente actúe contra la dao? muchos proponentes dicen que no debe ser así (y ellos mismos hasta se contradicen si los estudian detenidamente). Más de alguien me contestará que simplemente realizar la consulta mediante Specification es suficiente (pueden tomar como ejemplo el proyecto de mi amigo Romaniello ;) pero a mi criterio seguimos exponiendo IQueryable hacia la vista final, algo que a mi concepto no me agrada para nada.

Es ahí cuando entra en acción el concepto de Application Services (no confundir con Domain Services), un Application Service se encarga de verselas contra el mundo “externo” ajeno al dominio (entiendase, lo que el mundo externo consumirá del dominio) mientras que el Domain Service vela por la coordinación de operaciones dentro del dominio. Simple :) [Jimmy Bogard tiene un excelente artículo al respecto, se los recomiendo]

Digamos entonces que tenemos algo simple y sencillo, nuestra interface de búsqueda del servicio de búsqueda que utiliza nuestro controller

interface SearchService {
    IEnumerable<ItemResult> SearchItems(SearchParameters parameters);
}

Como veran se expone la mínima interface necesaria para ver los elementos finales de la búsqueda (en este caso una colección simplemente necesita IEnumerable<T>, de hecho, es probable que el elemento retornado no tenga nada que ver con la entidad consultada dentro del servicio usando un repositorio (de hecho podría ser que tengamos que consultar varias entidades y hacer varios cambios antes de retornar la entidad). ¿Qué pasa entonces con conceptos como pagineo y/o límites? como vemos IEnumerable<T> no expone conceptos como Count (y menos otros como TotalCount o Limit-Offset), porqué entonces no aprovechamos que ahora hablamos de un concepto totalmente diferente y que involucra solamente presentación, que tal si retornamos IPageable<T> ?

interface IPageable<T> : IEnumerable<T> {
    int TotalCount { get; }
    int Limit { get; }
    int Offset { get; }
    int Max { get; }
}

En resumidas cuentas, hacer que el repositorio sea flexible funciona, pero no debemos permitir permear conceptos de dominio y mezclarlos con conceptos de presentación, no vaya a ser que terminemos al final con un super repositorio con 50 métodos.

Como siempre comentarios al respecto, soy todo oídos (u ojos, whatever!) ¡Hasta luego!

Stream – CopyTo

Algo común en el manejo de IO en la .Net framework es el lidear con buffers y Streams, a veces simplemente necesitamos copiar el contenido de una stream hacia otra, por ejemplo, cuando necesitamos comprimir (usando GZipStream) o encriptar (usando CryptoStream). Comúnmente hacemos algo como esto:

using (var input = new MemoryStream())
using (var output = new MemoryStream()) {
    var buffer = new byte[input.Length];
    input.Read(buffer, 0, buffer.Length);
    output.Write(buffer, 0, buffer.Length);
}

Y nos topamos con siempre el pedazo de código repetitivo, además de una variable buffer la cual usamos solamente para copiar el contenido. Pues bien, en la .Net Framework 4.0 esto se simplificó un poco con el método CopyTo de la clase abstracta Stream

using (var input = new MemoryStream())
using (var output = new MemoryStream()) {
    input.CopyTo(output);
}

Bastante más conciso a mi criterio :)

Saludos!

Regresando a lo básico – Javascript en ASP.NET

Hace unos días un amigo me preguntó algo curioso:

Necesito que todo lo que entre mi usuario en una caja de texto en ASP.NET se transforme automáticamente a mayúsculas. Se me había ocurrido usar OnTextChanged pero no se que tan efectivo podría resultarme.

Bien, considero que esta es algo así como una pregunta elemental, así que tomemonos el tiempo para analizarla y ver las opciones. Asumamos que no podemos usar ASP.NET Ajax Library, ni ASP.NET Ajax Toolkit. Tomemos en cuenta que tampoco podemos usar algo así como JQuery.

La implementación en ASP.NET que propone nuestro amigo se vería algo así:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebControls.aspx.cs"
    Inherits="WebApplication7.WebControls" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:TextBox ID="nameText" runat="server"
            OnTextChanged="nameText_TextChanged"
            AutoPostBack="true" />
        <br />
        <asp:Label Id="nameLabel" runat="server" />
        <br />
        <asp:Button ID="acceptButton" runat="server" Text="Accept" />
    </div>
    </form>
</body>
</html>

Y el “codebehind” sería algo simple como esto:

using System;
using System.Web.UI;

namespace WebApplication7 {
    public partial class WebControls : Page {
        protected void Page_Load(object sender, EventArgs e) {
        }

        protected void nameText_TextChanged(object sender, EventArgs e) {
            nameText.Text = nameText.Text.ToUpper();
        }
    }
}

Bien, ASP.NET lo que hace al activar el "AutoPostback" es que en cuanto el control pierde su "focus" se envía la página completa de regreso al server, este procesa el evento (en este caso TextChanged) y regresamos el contenido en mayúsculas. Vemos un par de problemas con este caso en particular, el primero es lo poco "práctico" que es enviar toda la página de regreso solamente para hacer una operación "sencilla" como la es transformar el texto en mayúsculas (si, probablemente hay operaciones más "complejas" en las cuales se necesite hacer tal cosa, pero en este caso no se justifica). Tal operación es fácilmente hecha con un simple script de Javascript.

Cuando comenté esto mi amigo me respondió: hey, pero no estoy usando MVC, puedo usar fácilmente Javascript con ASP.NET?, pues, ¡claro que si!, hay varias maneras. Primero, veamos como sería la función de Javascript en cuestión:

function textToUppercase(sender) {
    if (sender && sender.value) {
        sender.value = sender.value.toUpperCase();
     }
}

Una función simple, nada del otro mundo. Bien, ahora solamente modificamos el TextBox para que luzca algo así:

<asp:TextBox ID="nameText" runat="server" onblur="textToUppercase(this);" />

Listo, con esto podemos elminar el codigo que hacía la misma operación en el server, ya no más postbacks :)

Recuerden, no hay problema si agregamos atributos extras de HTMl a nuestros controles de ASP.NET.

Moraleja: Aprovechen el proceso del lado del browser cliente, no abusen del codebehind. Javascript es su amigo, aprovechenlo. No en vano Microsoft esta invirtiendo tiempo para mejorar el soporte de Javascript y la programación al browser cliente para esta y las próximas versiones de ASP.NET.