Tag Archive for programming

PHP y Microsoft como plataforma

Hace unas semanas fui invitado por parte de Microsoft a conversar un poco en el DrupalCamp 2010 que se realizó en Guatemala, quizás muchos no lo saben pero en “una vida pasada” fui developer en PHP por mucho tiempo (ufff… tiempos aquellos). Bien, fue interesante regresar a hablar sobre el soporte en que ahora ha trabajado Microsoft en su “stack” junto con PHP, transformando a Microsoft Windows no solamente en una excelente plataforma de desarrollo para PHP, sino también en una fuerte plataforma de ejecución.

Como lo había prometido (pero un poco tarde esta vez) los dejo con las diapositivas de la charla, quizás algún otro día conversamos un poco más sobre PHP (si me diera tiempo claro).

Ver diapositiva en Slideshare.net

.NET y Configuraciones – Parte 8

La última vez que conversamos acerca de configuraciones sacamos a relucir lo sencillo que es agregar soporte para funciones de validación callback, y antes de eso comentábamos lo sencillo que era agregar soporte para validación de forma declarativa usando los atributos de validación incluídos en la Configuration Framework de la .Net Framework.

Hoy seguiremos caminando en el soporte de validación customizada de secciones y elementos de validación, pero esta vez creando nuestros propios atributos de validación customizados.

Atributos de Validación

Un atributo de validación nos permite validar los elementos o secciones de nuestra configuración de .Net, simplemente tenemos que adornar ese elemento con el atributo en cuestión. La .Net framework nos incluye algunos atributos ya dentro de la caja, pero podemos agregar los nuestros propios de forma sencilla.

Realmente un atributo de validación costa de dos clases: La clase que marca el atributo (un atributo marcador) y la clase que ejecuta la acción de validar (el validador). Como podremos notar en este lado de la framework se utilizan los atributos de una manera muy particular (y que en lo personal me gusta) de mezclar el atributo como marcador pero no como ejecutor.

Usemos un simple ejemplo, imaginemos que necesitamos validar la entrada de correos electrónicos, como todos sabemos, podemos seguir un par de reglas expuestas en una serie de RFC’s acerca de direcciones de email. Bueno, comencemos por la clase que hace realmente la validación, esta debe heredar de la clase ConfigurationValidatorBase y luego el override de los métodos CanValidate (que nos dice si podemos o no validar el tipo en cuestión) y Validate (quien realmente realiza la validación).

using System;
using System.Configuration;
using System.Text.RegularExpressions;

namespace Cprieto.Samples {
    public class EmailValidator : ConfigurationValidatorBase {
        private const string Word = "[^x00-x1F^(^)^<^>^@^,^;^:^\^"^.^[^]^s]";
        private const string IpEntry = "[[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}]";
        private static readonly string Domain = string.Format("({0}+(.{0}+)*", Word);

        private static readonly Regex EmailRegex =
            new Regex(string.Format("^{0}+(.+)*@{1}|{2})$", Word, Domain, IpEntry), RegexOptions.Compiled);

        public override bool CanValidate(Type type) {
            return type == typeof (string);
        }

        public override void Validate(object value) {
            var item = (string) value;
            if (!string.IsNullOrEmpty(item) && !EmailRegex.IsMatch(item))
                throw new ArgumentException("value is not a valid email");
        }
    }
}

Bien, ahora simplemente creamos el atributo marcador, este debe heredar de ConfigurationValidatorAttribute y la parte importante de este es el override de la propiedad ValidatorInstance que retorna una nueva instancia de nuestra clase validadora.

using System.Configuration;

namespace Cprieto.Samples {
    public class EmailValidatorAttribute : ConfigurationValidatorAttribute {
        public override ConfigurationValidatorBase ValidatorInstance {
            get { return new EmailValidator(); }
        }
    }
}

Ahora simplemente lo aplicamos a nuestra sección de configuración:

using System.Configuration;

namespace Cprieto.Samples {
    public class SampleConfigurationSection : ConfigurationSection {
        [CallbackValidator(Type = typeof(PortValidator),
            CallbackMethodName = "Validate")]
        [ConfigurationProperty("port", DefaultValue = 80)]
        public int Port {
            get { return (int) this["port"]; }
        }

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

        [EmailValidator]
        [ConfigurationProperty("email")]
        public string Email {
            get { return (string) this["email"]; }
        }
    }
}

Y claro, nunca cae de más un pequeño archivo de validación que debe marcar como inválido

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="sample"
             type="Cprieto.Samples.SampleConfigurationSection, Cprieto.Samples.ValidationCallback"/>
  </configSections>
  <sample port="80" host="localhost" email="invalid@@email" />
</configuration>

Bueno, y ahora me queda pensar que escribo para el siguiente post de la serie :) Hasta la próxima!

Cambiando el usuario de un commit en Mercurial

Hoy mi gran amigo José Romaniello (@jfroma) me abarcó con una pregunta acerca de Mercurial un poco curiosa pero bastante bien fundada:

Por un error anterior, necesito cambiar el nombre de usuario que aparece registrado en algunos commits de mi repositorio de Mercurial por otro usuario, cómo puedo hacerlo? ¿tengo que reescribir la historia del repositorio?

Digamos que al principio de mis commits utilizaba el nombre de Santa Clos (digamos que así estaba la máquina con que comencé a trabajar el proyecto) y luego decidí cambiar el nombre a mi correcto nombre de Cristian Prieto, bueno, si vemos el log de commits tendremos algo como lo siguiente:

Powershell-2010-07-06_19.20.15

Bueno, si quieren pueden intentar cambiar la historia con Hg mq, pero una manera mucho más sencilla si tienen su historial local es usar a nuestro amigo “Convert”.

Algunos creen que convert (la cual es una extensión de Mercurial incluida en la instalación) simplemente sirve para convertir de un sistema de control de versiones a otro (entiéndase de Subversion a Mercurial, como nos lo muestra nuestro amigo Fabio), la verdad también nos permite convertir de un repositorio de Mercurial a otro, y en el transcurso de la conversión cambiar los valores de cada uno de los commits, entre ellos, el author del commit. En este caso en particular basta con crear un archivo “authors” que contenga la lista de valores de conversión de los autores, es un simple archivo de texto con retorno de carro. En este caso tendremos un archivo con este simple contenido:

Santa Clos <santa@northpole.net>=Cristian Prieto <me@cprieto.com>

Ahora asegurémonos que tenemos nuestra extensión convert activada, revisen que en su Mercurial.ini tengan la siguiente línea

[extensions]
hgext.convert=

Y basta solamente convertir nuestros repositorios

hg convert --authors authors.txt orig changed

Bien, ahora si revisamos el historial nos quedaría bello, como esperábamos :)

Powershell-2010-07-06_19.28.20

Para saber un poco más acerca de convert, basta con la página del wiki de Mercurial :)

Mapeo, DTO’s y ViewModels en ASP.NET MVC

Los DTO’s –Data Transfer Objects- (algunos los llaman ViewModels/EditModels según el uso para el que existan) nacen por una razón específica: El modelo de lo que ves en la vista no representa directamente tu modelo de negocio. Mi ejemplo tradicional siempre ha sido el formulario de Login/Usuario/Contraseña.

Con el pasar del tiempo mi postura hacia este tema ha sido variada y se ha hecho bastante flexible. Por ejemplo, si tu modelo y tu aplicación es lo suficientemente sencilla y sabes que luego de eso jamás se va a modificar ni cambiar entonces es suficientemente fácil quedarte con el modelo y permearlo hacia la vista y vice versa, eso es precisamente lo que hace la generación Rails/Django/Whatever y lo que solemos hacer con MonoRail y Castle ActiveRecord, ¿la razón? simple, el modelo es sencillo, el dominio es sencillo y no es un proyecto complicado.

Para bien o para mal, en el entorno en que muchos se mueven no se ven cosas tan estáticas y los modelos y reglas de negocio son mucho más complejos siendo generalmente nuestros modelos de negocio , de hecho, si trasladamos eso a una visión de diseño orientado a servicio las cosas cambian aún más (ni hablemos de una "DDD shop"), lugares donde vemos que esta regla se revienta es en sistemas empresariales al estilo CRM/ERP o las siglas que sean…

En el contexto de una aplicación MVC se sobreentiende que el viewmodel es un concern de la vista, por lo tanto esta restringido a los conceptos de presentación. Recordemos también que un controller también es un concern de la vista (si, para aquellos que siguen creyendo que el controlador es la lógica de negocio, les vuelvo a romper el corazón en este momento), un buen lugar para que vivan los viewmodels es dentro de la aplicación MVC, surge el problema entonces, ¿cómo mapeo de un modelo de negocio al modelo de la vista?, bueno, les presento un par de ideas.

Usando el mapper como un servicio

Podemos usar un mapper automático como nuestro intermediario en el controlador entre el modelo de dominio y el viewmodel y de esta manera separar e injectar el mapper en el controlador

public class OrdersController : BaseController {
    readonly IOrdersRepository _ordersRepository;
    readonly IOrdersMapper _mapper;

    public OrdersController(IOrdersRepository ordersRepository, IOrdersMapper mapper) {
        _ordersRepository = ordersRepository;
        _mapper = mapper;
    }

    public ViewResult List() {
        var orders = _ordersRepository.FindAll();
        View(_mapper.Map(orders));
    }
}

Usando un Application Service

En este caso el Application Service se encarga de tomar las decisiones y luego retornar hacia el controlador los resultados, en este caso el controlador no sabe nada de la entidad original del dominio ni sobre el repositorio original, este es sumamente flexible cuando nuestro dominio original suele cambiar drásticamente o tomar decisiones muy complejas para delegárselas al controlador. En este caso es posible que a su vez el mapper sea inyectado y sea una dependencia del servicio. De hecho, podría ser que el servicio no use un mapper para nada, si no que simplemente arme el resultado usando varias uniones de otros resultados sobre la marcha (usando LINQ por ejemplo).

public interface IOrdersService {
    IEnumerable<OrderView> GetOrders();
}

public class OrdersController : BaseController {
    readonly IOrdersService _orderService;
    public OrdersController(IOrdersService orderService) {
        _orderService =  orderService;
    }

    public ViewResult List() {
        var orders = orderService.GetOrders();
        View(orders);
    }
}

Delegando el mapeo a un ModelBinder y ActionFilter

Debo admitir que aunque este es uno de mis resultados o formas favoritas de hacerlo en una aplicación MVC, lo siento a mi criterio demasiado “opionated” (entiéndase, fumado o cargado). En este escenario no es responsabilidad directa ni de un mapper ni de un servicio el retornar los resultados esperados, si no de un Model Binder junto con un ActionFilter en ASP.NET MVC. El controlador luciría algo así:

public class OrdersController : BaseController {
    readonly IOrdersRepository _ordersRepository;

    public OrdersController(IOrdersRepository ordersRepository) {
        _ordersRepository = ordersRepository;
    }

    [Automap(typeof(Order), typeof(OrderView)]
    public ViewResult List() {
        var orders = _ordersRepository.FindAll();
        View(orders);
    }
}

Este último caso es bastante flexible pero involucra que conozcamos bien que es un Model Binder y un ActionFilter, claro, nada que un par de minutos al frente de Visual Studio no pueda solucionar :)

Debo admitir que el caso de usar un Application Service me parece más natural si nuestra aplicación es simplemente un front end a una infraestructura orientada más hacia servicios que hacia un modelo directo de consumo (entiéndase, cosas como un ERP/CRM que probablemente usemos sus interfaces por otro lado y no solamente en nuestra aplicación de “CRUD”) y es mucho más flexible para casos en que necesitamos aislar completamente la “orquestración” del resultado del “despliegue” del resultado, suena extraño al principio pero se me ocurren bastantes casos donde esto se puede presentar.

Debo hacer notar que estas observaciones son meramente orientadas al contexto de una aplicación en ASP.NET MVC y no directamente se pueden trasladar a una aplicación o a un Tier en WCF, en este caso lo único que debemos compartir entre servicios es su esquema, no sus objetos.

Como siempre, espero sus comentarios o críticas al respecto, siempre son bienvenidas, recuerden, estamos en este barco del aprendizaje todos juntos como marineros.

¡Saludos!

UPDATE: Mi amigo José Romaniello me comenta del uso de una interface estilo IMapper en vez de una especializada para mapeo (como lo es IOrdersMapper), este patrón de uso lo considero igual al uso de una especializada, por lo tanto no la incluyo.

UPDATE 2: No incluyo implementaciones definidas de como crear estos mappers, para esto se puede hacer de forma directa o usando una herramienta de mapeo de clases como Automapper, pero eso lo dejo para otro post futuro.

FluentNhibernate y Sql-query

Hoy en la oficina uno de mis compañeros de trabajo me presenta un simple problema muy particular

Necesito llamar a un procedimiento almacenado desde NHibernate, pero estoy usando FluentNhibernate para el mapeo de entidades, ¿hay algo que puedo hacer?

No es algo así como un problema “clásico” el tener que llamar procedimientos almacenados en Nhibernate, pero creo que vale la pena explicarlo.

Digamos que el procedimiento almacenado sea algo como esto

CREATE PROCEDURE [dbo].[usp_GetItemCount](@parentId INT) AS
BEGIN
    SELECT COUNT(*) AS [Total]
    FROM [items]
    WHERE [parent_id] = @parentId
END

Bueno, nada complicado, pero digamos que necesitamos llamarlo desde algún lugar de nuestra aplicación. Digamos que debido a que es algo fuera de la entidad de negocio necesitamos hacerlo usando un servicio. Bueno, escribamos el servicio

public interface ICountService {
    int GetTotal(int parentId);
}

Como recordaran, en NHibernate existe algo llamado named queries utilizadas para ejecutar consultas de SQL arbitrarias en el motor de base de datos, es una herramienta sumamente poderosa, les recomiendo dar una vuelta por la documentación. Una named query se define en un archivo de mapeo HBM al igual que los archivos de mapeo de NHibernate, por lo tanto podemos definir esta named query en el archivo Queries.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <sql-query name="SampleQuery" cacheable="true"
             read-only="true" callable="true">
    <query-param name="parentId" type="Int32"/>
    <return-scalar type="Int32" column="Total"/>
    exec usp_GetItemCount @parentId = :parentId
  </sql-query>
</hibernate-mapping>

Ok señores, pero digamos que estamos usando Fluent NHibernate para el mapeo de nuestras entidades… Rayos… Bueno, no tanto, en realidad es bastante sencillo, en Fluent Nhibernate tenemos la opción de agregar mapeos de XML al mapeo "fluent"

SessionFactory =
 Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
     .ConnectionString(
         c => c.Server("(local)").Database("Test")
             .TrustedConnection())
         .ShowSql().CurrentSessionContext("web")
         .ProxyFactoryFactory<ProxyFactoryFactory>())
     .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ItemClassMap>())
     .Mappings(m => m.HbmMappings.AddFromAssemblyOf<ItemClassMap>())
     .BuildSessionFactory();

Digamos que el archivo de mapeo de la query se encuentra en el mismo lugar que el de las classmaps de fluent nhibernate. Ahora es sencillo definir el servicio que ejecuta el procedimiento almacenado.

public class CountServiceImpl : ICountService {
    readonly ISessionFactory _factory;
    protected ISession Session {
        get { return _factory.GetCurrentSession(); }
    }

    public CountServiceImpl(ISessionFactory factory) {
        _factory = factory;
    }

    public int GetTotal(int parentId) {
        var total = Session.GetNamedQuery("SampleQuery")
            .SetInt32("parentId", parentId)
            .UniqueResult<int>();
        return total;
    }
}

Simple, sencillo, llano, conciso…

Como siempre para comentarios o lo que quieran decir/compartir/discutir se encuentra la cajita de comentarios en este post… Hasta la próxima!