Mostrando entradas con la etiqueta Desarrollo de Software. Mostrar todas las entradas
Mostrando entradas con la etiqueta Desarrollo de Software. Mostrar todas las entradas

viernes, 30 de noviembre de 2012

[Off-Topic] Javascript – Desde cero hacia las mejores prácticas (Materiales de la charla)


El pasado día 29 de noviembre tuve el placer de dar una charla en el comité sobre JavaScript con el título “Javascript – Desde cero hacia las mejores prácticas”

Aquí os dejo los materiales de la charla por si os pueden resultar de interés.

Descargar materiales

Un saludo

Andoni Arroyo

lunes, 23 de julio de 2012

Como desarrollar con Javascript y no morir (ni matar) en el intento – III


En JavaScript el concepto de Objeto representa un papel clave. Si tenemos en cuenta que no existe el concepto de clase que manejamos en otros lenguajes, es el objeto sobre el que recae la responsabilidad de definir el modelo y almacenar el valor de la instancia.

Una vez interiorizado este concepto, (superado el shock…) debemos tener en cuenta que en JavaScript disponemos de cinco tipos primitivos por valor que son: number, string, boolean, null, y undefined. Todo lo demás son objetos (más o menos especializados)

Estos tipos por valor (exceptuando null y undefined) poseen lo que se conoce como primitive wrapper objects. Los objetos wrapper pueden ser creados utilizando los constructores predefinidos Number(), String(), y Boolean()

Veamos este código al respecto:

   1:          //// number (primitivo)
   2:          var n = 100;
   3:          console.log(typeof n); // "number"
   4:          // objeto Number 
   5:          var nobj = new Number(100);
   6:          console.log(typeof nobj); // "object"

Estos objetos exponen una serie de métodos que nos ayudan a trabajar con la naturaleza de los datos a los que representan. Por ejemplo el objeto Number expone métodos como toFixed() o toExponential o el objeto String los métodos substring(), charAt() o toLowerCase().

Como hemos comentado alguna vez JavaScript es muy propenso a interpretar de la mejor manera que pueda el código e intentar hacer que funcione, con resultados algunas veces imprevistos.

¿Que os parece si os digo que estos métodos pueden ser aplicados también sobre los métodos primitivos por valor?

Pues en principio lo menos que os puede parecer es raro… Bueno, lo que esta ocurriendo detrás de la escena es que JavaScript promociona puntualmente el tipo primitivo a su correspondiente objeto, ejecuta el método y a continuación descarta el objeto creado. Lo dicho, buenas intenciones pero si no conocemos este comportamiento, puede provocar más de un dolor de cabeza…

Por ejemplo, como se nos ocurra la idea de aumentar un tipo primitivo, el interprete de JavaScript no nos arrojará ningún error, puesto que desde el punto de vista sintáctico todo está correcto, pero la propiedad incluida lo será sobre el objeto que se descartará automáticamente con lo que mal negocio hemos hecho.

Veamos un código que ilustra este ejemplo:

 
   1:          // string primitivo
   2:          var enterprise = "Plain Concepts";
   3:          // El primitivo es convertido a un objeto con el fin
   4:          // de ejecutar el método split()
   5:          console.log(enterprise.split(' ')[0]); // "Plain"
   6:          // Si intentamos aumentar un tipo primitivo no es un 
   7:          // error
   8:          enterprise.CIF = "XXXXXXXXXX";
   9:          // pero como el objeto es decartado automaticamente después de
  10:          // la promoción, la propiedad se pierde...
  11:          console.log(enterprise.CIF); // "undefined"​​





Este comportamiento, no ocurriría si instanciamos un objeto del tipo concreto (String(), Number(), Boolean()… ), por lo que si estamos pensando en aumentar el objeto creado no es buena idea usar los primitivos. 

También podríamos usar el constructor Object que incluye cierta lógica para crear el tipo derivado apropiado en base al valor recibido. (Una especie de factory)
 
Por ejemplo:
 

   1:           var n = new Object(3);
   2:           console.log(n instanceof Number); // True


 
Esta característica es un arma de doble filo puesto que nos puede llevar a errores o comportamientos inesperados cuando empleamos tipos dinámicos, por lo que en general se desaconseja su empleo siendo mas aconsejable (por sencilla y certera) emplear la notación literal.
 


 

miércoles, 18 de julio de 2012

Como desarrollar con Javascript y no morir (ni matar) en el intento – II


Cuando trabajamos con JavaScript una de las características que más quebraderos de cabeza nos pueden dar es el ámbito de las variables. Así como en otros lenguajes tenemos la capacidad de definir un ámbito dentro de varios elementos (por ejemplo en C# dentro de una clase, método, usign…) en JavaScript el único elemento que nos permite definir ámbito es el objeto function. (Y digo objeto porque en JavaScript una función es un Objeto, es decir puede tener propiedades y métodos…)

Hoy vamos a analizar un efecto conocido como Hoisting. Este efecto ocurre porque en JavaScript podemos dispersar las declaraciones de nuestras variables a lo largo de nuestra aplicación.

Veamos el siguiente código:

   1:          var name = "global name";
   2:          // global variable 
   3:          function func() 
   4:          {    
   5:              console.log ('name value: ' + name);   // undefined   
   6:              var name = "local name";    
   7:              console.log('name value after assign value: ' + name);  
                                                          //local name
   8:          };
   9:          func(); 

Como podéis ver en este código tenemos una variable “name” con el mismo nombre en el ámbito global y dentro de la función. Como hemos comentado antes, la función nos permite definir ámbito de variables, por lo que la variable “name” es diferente dentro y fuera de la misma.
Si analizamos el código anterior podemos observar que en la línea 5 se accede a la variable “name”. Sería lógico espera que dicha variable tenga el valor “global name” pero aquí entra en juego la característica de JavaScript llamada Hosting…

Con este nombre, JavaScript nos permite colocar múltiples “var” en cualquier punto de la función de tal manera que ellos funcionen como si hubiesen sido declarados al principio de la función.

Lo que tenemos que tener en cuenta es que la declaración de la variable se promociona al tope de la función (como si “var name” se colocase antes de la fila 5) pero la inicialización de la misma se ejecuta en el punto definido (la línea 6 en el código anterior). Es por eso que ocurre el efecto comentado anteriormente, es decir, en la línea 5 la variable “name” de la función (“var name”) se ha ejecutado pero no la inicialización de la misma. (Por eso el valor undefined)

Una vez entendido como funciona y con el fin de evitar errores un tanto confusos que disparen el coste de mantenimiento, un buen hábito es asumir la convención de definir todas las variables que vamos a usar al principio de la misma.

martes, 17 de julio de 2012

[Material del evento] Porque debería automatizar mis pruebas?

Os he dejado en mi skydrive el material del evento Porque debería automatizar mis pruebas? que vimos en el Centro de Innovación Social de Bilbao.

Espero que os resulte interesante, un saludo.

Como desarrollar con Javascript y no morir (ni matar) en el intento


Cada día son más las aplicaciones que cuentan con JavaScript como lenguaje de programación.
El motivo de este éxito anunciado es, entre otro, la ubicuidad de este lenguaje, y es que correr en “casi” todos los navegadores instalados a lo largo y ancho del mundo no es poca cosa.

La Web actual requiere cada vez una mayor carga de programación en cliente, hace un uso cada vez más intensivo de las capacidades del mismo (manejo del DOM, AJAX, Almacenamiento en local…) Además existen otros tipos de escenarios donde tradicionalmente JavaScript no tenía presencia (las aplicaciones nativas para Windows, aplicaciones para dispositivos móviles…) que también van convirtiéndose en terreno abonado para JavaScript.
Un claro ejemplo de este cambio ha sido confirmado con la aparición de Windows 8 y su Interfaz Metro. En él, JavaScript se presenta como un lenguaje de cliente de primera clase para desarrollar aplicaciones. Esto lo hace comparable a los hasta ahora intocables lenguajes manejados como C# o VB presentes en WPF o Silverlight.

Este cambio ha sido posible gracias en gran medida a incluir ciertas características que antes formaban  parte de .NET a nivel del Sistema Operativo y, por lo tanto, consumible desde un entorno no manejado como en el que se ejecuta JavaScript. (Internet Explorer)

Además de Metro, en las aplicaciones móviles también JavaScript es bastante común para conseguir reutilización entre plataformas, contando con ciertas artistas invitados como Phonegap…

Y es por todo esto que las comunidades de desarrolladores muy versadas en entornos muy avanzados de programación (como la gente de .NET o Java) van aterrizando en JavaScript y en la mayoría de ocasiones su primera sensación viene a resumirse en la muy común frase “vaya m***** es JavaScript”

Bueno pues la realidad es que sin estar al nivel de los lenguajes y marcos de trabajo modernos tampoco es tan malo como al principio creemos. Lo que si es necesario es realizar el esfuerzo de entender las aproximaciones con las que JavaScript afronta algunos de los problemas comunes. Esta tarea es la que vamos a realizar en esta serie de entradas ayudándonos a encajar los conceptos básicos.
Una de las primeras cosas que debemos tener en cuentas es:

“El problema con las variables globales”

Las variables globales (como su nombre indica) son compartidas a través de todo el código de tu aplicación JavaScript o página Web. Esto quiere decir que la superficie de colisión de dichas  variables es sencillamente: toda tu aplicación, con lo cual es relativamente probable definir diferentes variables globales con el mismo nombre pero diferentes propósitos.

Para entender este problema debemos ser conscientes de que JavaScript es esencialmente propenso a ayudar a que nuestra aplicación funcione a costa de no ser (a veces excesivamente) riguroso en sus validaciones (algo mejorado con el uso del strict)

Se dan dos características para la propensión a este problema:
  • En JavaScript podemos utilizar una variable que no hayamos definido
  • Cualquier variable que no hayamos declarado se convierte automáticamente en la propiedad del objeto global
Veamos un ejemplo:

(Tened en cuenta que en JavaScript el unico elemento que nos permite definir ámbito es el objeto fuction)

   1:   
   2:          function sum(x, y) {
   3:              result = x + y;
   4:              return result;
   5:          }
   6:          console.log(sum(2, 4));  // 6
   7:          console.log(result);  // 6

Como podemos observar aunque el ámbito de la variable result se desea limitar a la function sum en la que se emplea sigue viva fuera de la misma.
La regla de oro es aplicar siempre la palabra reservada var. Este mismo código declarando resutl con un var por delante nos daría un bonito:

Uncaught ReferenceError: result is not defined al ejecutar el código de la línea 7

Sencillo ¿verdad?

Veamos otro código muy similar al anterior pero incluyendo el var que aun  así no funciona como esperamos:

   1:          function foo() 
   2:          {    
   3:              var a = b = 0;
   4:          }
   5:          foo();
   6:          console.log(b);

En este caso lo que está ocurriendo es que solo se aplica el var a la variable a, que se está inicializando con el resultado de la asignación de b = 0. Pero con b nos está ocurriendo lo mismo que en el ejemplo anterior, la estamos usando antes de declararla por lo tanto es un variable global
Hay muchos aspectos sobre los que podemos ir comentando particularidades de JavaScript así que estad atentos.

viernes, 8 de julio de 2011

Silverlight y las excepciones no gestionadas

Silverlight nace para cubrir las necesidades de aplicaciones RIA, y como sabemos, las aplicaciones de Internet son exigentes en muchos aspectos. Es debido a dicha concepción, que posee ciertas características muy interesantes para escenarios para los que originalmente no fue creado.

Por ejemplo, la huella en memoria de Silverlight es sensiblemente menor que incuso para el .NET Framework Client Profile. Además el tamaño del instalador es también varias veces menos que dicho (de 28MB a 6MB ). Estos detalles que nos pueden parecer banales, no lo son tanto, si multiplicamos dichas diferencias por muchos millones de descargas o requerimientos de Hardware…

Teniendo en cuenta estas ventajas y que las partes más comunes de WPF se encuentra también presente en Silverlight, este se presenta como un candidato válido para desarrollo de aplicaciones de escritorio. (Ahora que está tan de moda HTML5/JS…)

Este modo de trabajo se conoce como “out of browser” (OOB). Tengamos en cuenta que la misma aplicación puede ejecutarse dentro y fuera del navegador, en principio, en base a que el usuario decida instalarla.

Si deseamos desarrollar aplicaciones de escritorio, podríamos distribuir nuestro .xap como parte del instalador de la aplicación completa, evitando dar la posibilidad de ejecutarla en el navegador (El host va a ser el sllauncher.exe)

Las mayores restricciones en este aspecto están relacionadas con la interacción con el Sistema Operativo y acceso a recursos de la máquina local. Si vuestro conjunto de requisitos de interacción en el puesto cliente no son muy elevadas, es posible que Silverlight pueda ser vuestra tecnología de cliente.

En esta forma de trabajo, debemos evaluar la conveniencia de algunos de los planteamientos del equipo de Microsoft y adaptarlos a nuestras necesidades. La gestión predeterminada de las excepciones no gestionadas que nos propone Visual Studio no está pensada si deseamos crear una aplicación de escritorio.

Si vemos el código que nos propone el Visual Studio al crear el proyecto de Silverlight observamos:

  1:         private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
  2:         {
  3:             // If the app is running outside of the debugger then report the exception using
  4:             // the browser's exception mechanism. On IE this will display it a yellow alert 
  5:             // icon in the status bar and Firefox will display a script error.
  6:             if (!System.Diagnostics.Debugger.IsAttached)
  7:             {
  8:
  9:                 // NOTE: This will allow the application to continue running after an exception has been thrown
 10:                 // but not handled. 
 11:                 // For production applications this error handling should be replaced with something that will 
 12:                 // report the error to the website and stop the application.
 13:                 e.Handled = true;
 14:                 Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
 15:             }
 16:         }
 17:
 18:         private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
 19:         {
 20:             try
 21:             {
 22:                 string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
 23:                 errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
 24:
 25:                 System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
 26:             }
 27:             catch (Exception)
 28:             {
 29:             }
 30:         }

Como vemos se incluye una función para interactuar con el DOM. Esto no tiene sentido si nuestra aplicación va a correr siempre en modo OOB. Además comprueba si no tenemos el depurador adjunto para realizar esta notificación…

Vamos a comenzar a modificar este comportamiento para que se adapte a nuestras necesidades.


Lo primero vamos a hacer es cambiar el código del método Application_UnhandledException y eliminar la función ReportErrorToDOM.

El resultado quedaría algo así:

  1:         private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
  2:         {
  3:             e.Handled = true;
  4:             new ExceptionDetailView {DataContext = new ExceptionDetailViewModel(e.ExceptionObject)}.Show();
  5:         }


Sencillo, verdad?


Antes de nada marcamos como tratado el parámetro recibido para notificar que ya ha sido tratada y que no escale más por la pila de excepciones. Además mostramos un mensaje de error por pantalla notificando al usuario que se ha producido un error.

Este sería un punto interesante para guardar en el log de la aplicación la información más detallada de la excepción, que seguro el departamento de soporte nos lo agradecerá.

Si deseáis incluir una buena gestión de log en Silverlight os recomiendo usar el Silverlight Integration Pack for Microsoft Enterprise Library 5.0.


Ahora la pregunta es que es ExceptionDetailView?


Pues no es más que una vista que creamos para mostrar el mensaje de error de manera agradable para el usuario. La particularidad de la misma, es que es una ChildWindow clase que se incluye en Silverlight desde la versión 3.


Esta clase nos permite colocar un control de usuario simulando una ventana modal. Es decir, deshabilita y oscurece el fondo. Este es el comportamiento que deseamos para mostrar nuestra excepción de modo que quede algo como esto:


image


En la implementación de la vista empleamos el patrón MVVM, sobre el cual existen toneladas de información. (y eso en raras ocasiones es bueno…)

Resumiendo podemos decir que disponemos de un ViewModel (ExceptionDetailViewModel.cs) y una vista que se encarga de pintar los datos que ese ViewModel expone por pantalla. (ExceptionDetailView.xaml)

La vista tiene asociada en su DataContext el ViewModel y vía Binding implementamos el conexión entre los datos y su representación gráfica.

Además de los datos es responsabilidad del ViewModel exportar la funcionalidad (vía comandos) que la vista puede invocar. En este caso, nuestro ViewModel expone un comando a la vista (ToggleShowingExceptionDetailCommand) que le permite mostrar u ocultar la información detallada de la excepción, para contentar a los más curiosos…

Pues ya solo queda probar, porque nos encanta probar, verdad??


Y en este caso debemos lanzar una excepción (al gusto, yo me he decantado por una IndexOutOfRangeException) y comprobamos que la aplicación muestra el mensaje de error de manera correcta en vez de quedarse en blanco.


Espero que os resulte interesante la idea y os incluyo el código fuente de la aplicación de ejemplo para que podáis probar su funcionamiento. Podéis consultar este y otros prototipos aquí (el nombre del archivo de esta solución es Andoni.Arroyo.UnhandledException )

lunes, 18 de enero de 2010

El misterioso caso de LINQ to SQL y 0=1…

Como ya más o menos todos conocéis LINQ to SQL implementa una política de concurrencia optimista. Esta característica parte de la premisa de no realizar ningún bloqueo sobre los registros con los que estamos trabajando. Este modo es el recomendado, y en ocasiones el único aceptable, sobre todo en entornos de alta escalabilidad como son por ejemplo las aplicaciones Web.

Cuando nos creamos el modelo de nuestra aplicación a partir de la base de datos, generamos un fichero dbml. Es importante tener en cuenta que, entre otras propiedades, podemos especificar como queremos que el contexto gestione el UpdateCheck de cada columna. (Always, WhenChanged, Never).

Esto nos permite, en base a la naturaleza de la información de un campo, afinar la política de comprobación de la concurrencia que deseamos aplicar. Por ejemplo, podemos sobrescribir siempre la descripción detallada de un producto (sin importarnos si otro usuario la ha modificado desde que leímos ) pero puede no ser aceptable para, por ejemplo, el Stock asociado al mismo. Esta característica junto con el RowVerison nos permite detectar los problemas de concurrencia y automatizar su resolución en la medida de lo posible.

Hablando con un equipo de desarrollo me contaban que tenían problemas al borrar un registro. Revisándolo con ellos, me comentaban que pasaban por parámetro clave primaria del registro que deseaban eliminar. El código que empleaban era similar a este:

using (xxxDataContext ctx = new xxxDataContext())
{
      Table1 t1 = new Table1 { Id = id };
        ctx.Table1s.Attach(t1);
        ctx.Table1s.DeleteOnSubmit(t1);
        ctx.SubmitChanges();
}

Y el error que percibían era que no se eliminaba el registro asociado en la base de datos pero no sabían exactamente porqué...

Al revisar la política de UpdateCheck de las columnas de la entidad, me di cuenta que estaban definidos en el modelo con su valor predeterminado. (Always). Por lo que la cosa estaba clara, Linq To SQL estaba creando la consulta que lanzaba al proveedor subyacente concatenándole el valor original y al no encontrar dicho registro en la base de datos no eliminaba nada…

Al comprobar mi teoría veo que la sentencia que genera Linq To SQL para el borrado incluye una clausula where del estilo ...

DELETE FROM [dbo].[Table1] WHERE 0 = 1

¿¿0=1??

Para darles respuesta les comenté el problema y la solución fue tan simple como cambiar el UpdateCheck a Never puesto que este escenario les cuadraba para dicha tabla, pero yo ya me había quedado mosca con el tema del 0=1...

Leyendo un poco descubro que es una optimización generada por el equipo de ADO.net puesto que determinan que nunca se cumple la condición. Y la condición que nunca se cumple es la siguiente:

En la base de datos existe un campo Name que esta definida como NOT NULL, por lo tanto nunca puede almacenar un valor NULL (obvio, no?). En .Net el tipo de la propiedad que mapea a dicho campo es de tipo String y por la naturaleza del mismo este puede almacenar un NULL. De hecho es los que almacena si nos fijamos en el código superior.

Como LINQ To SQL observa que en el objeto el valor es un NULL y en la definición del esquema de la base de datos este valor no puede estar presente, determina que no va a coincidir por lo que optimiza con el 0=1...

Bueno dicho (y comprendido) queda...

lunes, 30 de noviembre de 2009

Instanciando objetos en Silverlight: Code VS XAML

Si os pregunto que manera de instanciar los objetos es más rápida, por código o vía el parser de XAML ¿Cual sería vuestra respuesta?
Pues la mayoría de los desarrolladores dirían que por código, pero obviamente la cosa tiene trampa…

En la mayoría de los casos el parser de XAML es más rápido. La razón de esta característica es el resultado de una serie de optimizaciones realizadas en tiempo de ejecución por Silverlight. El parser de XAML no crea los API objects que se emplean para interactuar con los elementos, sino que solo crea una representación interna de los mismos. Cuando desde código comenzamos a interactuar con esos objetos es cuando Silverlight crea los API objects necesarios. Esta característica se hace especialmente patente en inicializaciones de gran cantidad de objetos, aunque hay entra nuestra labor de diseño para evitar crear vistas inmanejables…

Teniendo esta particularidad en mente y valorando las facilidades de integración diseñadores/desarrolladores que nos da escribir UI en XAML es recomendable dejar la creación de objetos por código para los escenarios en los que realmente es necesario.

domingo, 29 de noviembre de 2009

Metodología, motivación y otras hierbas…

No digo nada nuevo al afirmar que las empresas de desarrollo de software cuentan como materia prima para crear sus “productos finales” con la tecnología y conocimiento. Ahora bien, este conocimiento no reside en el aire, sino en las personas.

Los malos modelos directivos valoran los recursos solo en su aspecto cuantitativo sin valorar la calidad de los mismos. He oído a “grandes” gestores del sector de desarrollo de software, sacar pecho al decir que consigue dos “recursos” (por ejemplo programador) al precio de uno. Por supuesto, el cambio implicaba sustituir una persona con diez años de experiencia por dos becarios, pero desde su perspectiva el cambio de 2x1 implicaba el doble de trabajo al mismo coste…

Este mercado avanza, lentamente y en su proceso madura. Podemos decir que el ritmo al que madura el mundo del desarrollo del software es varias veces más lento que el ritmo al que avanza la tecnología, pero aun así, lo hace. Si hiciéramos un paralelismo con algún otro sector de desarrollo más maduro, supongamos la automoción, nadie se plantearía trabajar sin una metodología definida que permita a todos los miembros de los diferentes equipos conocer las reglas del juego. Aún así hay muchas empresas que no emplean ningún tipo de metodología explicita. 

Pensemos un poco sobre como impacta la forma de trabajar en la motivación de los profesionales. Los músicos de una orquesta, por muy buenos que sean, necesitan una partitura compartida para tocar juntos. Es cierto que la partitura ya esta creada por un compositor (en muchas ocasiones genios) y esta no varía. Se repite de idéntica manera miles de veces y no se adapta a las demandas del que la escucha. Nuestra partitura es más compleja. Varía con el tiempo y no es conocida de antemano (aunque las metodologías predictivas se empeñen en decir lo contrario). Al empezar nuestra obra no conocemos la cantidad de violines o tubas que necesitaremos…

Esta complejidad es una razón más para contar con una poderosa herramienta como la metodología que nos guie por el camino. Esta nos aporta:

  • Evitar desgastarnos en definir y redefinir procesos implicados en el día a día.
  • Aplicar cierta “objetividad” a la forma de trabajar y a la valoración del trabajo de los miembros del equipo.
  • Ganar en visibilidad al definir roles y responsabilidades asociadas.
  • Alinear los objetivos de los diferentes miembros del equipo.
  • Tener una base que adaptar y mejorar para los siguientes proyectos.

Cualquiera de estas características son básicas a la hora de motivar a los profesionales, sobre todo a los buenos. He tenido experiencias al respecto y es un autentico fenómeno a estudiar como cambia la aptitud de los miembros de un equipo que trabajan sin ninguna metodología explicita, al implantar una metodología (especialmente las ágiles). Muchos de ellos tienen la sensación de que su trabajo no se valora porque no es visible, lo cual acaba implantando un “comunismo” asesino de la eficiencia.

Podemos decir que los buenos profesionales necesitan visibilidad y que la metodología aporta visibilidad…así que la cosa está clara.

martes, 18 de agosto de 2009

¿Es lo mismo arquitectura por capas y N-Tier?

Me parece importante, para optimizar la comunicación entre profesionales, que todos tengamos claros los conceptos y los apliquemos para referirnos exactamente a lo mismo. Esto nos evita malas interpretaciones y errores muy críticos sobre todo en entonos de desarrollo rápido de aplicaciones (RAD). 

Existen dos conceptos arquitectónicos que a veces tendemos a confundir. Estos son la “Layered arquitecture” (arquitectura por capas) y la “N-tier arquitecture” (arquitectura de N-niveles). Me voy a referir a ellas sin traducirlas, puesto que ambos conceptos (“layer” y “tier”) pueden verse traducidas (erróneamente en el caso de “tier”) como “capa” lo cual fomenta aún más la propensión a errores.

Veamos primero que es exactamente “Layered architecture”: 

Se centra en una distribución jerárquica de las roles y responsabilidades proporcionando una separación efectiva de las preocupaciones. (cada cual que se apañe con sus problema…). El rol indica el modo y el tipo de interacción con las otras capas, y la responsabilidad indica la funcionalidad a alcanzar.

Por ejemplo, el diseño de una típica aplicación Web comprende una capa de presentación (funcionalidad relacionada con la U.I.), capa de negocio (procesamiento de reglas de negocio) y capa de datos (funcionalidad relacionada con el accesos a datos.)

El estilo de arquitectura por capas tiene algunas características que  la identifica:

  • Describe una descomposición de servicios de tal manera que las interacciones ocurren normalmente entre capas vecinas. (depende de lo laxos que queramos ser…)
  • Las capas de la aplicación pueden residir en el mismo ordenador fisco o pueden estar distribuidas en separados equipos. El concepto de distribución se aplica siempre que se produzca el mecanismo de marshaling para realizar una comunicación (siempre que no se comparta espacio de memoria…)
  • Los componente de cada capa se comunican con otros componente de otras capas a través de un conjunto de interfaces bien definidos. (sino apañados vamos…)
  • En alguna ocasión ha sido descrito como “pirámide invertida de reutilización” donde cada capa agrega sus propias responsabilidades  y abstracciones a la capas que están por debajo.

Que beneficios conseguimos aplicando esta distribución en capas?

Abstracción, encapsulamiento, capas de funcionalidad muy bien definidas, alta cohesión, reusabilidad (las capas inferiores de la pirámide no tienen dependencias de las superiores por lo que es fácil reutilizarlas) y débil acoplamiento (comunicación basada en abstracciones)

La separación, reduce el riesgo y el impacto de los cambios tecnológicos. Por ejemplo al cambiar el mecanismo de persistencia de la aplicación las capas que lo consumen no tienen porque realizar cambios. Además aumenta el rendimiento (a partir de cierta carga de trabajo) al distribuir las capas sobre múltiples capas físicas. También aumenta la escalabilidad y la tolerancia a fallos.

Este escenario es propicio para implementar una buena política de pruebas, permitiendo conmutar entre diferentes implementaciones de los interfaces (mock, servicios reales…)

Por otro lado tenemos la “N-Tier architecture”

El estilo de despliegue de esta arquitectura describe la separación de la funcionalidad en diferentes segmentos, de manera similar a la arquitectura por capas. pero cada segmento es un nivel que se encuentra físicamente en un equipo independiente.

Es un estilo que define el despliegue de las capas de la aplicación, se caracteriza por por una descomposición funcional de la aplicación, componentes de servicios y su despliegue distribuido, proveyendo mejoras de escalabilidad, disponibilidad  y utilización de recursos.

Cada capa es completamente independiente del resto, excepto de aquella/s se encuentran inmediatamente por debajo de ella. La capa n sabe como manejar las peticiones a la capa n+1, como trasladar dicha petición a la capa n-1 (si es que existe) y como tratar el resultado de la misma.

Las arquitecturas con “N-Tiers” poseen por lo menos 3 capas lógicas separadas. Cada capa tiene una funcionalidad especifica, de la cual es responsable y están localizadas en diferentes servidores físicos. Una capa (“layer”) se despliega en un nivel (“tier”) si más de un servicio o aplicación es dependiente de la funcionalidad expuestas por la capa.

Veamos los beneficios que nos aporta esta arquitectura:

  • Mantenibilidad
    Cada nivel es independiente de los demás, con lo que se consigue independencia. Se puede actualizar o modificar un nivel sin afectar a la aplicación en su conjunto. 
  • Escalabilidad
    Es razonablemente sencillo escalar puesto que los niveles están basadas en el despliegue de las capas.
  • Flexibilidad
    Cada nivel puede ser gestionado o escalado independientemente, lo cual aumenta la flexibilidad.
  • Disponibilidad
    Las aplicaciones pueden explotar la arquitectura modular empleando componentes fácilmente escalables.

Resumiendo un poco :

Podemos decir que para que una aplicación sea “N-Tier”, es condición necesaria pero no suficiente que mantenga una arquitectura por capas. Esta característica nos permite cumplir los requisitos de despliegue (3 o más capas separadas) que hacen a una aplicación “N-Tier”.

miércoles, 12 de agosto de 2009

Dulce introducción al Kanban!!

Bueno, parece que SCRUM ha puesto la pica en Flandes y se ha convertido en una metodología ampliamente conocida y respetada. Pues ya está, no? ya tenemos metodología ágil para cualquier tipo de proyecto y para siempre…

Muy confiado tienes que ser para creerte eso…

En mi trabajo hemos desarrollado un producto aplicando SCRUM con unos resultados muy satisfactorios. Dicho producto, se ha comenzado a implantar y ahora entra un equipo de soporte a mantener la primera versión del mismo y comienza una nueva rama de desarrollo de la siguiente versión.

Estaba planteándome como organizar el equipo de soporte y no acababa de encajar SCRUM sobre la naturaleza de su trabajo(la verdad que esta y cualquier otra metodología…). Es muy difícil organizarse para planificar incluso un pequeño Sprint, puesto que no se conocen las tareas de antemano. Por lo tanto, llegué a la conclusión de que necesitamos para este tipo de proyectos (que no son pocos) algo todavía más adaptable que SCRUM…

Tomando un café con el gran (aunque javero) Jorge Prieto me comentó algo sobre Kanbas y comencé a tirar del hilo para ver si me podía cuadrar eso que sonaba a pescado crudo…

Así que vamos a aprovechar este post para explicar que es eso de Kanban compararlo con SCRUM e identificar sus conflictos potenciales. Antes que meternos en harina vamos a dejar las cosas claras, haciendo un pequeño resumen de SCRUM y Kanban

SCRUM (en pocas palabras)

  • Divide su organización en pequeños equipos auto-organizados y multidisciplinares.
  • Divide el trabajo en una lista de pequeños elementos muy concretos.
  • Ordenar la lista por orden de prioridad y estimar el esfuerzo relativo de cada elemento.
  • Dividido en iteraciones cortas de longitud fija (normalmente con entrega o demostración después de cada iteración.)
  • Optimizar el plan de liberación y actualizar las prioridades en colaboración con el cliente, sobre la base de conocimientos adquiridos por la inspección de la entrega después de cada iteración.
  • Optimizar el proceso por tener una retrospectiva después de cada iteración.

Resumiendo el resumen:

Pasamos de “Muchas personas haciendo algo muy grande” a “Pocas personas haciendo cosas pequeñas que se integran con regularidad para ver el conjunto.”

Kanbas (en pocas palabras también)

  • Visualizar el flujo de trabajo
    Dividir el trabajo en trozos escribir cada uno de los elementos en una tarjeta y poner en la pared.
    Usar el nombre o columnas para ilustrar en que estado se encuentra cada elemento dentro del flujo de trabajo.
  • Límitar WIP (Work In Progress)
    Asignar límites explícitos obre cuantos elementos pueden estar en cada uno de los estados del flujo de trabajo.
  • Medir el tiempo
    Contar el tiempo promedio para completar un tema, a veces llamado "tiempo de ciclo" y, como es obvio, optimizar el proceso para que el tiempo tan pequeño y previsible como sea posible.

image

Podemos observar que Kanban es todavía menos prescriptivo que SCRUM.

Prescriptivo significa “reglas para seguir”. 100% prescriptivo implica que no tienes que usar el cerebro, ridículo verdad?…) y en este apartado vemos que SCRUM aporta mas reglas “out-of-the-box” como por ejemplo encajar en un tiempo los Sprints cosa que Kanban no hace.

Para hacernos una mejor composición podemos observar la escala de “prescriptividad” (toma ya!) de forma gráfica:

image

Como siempre podemos decir que la mejor opción es no limitarse a un herramienta en concreto. Probablemente la solución nuestros problemas se encuentre en una combinación de varias. Muchos equipo Kanban realizan una reunión diaria a primera hora (típica liturgia de SCRUM). Algunos equipos de SCRUM que he conocido, escriben su Backlog como Casos de Uso (típico de RUP) o limitan el tamaño de las colas (típico de Kanbas).

Así que como siempre “haz las cosas como mejor te funcionen”, ya os contaré el resultado de aplicar esta forma de trabajo con el equipo de soporte.

Para terminar os cito a Miyamoto Musashi que los japoneses algo saben de todo esto:

“No desarrolles ninguna dependencia de arma o escuela de lucha”

lunes, 3 de agosto de 2009

Aplicaciones multilenguaje ASP.NET MVC

El desarrollo de capa de presentación Web en .NET ha cambiado desde que Microsoft se decidió a realizar una implementación oficial del conocido patrón MVC en la plataforma ASP.NET y la (amplia) comunidad de desarrolladores de ASP.NET lo asumió con todos los cambios que implica.

Y esta implementación ha calado rápido y profundo, (ya se está desarrollando la segunda versión) ha llegado a la gente acostumbrada a Frameworks ligeros de desarrollo web que incluían sus propias implementaciones de MVC. Entre otras ventajas, ha ayudado a estandarizar la organización de los archivos del sitio y refinar las responsabilidades (Controladores -> Procesos de interfaz de usuario, workflow de la aplicación... Vistas –> mostrar la información de manera amigable y recoger los datos, validaciones de formato...).

Si deseamos acogernos a la implementación de Microsoft de dicho patrón deberemos ir encajando los problemas la funcionalidad de toda la vida sobre estas nuevas reglas de juego.

Uno de los requisitos clásicos más general es que nuestra aplicación disponga de características de globalización / localización. La idea general es la de siempre, evitar incluir ninguna referencia explicita a una determinada cultura y jugar con las características de globalización que nos ofrece el .NET Framework. Pero como ya sabemos, en Web todo se complica un poquito más. Al correr sobre un protocolo sin estado como HTTP recae sobre nuestra aplicación recordar la cultura especificada por el usuario entre las distintas peticiones.

Entonces tenemos clara la misión:

Mostrar los elementos de la UI acordes a la cultura que el usuario especifique.

Suena fácil, no? Pues lo es, si somos un poco cuidadosos…

(Por cierto, os dejo al final del post el código de la solución para que os lo podáis descargar y probar.)

1 - Estableciendo las bases, recursos a los ficheros de recursos.

Vamos a ir realizando un ejemplo paso a paso para evitar perdernos:

  1. Creamos un nuevo proyecto ASP.NET MVC Web Application.
  2. Incluimos en el proyecto la carpeta de App_GlobalResources.
  3. Incluimos un par de ficheros de recursos de acuerdo a la configuración de recursos por idioma que deseamos incluir.

    La convención de nomenclatura de los mismos dice que la primera parte del archivo es el nombre base. La segunda especifica la cultura (puede también ser solo el lenguaje que la forma). Esta última parte es opcional, entendiéndose como el juego de recursos predeterminado en caso de no exista.

    Es responsabilidad del .NET Framework enlazar automáticamente (en base a los ficheros de recursos especificados) el fichero adecuado con a la cultura especificada en actual hilo de ejecución.

    Por ejemplo, creamos el fichero predeterminado (en Inglés) y otro para español sin tener en cuenta el país. (MLTest.resx y MLTest.es.resx (para cualquier cultura con lenguaje español))
  4. Incluimos en el conjunto de ficheros de recursos todos los recursos que nuestra aplicación va a necesitar.
    En nuestro caso solo uno con nombre "GREETING".
  5. Incluimos desde una vista ( por ejemplo Views/Home/Index.aspx) la forma de consumir el recurso:

    <%
    =Resources.MLTest.GREETING%>

    Fuertemente tipado, Intellisense, detección de errores en tiempo de compilación...(da gusto verlo!!)

Bueno, pues ya tenernos una aplicación que nos muestra los recursos en base a la cultura del Framework instalado (en el servidor Web en este caso) que se encarga de especificar la cultura del hilo de ejecución.

Ya es algo, pero no es lo que queremos, verdad?

(El que dude que revise la misión que hemos puesto arriba)

2- Estableciendo la cultura del hilo en ejecución

Ya sabemos que debemos establecer la cultura del hilo de ejecución para que el Framework cargue el fichero de recursos adecuado, pero ahora la pregunta es cuando?

Recordar que cada petición empieza de nuevo y no recuerda las anteriores ( HTTP es stateless). Indagando un poco en la MSDN podemos ver que la clase Controller (de la que derivan nuestros propios controllers) de la implementación del MVC de Microsoft especifica dos métodos virtuales que nos van a resultar muy interesantes:

  • OnActionExecuting
    Se ejecuta antes de la llamada a cualquier Action Method.
  • OnActionExecuted
    Se ejecuta después de la llamada a cualquier Action Method. (obvio, no?)

Como debemos de establecer la cultura cada vez que nos realicen una llamada a cualquier action method de cualquier controlador, lo ideal es crear un controlador base del cual hereden todos los demás y sobrescribir en el método OnActionExecuting el mecanismo para restablecer la cultura. Nuestros controladores harán así transparente al resto de la aplicación las particularidades de trabajar con estado. También podríamos usar un atributo aplicado sobre la clase base y en la implementación del atributo especificar que implementa el interfaz IActionFilter si lo queremos hacer un poco mas AOP que OO.

En la implementación que os dejo utilizo un atributo con el que decoro la clase base (Al gusto!!)

En el ejemplo:

La clase base de los controladores:

[SetCulture]
public class BaseController : Controller
{
...
}

Y en la implementación de la clase del atributo programo como establecer la cultura seleccionada en el hilo activo:



public class SetCultureAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext
actionContext)
{
CultureHelper.SetCulture(GetCurrentCulture
(actionContext), actionContext.
HttpContext.Session)
}
...


Para almacenar la cultura especificada entre las llamadas podemos emplear diferentes mecanismos, en este ejemplo el flujo de trabajo será el siguiente:



  1. Revisar si tiene alguna cookie de nuestro sitio que especifique la cultura.

  2. Comprobar la variable de sessión de la cultura.

  3. En caso de no disponer de ninguna de las dos informaciones anteriores, preguntar por las culturas configurados en el navegador y presentar la interfaz de usuario en base a la primera coincidencia que se produzca.


En la implementación que os dejo del proyecto podéis consultar los métodos que he creado para realizar dichas acciones, son muy sencillos y podéis modificarlos al gusto.

Los principales métodos son:



  • GetCurrentCulture de la implementación del atributo, que consulta la información previamente almacenada en base al flujo que hemos comentado.

  • CultureHelper.SetCulture que recibe la cultura a asignar y el objeto intrínseco Session Object y carga cultura en el hilo actual de ejecución.


Aquí nos aparece otro problema.(Que raro, eh?)

Si el usuario es la primera vez que accede a la Web no tiene cookie ni session establecida.

Para intentar que la aplicación sea lo más “inteligente” posible, recogemos del navegador las culturas que tiene especificadas y las cruzamos con una sección especifica del fichero de configuración creada a tal efecto.

Por ejemplo, si el usuario tiene Chino e italiano necesito determinar si mi aplicación dispone un algún fichero de recursos que da soporte a alguno de los mismos. Para ello me creo una section en el fichero de configuración y un handler que lo soporte que especifique una lista de culturas soportadas y su orden de aplicación. (Así vemos también como poder realizar esta tarea.)

Observar que la tarea no es tan sencilla como coger el idioma y asignarlo al hilo y dejar que el Framework resuelva. (si no lo puede resolver que aplique la predeterminada) puesto que si el usuario tiene, entre todos los lenguajes del navegador, uno que tenemos implementado nos lo estaríamos saltando. (Por ejemplo Chino, Italiano, Español, Ruso)


En el fichero de configuración especificamos:

<
configSections>
...
<section name="EnabledLanguages" type="AndoniArroyo.MLTest.
Controllers.Infrastructure.Configuration.EnabledLanguagesSection,
AndoniArroyo.MLTest"
/>

</
configSections>
...

además incuimos la citada sección:


<!--Especifica el conjunto de culturas con el que trabaja la aplicación. La última es la cultura por defecto-->
<EnabledLanguages>
<Languages>
<add title="Spanish" code="es-ES" />
<add title="English" code="en-GB" />
</Languages>
</EnabledLanguages>


Para que la aplicación pueda manejar esta section debemos implementar el handler que la maneje:


namespace AndoniArroyo.MLTest.Controllers.Infrastructure.
Configuration
{
public sealed class EnabledLanguagesSection : ConfigurationSection
{
[ConfigurationProperty("Languages", IsDefaultCollection = true,
IsRequired = true)]
internal LanguageElementCollection EnabledLanguages
{
get { return (LanguageElementCollection)this["Languages"]; }
}
}
}

Estos lenguajes será los que tendrá en cuenta el método que intenta cargar el lenguaje desde la información recogida del navegador.


Pues ya casi lo tenemos.

Nos queda por ver como el usuario puede explicitamente modificar la cultura con la que desea trabajar en la aplicación. Visto todos lo anterior la cosa es fácil, no? Basta con crear un action method de modificación de la cultura y en la implementación del mismo llamar explícitamente al método de establecer cultura con el parámetro recibido. (CultureHelper.SetCulture pasándole la cultura especificada por el usuario y la referencia al objeto de sesión...)


Recapitulando, hemos visto unas cuantas cosas:



  • Hemos observado los mecanismos de globalización que nos da el .NET Framework y como extenderlos para nuestras necesidades en web.

  • Definido una política de establecer la cultura activa de la aplicación intentando que la aplicación se adapte al usuario.

  • El punto donde cubrir las características de sin estado del HTTP para establecer la cultura especificada por el usuario.

  • Hemos creado secciones personalizadas en el fichero de configuración y hemos visto como manejarlas.


Y como extra lo prometido el ejemplo con todas estas ideas en acción.


miércoles, 6 de mayo de 2009

8 maneras de cargarte la metodología de un plumazo

No es fácil implantar una manera común de desarrollar proyectos de Software. Cada maestrillo tiene su librillo y no siempre nos es fácil adaptarnos al mínimo común necesario para trabajar en equipo de manera orquestada.

Por contra, lo que sí que es realmente fácil , es dinamitar el camino andado. Hace falta muy poco para saltarse alguna que otra regla y echar abajo lo ganado con tanto esfuerzo. Existen algunos puntos claves en los que los equipos somos especialmente propensos a ceder, veamos algunos…

(*Hablando en SCRUM)

  1. No preparar suficiente Product Backlog para que el equipo adquiera prespectiva del proyecto.
    Aunque parezca mentira a los desarrolladores nos gusta saber qué leches estamos programando. De hecho las mejores propuestas de mejora de las aplicaciones surgen, al menos en las primeras fases del proyecto, del propio equipo de desarrollo. Para poder aprovechar toda esa energía/sinergia los desarrolladores deben poder hacerse una idea global del proyecto.
  2. No profundizar lo suficiente el el Sprint Planning Meeting por cansancio o falta de concrección en la exposición del Product Owner.
    La reunión previa en cada sprint permite al equipo hacerse una idea lo más concreta posible de las funcionalidades que más valor aportan al proyecto. Nos permite alinearnos con las necesidades del cliente de tal forma que todos aunemos esfuerzos en la misma dirección. También permite mitigar los riesgos e identificar sorpresar antes de asumir un compromiso. Un buen hábito que no siempre se realiza es el de poner una meta al sprint ( por ejemplo “Disponer del sistema de automatización de informes” ) que identifique la situación ideal al final del mismo y ayude al desarrollador a responder preguntas que le “tienten” por el camino. (¿Es esto importante para la meta del sprint?)
  3. Falta sistemáticamente al Daily Scrum o no respetar sin aviso las pocas liturgias que especifica SCRUM.
    Una de las características que hace a SCRUM “medio” bala de plata tan demandada por los desarrolladores, es las pocas imposiciones que propone. De éstas, una de las más importantes, es la de realizar una pequeña reunión diaria en al que cada miembro del equipo explica que ha hecho el día anterior, que impedimentos se ha encontrado y que pretende hacer en el mismo día de la reunión. Este Daily Scrum es el que da jabón al equipo y permite que todo el mundo este al día del avance, evitar duplicar batallas…
  4. Estancar conocimiento asumiendo un mismo desarrollador todas las Sprint Backlog Item de un Product Backlog Item.
    Es importante que nadie sea imprescindible. Que todos los miembros del equipo desarrollen tareas de todos los Product Backlog Items permite evitar que se creen “Reinos de Taifas” y estandariza el código. Además los equipos de desarrollo con un poco de verguenza torera se igualan por el mejor, lo que permite que se produzca aprendizaje por el camino, mejorando la calidad final del proyecto.
  5. Inventarse tareas sobre la marcha o modificar las existentes bajo demanda.
    Cuando un equipo de SCRUM asume un compromiso con el cliente a través de un sprint, dicho compromiso es inmutable por ambas partes. Es por esto que los sprints son tan cortos, para permitir reorientar el proyecto entre sprints.
  6. Intentar esconder las desviaciones o sufrir el “sindrome del investigador“.
    Si existen desviaciones, lo mejor es saberlo y ser consciente de las causas que las han provocado. En la mayoría de ocasiones dichas desviaciones se pueden justificar y son el argumento principal para mejorar los procesos del equipo. Otro de los aspectos que debe afrontar cualquier metodología es lograr una adecuada visibilidad. Esta característica es la que debe permitir permite que los StakeHolders conocozcan la situación del proyecto. Adoptar una visibilidad adecuada permite detectar las desviacioes de manera temprana así como planificar las acciones orientadas a corregirlas. Como equipo debemos ser capaces de justificarlas y transmitir los motivos a los StakeHolders adecuados, así como las acciones y planes creados. Suele ser un buen hábito, especificar a nivel de Product Backlog Item las condiciones de aceptación, en las cuales se especifican las poscondicones necesarias para que una historia pueda darse por terminada. Por supuesto, deben cumplirse todas para que se pueda dar por finalizada.
  7. No retroalimentar Sprint Backlog Items después de realizarlos.
    Es verdad que siempre vamos con prisa, que existen muchas tareas y todas las excusas que quieras poner, pero para poder decir “Hecho” (y hecho es hecho!!) cada desarrollador debe actualizar como parte de la tarea el estado de los Sprint Backlog Items asociados. Mantener al día dicha información nos permite, analizar las desviaciones y observar la tendencia del sprint y el producto. Colateralmente nos ayuda a ganar y mantener la visibilidad del proyecto manteniendo a los diferentes StakeHolder lo más al día posible.
  8. Evitar las Sprint Retrospective o demostrar falta de compromiso.
    En SCRUM la unión y el compromiso del equipo es clave puesto que todos los miembre del mismo interactuan ampliamente con los demás. El Sprint Retrosprective es la liturgia clave para recibir feedback del mismo y aumentar la unión y sentimiento de grupo. Estas reuniones pueden mejorar mucho los procesos afinando el día a día del equipo, identificando los posibles cuellos de botella y planificando como evitarlos.
    Como siempre, la clave es la constancia, no ceder al desaliento y aplicar las técnicas espartanas de confianza en tus compañeros de equipo. Solo así se puede lograr el “milagro” de echar a andar y mantener una forma de trabajo metodológica.

Como siempre, la clave es la constancia, no ceder al desaliento y aplicar las técnicas espartanas de confianza en tus compañeros de equipo. Solo así se puede lograr el “milagro” de echar a andar y mantener una forma de trabajo metodológica.

Publicado originalmente en Synergos

lunes, 27 de abril de 2009

La metodología (Ágil) va a llegaaaaar…

Como ya predijo el filósofo Arrabál, las cosas están cambiando.

Poco a poco, el sector del desarrollo del software se va haciendo un hombrecito. Desde luego este proceso no se ha postpuesto por falta de esfuerzos. La industria, cual madre concienciada, haciendo palanca a través de la Ingeniería del Software ha intentado estandarizar de muchas maneras el “artístico” proceso de crear software. Algunos de estos intentos han sido más forzados que otras (UML, CMMI, Métricas de calidad… ), pero casi todos han demostrado la misma poca efectividad.

Dichos intentos “encauzadores” de mama industria han quedado a medio camino por la misma razón: contaban con que el terreno sobre el que se apoyaban era firme, cuando realmente lo hacían sobre arenas movedizas. En relación a otras ciencias (y entornos productivo-económicos) el desarrollo de software avanza muy rápido.

Alcanzar esta velocidad de crucero implica que hay mucho que mejorar y obliga al sector a reinventarse contínuamente. La tecnología, los modelos de negocio, el alcance de la funcionalidad de las aplicaciones, la automatización de procesos, la integración y orquestación de unidades de negocio… todo está en expansión. Como todos sabemos, no se puede estandarizar lo que no deja de cambiar, por lo que los intentos realizados se han ido quedando anticuados antes de alcanzar su madurez.

Pero en ese reinventarse ha cambiado la prespectiva…

Un buen día nos damos cuenta de que estamos peleando contra la realidad. Nos liberamos y dejemos de atacar y evitar el cambio como un enemigo. Es una actitud provocada por el convencimiento que surge desde dentro de que no hay otra opción. Debemos asumir (cuanto antes mejor) el cambio como algo que está ahi, nos guste o no, no podemos evitarlo. ¡¡Todo cambia!!

En las metodologías “predictivas” se destinan gran parte de los recursos a ser capaz de predecir lo que se va a desarrollar en los próximos años. Por muy concienzudo que sea dicho estudio, el contexto varía, las necesidades del cliente cambian, surgen nuevas oportunidades y riesgos. El que mayor capacidad de cambio demuestre, contará con una ventaja competitiva significativa.
Por lo tanto, permitir que nuestro cliente marque el siguiente paso (o mejor dicho, pasito) a dar nos permite ajustar el camino a recorrer a las necesidades que sobre la marcha surgan, aportando un mayor valor al software y satisfacción al cliente, que es nuestro objetivo… ¿o no?


Publicado originalmente en Synergos

miércoles, 15 de abril de 2009

.NET Framework 4.0 y C# 4.0 (1 de 5)

Podemos incluir las nuevas caracteristicas que se incluyen en C# 4.0 en cuatro grupos principales:

  • Dynamic lookup
    Nos permite escribir métodos, operadores, acceso a propiedades y campos y cualquier invocación a objetos que se salte la comprobación estática de tipos de C# resolviendose en tiempo de ejecución. (¿esto es bueno o malo...? ya hablaremos, pero lo bueno es poder elegir, no? )

  • Parámetros con nombre y opcionales
    A partir de C# 4.0 los parámetros puedrán ser especificados como opcionales, asignandoles un valor por defecto en la declaración de miembro. Por supuesto, cuando el miembro sea invocado, los argumentos opcionales pueden ser omitidos. Los de VB.net que dejen de sacar pecho, porque además cualquier parámetro podrá ser pasado por nombre en lugar de posición. (nada de opcionales al final...)

  • Caracteristicas especificas de Interoperabilidad con COM
    La combinación de las dos mejoras comentadas anteriormente permiten hacer más cómoda la programación contra objetos COM. Además en el framework 4.0 se incluirán otras pequeñas características que mejorarán aún más esta "dura" experiencia.

  • Varianza y Contravarianza
    Quien haya profundizado en la O.O. usando genericos se dará cuanta de lo necesaria que era esta caracteristica. Ahora C# admite "co y contravariance" (por ejemplo Lista de objetos <-> Lista de string). Además los tipos de la B.C.L. son actualizados para que tengan en cuenta esta característica.

Continuaremos profundizando en posteriores posts.

martes, 7 de abril de 2009

.NET Framework 4.0 y C# 4.0 (0 de 5)

Visual Studio 2010 y el .NET Framework 4.0 estarán pronto en beta y con ellos se incluirán nuevas características. Una de ellas, es la nueva versión del lenguaje de programación C# (4.0, que se dice pronto!!). Para ponernos un poco en situación voy a escribir una serie de post en los cuales reflejar las evoluciones más significativas del mismo.

Para hacer las cosas como se deben vamos a hacer un poco de historia:

El equipo C# comienza en 1998 con el objetivo de crear un nuevo lenguaje de programación simple, moderno, orientado a objetos y type-safe (seguridad de tipos) para la plataforma .NET.

Microsoft lanza la plataforma .NET y el lenguaje de programación C# en verano de 2000 con gran éxito puesto que a día de hoy es uno de los más usados.

Uno de los principales éxitos de C# ha sido las buenas fuentes en las que se basa ( C++, Java...) así como el continuo y rápido proceso de evolución que la gente del equipo responsable de Microsoft le aplican.

Con la versión 2.0 del lenguaje se incluye el soporte para genericos, metodos anónimos, iteradores, tipos parciales y tipos nulables.

En la siguiente versión, la 3.0 el lenguaje se centra en habilitar LINQ para lo cual requiere todo lo anterior y una serie de nuevas características:
  • Variables locales de tipo implicito.
  • Métodos de extensión. (se emplea para implementar los proveedores de LINQ de manera debilmente acoplada)
  • Expresiones Lambda. (de esto ya hablaremos en otro post)
  • Inicializadores de objetos y colecciones.
  • Tipos anónimos.
  • Arrays implicitamente tipados.
  • Expresiones de consulta y árboles de expresiones.
Ahora que hemos conseguido un poco de prespectiva comenzaremos a hablar en el siguiente post de las novedades de C# 4.0.

Nota:
El nombre de C# es un guiño a modo siguiente evolución de C++. (C con 4 +)
C =>C++=>C++++

miércoles, 10 de diciembre de 2008

Como incluir un fichero en el resultado de una prueba unitaria en Visual Studio 2008

Existen ocasiones en las que nos puede interesar que una prueba unitaria incluya un determinado recurso. Esto ocurre cuando el código que deseamos testear cuenta con la existencia , por ejemplo, de un determinado fichero de texto, una hoja de cálculo o una Service-based Database (.mdf)

Como sabrán, el resultado del proceso de test genera una nueva carpeta (TestResults) donde incluye el resultado de cada generación. Si dicho resultado cuenta con una referencia relativa (la mejor manera de hacerlo) hacia un recurso pues ya la tenemos liada...

Pero como siempre (o casi) la solución es más facil de lo que parece. Existe un decorador especialmente creado para esta necesidad. Basta con colocar sobre el método que deseamos incluya el recurso el item de despliegue de la siguiente manera:

[TestMethod()]
[DeploymentItem(@".\fichero.xls")]

public int EjemploTest()
{

...

(.\ si está en la raiz claro...)

Por supuesto los más inquietos ya se estarán preguntando como evitar tener que incluir este decorador en todos los métodos (especialmente interesante si se trata de una Service-based Database (mdf)).

Pues para esto también existe una facil solución. Basta con incluir el recurso en el fichero LocalTestRun.testrunconfig dentro del elemento Deployment con la siguiente sintaxis:


\[Nombre del proyecto]\[Nombre del recurso]

y ya podemos quitar el decorador.

Como siempre, espero que les sea de utilidad.

Un saludo.

Extra ball:
Si desean incluir un fichero Service-based Database (mdf)  en una prueba unitaria y referenciarlo con un connection string del estilo: "..AttachDbFilename=|DataDirectory|.." asegurense que tienen instalado el SP1 de VisualStudio 2008.  Si este, la referencia se realiza directamente contra en .Net Framewok y no encontrará el recurso.


lunes, 29 de septiembre de 2008

Microsoft + JQuery ! (con el MVC la Santa Trinidad)

jQuery va a formar parte de la plataforma oficial de desarrollo de Microsoft.

Por cierto, jQuery es una librería de Javascript que permite simplificar la gestión de manipulación de documentos HTML a través del D.O.M. gestión y manejadores de eventos, animaciones...

Esta unión va a permitir que jQuery se distribuya con el Visual Studio. La idea es incluirla sin modificaciones (a ver si es verdad!!) de tal manera que se permita al equipo de desarrollo de jQuery continuar su propio avance de manera independiente.

Además los desarrolladores de Visual Studio podrán disponer de intellisense para jQuery (hay rumores que comentan que estará disponible como una descarga gratuita independiente en unas semanas)

Personalmente he desarrollado algunos proyectos con jQuery y la experiencia ha sido positiva por lo que me parece una conjunción positiva.

Un saludo.

martes, 24 de junio de 2008

Cuando emplear declaración implicita de tipo de variables en .net

En C# 3.0 es posible descargar en el compilador la tarea de determinar el tipo de una variable. Dicha labor de inferencia se realiza en tiempo de compilación por lo que desde el punto de vista de la aplicación generada (del IL en adelante) se mantiene la verificación estricta de tipos.

La palabra reservada para declarar de este modo las variables es "var".

Ahora la pregunta es cuando usarla y cuando no. Porque exista esta caracteristica no vamos a volver locos, por lo tanto mi recomendación es usarla solo y exclusivamente cuando sea estrictamente necesario.

Esto es, cuando vayamos a crear una variable de un tipo que no existe y no queremos reutilizar más alla del ámbito de vida de la misma.

En cualquier otro caso, como siempre, especificamos en tiempo de diseño el tipo porque mejora la legibilidad y nos cuesta lo mismo.

Además aligeramos el proceso de compilación y evitamos posibles errorres de programación que se apoyen en el funcionamiento de la inferencia del compilador.

Dicho queda, un saludo.

Palabra de consultor...

martes, 27 de mayo de 2008

Razones para evitar la programación en cliente en Aplicaciones Web

Existen algunas razones para intentar evitar la programación en el lado del cliente:
  • Aislamiento
    El código del lado del cliente no puede acceder a los recursos del servidor. Por ejemplo, una aplicación que se ejecuta en el cliente no tiene una manera sencilla de leer un fichero o interactuar con una base de datos del servidor (al menos no sin caer en problemas con la seguridad y compatibilidad de navegadores)

  • Seguridad: Los usuarios finales pueden ver el código de cliente. (Y cuando digo pueden es SIEMPRE pueden solo varia el tiempo que tienes que invertir en poder ...) Por lo tanto un usuario malintencionado al entender como funciona la aplicación puede "trampearla" más a menudo.
Un saludo