martes, 17 de marzo de 2009

Software Libre vs Software Propietario

No acostumbro a escribir sobre estos temas, mis posts generalmente son más técnicos. Sin embargo, desde hace tiempo que a veces me preguntan y muchas veces participo, voluntaria o involuntariamente, en desgastantes debates sobre el mundo Open Source y el Mundo Propietario, y la mayoría de las veces, estas discusiones, responden más a cuestiones ideológicas o fundamentalistas que objetivas.

La verdad es que me gustaría invertir más tiempo en otros temas, pero quise publicar este post para referenciar mi opinión al respecto en futuras e inevitables discusiones sobre este tema inacabable. Espero así en el futuro, cuando me encuentre en estas discusiones y me pidan opinión, pueda decir simplemente: “leé mi post”. ;-)

Encontrarán que hago muchas referencias y expongo ejemplos de o relacionado a Microsoft y sus tecnologías con las cuales trabajo día a día. Sin embargo, intento ser objetivo y espero ver comentarios objetivos de otras personas que tienen o han tenido experiencias en otras plataformas.

Introducción

Existe una gran confusión y un eterno debate entre la adopción de tecnologías basadas en Software Libre versus Software Propietario. Sin ánimos de iniciar un nuevo debate, la mayoría de las personas y organizaciones siempre están de acuerdo en que lo que se busca son soluciones de calidad al menor costo posible. Siempre se piensa en la relación Costo/Beneficio o Retorno de la Inversión.

Yo comparto esa visión, que contiene un amplio sentido común, y he decido evaluar las alternativas y plantear en forma realista diferentes soluciones en ambos enfoques, incluso creando soluciones combinadas para sacar el mejor provecho de cada una.

En este sentido, un aspecto fundamental a considerar es la realidad actual de las empresas y organizaciones, sus tecnologías disponibles, personal capacitado, cambios de plataformas, aceptación de los usuarios, etc.

Antes de estudiar y evaluar las alternativas sobre cada plataforma, veamos algunos mitos que giran entorno al Software Libre y Software Propietario.

Mito 1: Si es Software Libre, es Gratis

La palabra Libre se refiere a que se le concede a los usuarios 4 libertades básicas:

  1. Libertad de usar el programa con cualquier propósito
  2. Libertad de adaptar el programa a sus necesidades
  3. Libertad de copiar y distribuir
  4. Libertad de mejorar y hacer pública las mejoras a toda la comunidad

Cualquier programa que conceda estas libertades será considerado libre, pero esto no implica que sea gratis. Es evidente que para permitir estas libertades se debe proporcionar el código fuente del programa.

En la actualidad muchas empresas privadas desarrollan programas, herramientas y componentes y entregan el código fuente correspondiente junto a licencias que permiten su modificación y distribución, sin embargo no todas lo ofrecen en forma gratuita, pero siguen siendo libres.

Por otro lado, si un programa se distribuye gratuitamente, no significa que sea libre. Existen muchos programas de distribución gratuita que no incluyen su código fuente. Son gratis!, pero no son libres.

Mito 2: Si es Software Propietario, no es Libre

Cada vez más las empresas líderes de software reconocen los beneficios que el software libre puede aportar a la comunidad de usuarios y desarrolladores.

En consecuencia existen iniciativas de dominio público respaldadas por estas empresas que favorecen el uso de software libre y promueven comunidades de usuarios para el desarrollo e intercambio de programas y código fuente. Por el lado de tecnologías Microsoft son muy reconocidas y valiosas las comunidades de intercambio proyectos de código abierto como CodePlex (www.codeplex.com), SourceForge (www.sourceforge.net) y Code Project (www.codeproject.com).

Siguiendo con el mito 2, hace un tiempo que Sun Microsystems ha adquirido el famoso gestor de base de datos MySQL, y por ello no ha dejado de ser libre.

Por su parte, Microsoft también ha liberado el código fuente de su plataforma de desarrollo más preciada: .NET Framework. Y las bases de esta plataforma y el lenguaje C# se encuentran definidos como estándares internacionales por la ECMA; lo que ha permitido el desarrollo de nuevas iniciativas Open Source como el Proyecto Mono (http://www.mono-project.com) y el Proyecto dotGNU (http://www.dotgnu.org)

Mito 3: Si es Software Propietario, hay que pagar licencias

Hoy en día muchas empresas ofrecen innumerables productos, plataformas y servicios en forma totalmente gratuita. Empresas como Sun, Adobe, HP, Oracle y Microsoft ofrecen desde programas de usuario final hasta completas suites de desarrollo y potentes motores de bases de datos en forma totalmente gratuitas.

Por ejemplo:

Las prestaciones de estas herramientas son totalmente funcionales y permiten el desarrollo de soluciones completas y de calidad profesional, no hay que pagar licencias para usarlas.

Mito 4: Si la licencia de uso es gratis, el costo del sistema es cero

Quizás este sea el mito qué más puede confundir y perjudicar. El costo real de un sistema no está en las licencias de uso, sino en el mantenimiento y soporte necesario durante todo el ciclo de vida.

Cada empresa u organización debe evaluar si dispone y/o puede costear el personal técnico capacitado para dar soporte y mantenimiento a los sistemas antes de implementarlos. También debe evaluar el respaldo tecnológico asociado a la plataforma elegida, la comunidad de usuarios técnicos y no técnicos, etc.

Hace tiempo que las empresas y el mundo han comprendido que nada es realmente gratis, todo tiene un costo asociado. Y en las soluciones informáticas, generalmente el principal costo reside en el soporte y mantenimiento que asegure el funcionamiento de los sistemas en las condiciones apropiadas.

Finalmente, no se encuentra mucho valor al enfocarse solo en el costo de la solución, sino en los beneficios que éste puede brindar. Volvemos al principio: la relación costo/beneficio.

Usar lo mejor de cada mundo

La buena noticia de todo esto es que existe competitividad y un gran abanico de posibilidades para elegir. Además no todo es blanco o negro, existe la interoperabilidad entre plataformas.

Por ejemplo, existen soluciones en ASP.NET usando como bases de datos MySql o PostgreSql. Lo mismo ocurre con Java y las plataformas de Sun; y desde PHP podemos conectarnos a Microsoft SQL Server u Oracle. Y ni hablar si usando un enfoque SOA.

En un proyecto actual en el que estoy trabajando, incluye una solución de escritorio, destinado al sector educativo. Hemos visto que todas las escuelas de la región que intentamos dar cobertura tienen PCs con Windows XP y Office. Analizando este escenario:

  • ¿Porqué querríamos cambiar a Linux? ¿Por las licencias?
    Microsoft le ha otorgado licencias a costo casi cero a todas las escuelas.
  • Y si así no lo fuera, ¿cuál sería el costo de contratar personal capacitado para instalar Linux en todas las escuelas?
  • ¿Cuánto costará y cuánto tiempo llevará capacitar al personal administrativo?
  • ¿Qué costos tendría el cambio radical de sus programas y su forma de trabajo al personal?

Con esto no quiero decir que Linux sea una mala opción. Sino que siempre hay que evaluar el escenario. Quizás aquí podría ajustarse una solución desktop para Windows basada en Java o .NET usando como motor de datos MySql o SQL Server Express.

En definitiva, creo que la clave está en evaluar y saber elegir las soluciones más convenientes y apropiadas para cada escenario. Podemos usar lo mejor de cada mundo y debemos tener siempre presente la relación costo/beneficio y podría destacar entre los beneficios, la proyección y visión hacia futuro.

Bueno, espero haber aportado algo de claridad sobre este tema tan discutido.
Saludos, Gus

domingo, 8 de marzo de 2009

ADO.NET Entity Framework: The version of SQL Server in use does not support datatype 'datetime2'

Trabajando con ADO.NET EF, en mi entorno de desarrollo tengo SQL Server 2008 y en producción está SQL Server 2005. Al publicar mi aplicación, en algunas páginas obtengo el siguiente error:

The version of SQL Server in use does not support datatype 'datetime2'

SQL Server 2008 dispone de un nuevo tipo de datos Datetime2 que agrega soporte mejorado de fechas y horas.

Por ejemplo, Datetime2 soporta fechas y horas desde 0001-01-01 00:00:00 hasta 9999-12-31 23:59:59.9999999 (nanosegundos de precisión), mientras que el conocido Datetime solo acepta rangos desde 1753-01-01 00:00:00 hasta 9999-12-31 23-59:59.999 (solo milisegundos de precisión). Pueden leer más sobre esto en el siguiente enlace (en inglés): DATETIME2 vs DATETIME in SQL Server 2008

Para resolver el problema de incompatibilidad usando ADO.NET Entity Framework hay que abrir el archivo .edmx con el editor de XML y cambiar el valor del atributo ProviderManifestToken a 2005.

<edmx:Runtime>
<edmx:StorageModels>
   <Schema Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005">

Luego guardamos los cambios en el modelo y recompilamos la aplicación. Esto resolverá el error de versiones.

Algo importante a saber es que si posteriormente actualizamos el modelo en nuestro entorno de desarrollo el atributo ProviderManifestToken volverá a establecerse al valor 2008 y deberemos cambiarlo manualmente antes de publicar nuestra aplicación.

Quizás con una tarea postbuild podríamos hacer este cambio automáticamente. Si alguien se anima a crear una tarea como esta será bienvenida.

Espero que sirva.
Saludos, Gus

viernes, 6 de marzo de 2009

Paginación y Ordenamiento del lado servidor con GridView y ADO.NET Entity Framework

Esta vez quiero mostrarles como actualmente estoy implementando paginación y ordenamiento del lado servidor, usando GridView, ObjectDataSource y ADO.NET EF. Aunque de una forma muy similar también es aplicable a LINQ2SQL.

 

Creando los métodos en la capa de negocio o servicios

El primer paso consiste en crear en nuestra capa de negocios o servicios un par de métodos que luego serán invocados por el control ObjectDataSource.

Básicamente necesito 2 métodos para lograr mi objetivo:

  1. Un método que me devuelva la cantidad total de registros
  2. Y otro método que me devuelva los registros paginados

Para el ejemplo voy a crear en una clase CatalogService, un método FindProducts() y otro método FindProductsCount().

public IList<Product> FindProducts(int? code, string description, int? categoryID, string sortExpression, int startRows, int maxRows)
       {
           using (var db = new StoreEntities())
           {
               var query = from p in db.Products select p;

               query = FindProductsFilter(query, code, description, categoryID);
               query = FindProductsSort(query, sortExpression);

               return query.Skip(startRows).Take(maxRows).ToList();
           }
       }

Aquí vemos que FindProducts() llamá a 2 métodos FindProductsFilter() y FindProductsSort() que se encargan de aplicar los filtros necesarios y ordenar los registros, y luego usa los métodos Skip y Take para paginar los resultados.

private static IQueryable<Product> FindProductsFilter(IQueryable<Product> query, int? code, string description, int? categoryID)
{
    if (code.HasValue)
        query = query.Where(p => p.Code== code);

    if (!string.IsNullOrEmpty(description))
        query = query.Where(p => p.Description== description);

    if (categoryID.HasValue)
        query = query.Where(p => p.Category.ID== categoryID);

    return query;
}

private IQueryable<Product> FindProductsSort(IQueryable<Product> query, string sortExpression)
{
    if (string.IsNullOrEmpty(sortExpression))
        return query.OrderBy(p => p.Description);

    return query.OrderBy(sortExpression);
}

Es importante saber que el método OrderBy() no acepta un parámetro string para realizar el ordenamiento. Sin embargo, aquí estoy usando unas extensiones de LINQ conocidas como Dynamic Query para lograr este objetivo.

Pueden leer un artículo de Scot Guthrie traducido al español sobre Dynamic Query y descargar el código fuente.

Sin Dynamic Query, tendría que parsear el parámetro sortExpression y escribir un switch o multiples ifs para aplicar el OrderBy correspondiente según el campo. En pocas palabras, tendría que escribir muuucho más código, entonces prefiero Dynamic Query.

Y ahora el método FindProductsCount() que no hace otra cosa más que contabilizar el total de productos. Este método lo utiliza el ObjectDataSource y la grilla para poder calcular el total de páginas necesarias, sin tener que traer todos los registros para luego paginarlos.

public int FindProductsCount(int? code, string description, int? categoryID)
{
    using (var db = new StoreEntities())
    {
        var query = from p in db.Products select p;

        query = FindProductsFilter(query, code, description, categoryID);

        return query.Count();
    }
}

 

Consumiendo los métodos desde la UI

Ahora creo una página aspx con unos campos para filtrar, un botón y una grilla asociada a un ObjectDataSource para los resultados. El formulario se vería mas o menos así:

image

No deseo explicar cómo enlazar la grilla con un ObjectDataSource, solo bastaría con decir que debemos asociar al método FindProducts() creado anteriormente y asociar los parámetros del método con los controles de la página. Y luego hay que habilitar Paging y Sorting en la grilla.

Las propiedades establecidas para el ObjectDataSource aparecen en negrita:

image 

Las propiedades sortExpression, startRows y maxRows serán pobladas y pasadas al método FindProducts y/o FindProductsCount automáticamente.

La última pieza es escribir código para el botón Buscar:

protected void FindButton_Click(object sender, EventArgs e)
{
    if (!Page.IsValid) return;

    try
    {

    ProductsGridView.DataSourceID = ProductsDataSource.ID;
    ProductsGridView.DataBind();
}
catch (Exception ex)
{
    ShowError(ex.Message);
}

}

Debe observarse que solo en runtime estoy enlazando la grilla con el control ObjectDataSource. Es decir, después de configurar la grilla y el ObjectDataSource, en tiempo de diseño, quito la referencia al ObjectDataSource en la propiedad DataSourceID de la grilla. De esta forma, cuando la página se carga no se hace una búsqueda automática, sino solo cuando se completan los filtros de búsqueda y se presiona el botón Buscar.

Pero esto es una particularidad que quise implementar y no tiene ningún efecto sobre la paginación y ordenamiento, motivo de este post.

Bueno creo que ya está todo, ahora hay que probar.

image

A mí me funcionó de maravillas ;-).

Mirando con el SQL Profiler veo que solo se consultan 10 registros por página. Las consultas al SQL Server devuelven solo los registros que el usuario quiere ver. Esto permite que nuestras aplicaciones sean mucho más escalables, pues solo traemos los registros necesarios y se minimiza la carga de trabajo en la BD.

Bueno espero que sirva.
Comentarios son bienvenidos!

Saludos, Gus

RUN09

Este es el nombre que finalmente fue bautizado al antes llamado Buenos Aires Briefing. Hoy Miguel Saez nos avisa que ya está disponible el site del evento en http://www.puertadeenlace.net/run09. Desde este sitio podrán registrarse, ver los oradores y revisar la Agenda del evento, y quizás descubrir algunas perlitas del site.

image

Es de destacar que el site tiene una UI inspirada en Windows 1.0, pero está desarrollado con las últimas tecnologías de MS. Incluso mike nos comenta en su blog que está disponible un servicio de WCF (http://www.puertadeenlace.net/run09/Models/Service.svc/) que se puede usar para construir otro cliente para el evento en Silverlight, WPF o Gadget de Vista y quizás ganar un poco de publicidad durante el evento.

Bueno, a tomarse un respiro y aprovechar este evento. Seguramente nos encontramos allí.
Saludos, Gus