GroupBy con LINQ to Objects

El agrupamiento de un conjunto de datos mediante LINQ, ya sea mediante la extensión de IEnumerable o IQueryable, tiene una serie de características las cuales me gustaría comentar aquí.

Para explicar un poco las posibilidades del agrupamiento mediante la extensión GroupBy voy a exponer un ejemplo con LINQ to Objects y para ello, primero, definiremos una clase sencilla que represente la entidad Cliente.

public class Cliente
{
public int IdProvincia { get; set; }
public int Tipo { get; set; }
public string Nombre { get; set; }
public decimal VolumenNegocio { get; set; }

public override string ToString()
{
return string.Format("tt-> Cliente: {0} - Provincia:{1} - Tipo: {2} - Vol.:{3}en",
Nombre, IdProvincia, Tipo,VolumenNegocio);
}
}

Como se puede observar no es más que una clase con 4 propiedades implícitas y el método ToString() sobrescrito para poder mostrar por la consola la información de un objeto iterado del tipo Cliente.

Vamos a generar una lista de clientes mediante una lista genérica de la siguiente forma:

//inicializamos lista de clientes
var list = new List<Cliente>
{
new Cliente {IdProvincia = 1, Nombre = "Cliente1", Tipo = 10, VolumenNegocio = 100.00m},
new Cliente {IdProvincia = 2, Nombre = "Cliente2", Tipo = 20, VolumenNegocio = 20.00m},
new Cliente {IdProvincia = 3, Nombre = "Cliente3", Tipo = 20, VolumenNegocio = 230.00m},
new Cliente {IdProvincia = 3, Nombre = "Cliente4", Tipo = 20, VolumenNegocio = 500.00m},
new Cliente {IdProvincia = 1, Nombre = "Cliente5", Tipo = 30, VolumenNegocio = 10.00m},
new Cliente {IdProvincia = 2, Nombre = "Cliente6", Tipo = 10, VolumenNegocio = 750.00m},
new Cliente {IdProvincia = 1, Nombre = "Cliente7", Tipo = 20, VolumenNegocio = 340.00m},
new Cliente {IdProvincia = 1, Nombre = "Cliente8", Tipo = 20, VolumenNegocio = 170.00m}
};

La intención es agrupar esta lista de clientes por la provincia, a la cual pertenecen, a través de la propiedad IdProvincia del tipo int. Para ello, en primer lugar, echaremos un vistazo a la extensión GroupBy que incorpora la clase System.Linq.Enumerable. Dicha extensión presenta las siguientes sobrecargas:

public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TKey, IEnumerable<TSource>, TResult> resultSelector);

public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector);

public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> comparer);

public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
IEqualityComparer<TKey> comparer);

public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, IEnumerable<TElement>, TResult> resultSelector);

public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey> comparer);

public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
IEqualityComparer<TKey> comparer);

En todas ellas existen un denominador común, el parámetro keySelector del tipo Func<TSource, TElement> que determina el valor de tipo TKey por el cual se agrupara la lista. Por otro lado GroupBy puede retornar un objeto del tipo IEnumerable<TSource> si se especifica el parámetro resultSelector (tipo Func<TSource, TKey>) o bien un objeto del tipo IEnumerable<IGroupingKey<TKey, TElement>> para todos los demás. Vamos  centrarnos en éste último por ahora.

Manejando resultados IEnumerable<IGroupingKey<TKey, TElement>>

Si el agrupamiento se realiza sobre una lista de elementos iterativos o “IEnumerables” es obvio que el resultado, otra lista de subelementos agrupados por una clave del tipo TKey, sea otra lista de elementos iterativos de ahí que el tipo resultante sea IEnumerable<T>. La singularidad esta en el tipo genérico en la iteración del valor retornado el cual es del tipo IGroupingKey<TKey,TElement> y vamos a ver el porqué. Lo que LINQ hará ante un GroupBy es realizar un recorrido completo por la lista y seleccionará todos los elementos del tipo TElement de una misma clave (TKey). Por consiguiente el resultado será una lista del agrupamiento de elementos definidos por la interfaz IGroupingKey<TKey,TElement>, en la que almacenará la clave y el conjunto de elemento agrupados por el valor de dicha clave, respetivamente en cada tipo genérico. Veamos un ejemplo.

En nuestra lista de clientes vamos a agrupar los elementos por el identificador de provincia definido por Cliente.IdProvincia.  Para ello definiremos una variable del tipo IEnumerable<IGroupingKey<int,Cliente> pues el tipo de datos de agrupamiento es del tipo int (propiedad IdProvincia) y el elemento a agrupar es del tipo Cliente, por tanto:

IEnumerable<IGrouping<int, Cliente>> groupByProv = 
from cliente in list group cliente by cliente.IdProvincia;

O lo que es lo mismo:

var groupByProv = list.GroupBy(cliente => cliente.IdProvincia);

Ahora la variable groupByProv posee una lista de todas las clave/agrupaciones realizadas. De hecho podemos comprobarlo de la siguiente forma:

foreach (var cProv in groupByProv)//cProv es del tipo IEnumerable<IGrouping<int, Cliente>>
{
Console.WriteLine(
string.Format("Provincia {0}, {1} clientes", cProv.Key, cProv.Count()));
}

Cuyo resultado por pantalla seria:

image

La variable implícita cProv posee tanto la clave utilizada (IdProvinicia) como la iteración de los clientes agrupados por dicha propiedad, de forma que podría ser recorrida de igual forma.

foreach (var cProv in groupByProv)//cProv es del tipo IEnumerable<IGrouping<int, Cliente>>
{
Console.WriteLine(
string.Format("Provincia {0}, {1} clientes", cProv.Key, cProv.Count()));

foreach(var cliente in cProv)
Console.WriteLine(cliente.ToString());
}

Y el resultado:

image

Sin embargo podríamos rizar aún más el rizo y agrupar, de nuevo, cada una de las agrupaciones por el tipo de cliente. De esta forma tendríamos una primera agrupación según la IdProvincia del cliente y por cada uno, una agrupación por tipo de cliente de la siguiente forma:

   1: foreach (var cProv in groupByProv)//cProv es del tipo IEnumerable<IGrouping<int, Cliente>>
   2: {
   3:     Console.WriteLine(string.Format("Provincia {0} ", cProv.Key));
   4:  
   5:     IEnumerable<IGrouping<int, Cliente>> groupByTipo = cProv.GroupBy(cliente => cliente.Tipo);
   6:  
   7:     foreach (var cTipo in groupByTipo)
   8:     {
   9:         Console.WriteLine(string.Format("tTipo {0} n", cTipo.Key));
  10:  
  11:         foreach (var cliente in cTipo)
  12:             Console.WriteLine(cliente.ToString());
  13:     }
  14: }

Lo que hemos hecho en el ejemplo anterior es aprovechar la iteración del primer agrupamiento para volver a generar un extensión GroupBy pero en esta ocasión con la propiedad Cliente.Tipo (int) como TKey. El resultado:

image

Manejando resultados IEnumerable<TSource>

Como comenté anteriormente, GroupBy puede devolver una iteración de tipo IEnumerable<TSource> indicando en la sobrecarga el parámetro resultSelector. Para ver este ejemplo, en base a la lista de cliente generada anteriormente, vamos a mostrar, por ejemplo, para cada una de las provincias (agrupamiento) el número total de clientes, el valor máximo, mínimo y medio de la propiedad Cliente.VolumenNegocio (decimal) de modo que nos ofrecerá información, por cada provincia, de los valores máximo, mínimo y medio del volumen de negocio de los clientes.

Para ello utilizaremos la sobrecarga:

   1: System.Linq.Enumerable.GroupBy<TSource, TKey, TResult>(
   2:    this System.Collections.Generic.IEnumerable<TSource>, 
   3:    System.Func<TSource,TKey>, 
   4:    System.Func<TKey,System.Collections.Generic.IEnumerable<TSource>,TResult>)
La implementación será:
   1: var groupByInfo = list.GroupBy(
   2:     cliente => cliente.IdProvincia, //seguimos con el agrupamiento por provinicia
   3:     (provincia, clientes) => new //retornamos un tipo anónimo
   4:         {
   5:             //con info sobre el agrupamiento
   6:             Key = provincia,
   7:             Count = clientes.Count(),
   8:             Min = clientes.Min(c => c.VolumenNegocio),
   9:             Max = clientes.Max(c => c.VolumenNegocio),
  10:             Avg = clientes.Average(c => c.VolumenNegocio)
  11:         });

El primer lugar, el tipo de la iteración de retorno es del tipo anónimo y es por ello que nos basamos en una variable implícitamente tipada (var). El primer parámetro (línea 2) es del tipo keySelector que vimos anteriormente y como dije es común en todas las sobrecargas pues es el valor clave de agrupamiento. Seguidamente el segundo parámetro (líneas 3-11), del tipo Func<int,IEnumerable<Cliente>,anonymous type> es donde se proyectará el resultado del agrupamiento.

Iteramos y mostramos los resultados.

   1: foreach (var res in groupByInfo)
   2:     Console.WriteLine(
   3:         string.Format("Provinicia:{0}ntCount:{1}ntMin Volumen:{2}ntMax Volumen:{3}ntAvg:{4}"
   4:                       , res.Key, res.Count, res.Min, res.Max, res.Avg));

En total 3 iteraciones con sus respectivas “estadísticas”:

image

El código completo:

namespace LINQGroupingBy
{
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
static void Main(string[] args)
{
//Ejemplo para LINQ to Objects

//inicializamos lista de clientes
var list = new List<Cliente>
{
new Cliente {IdProvincia = 1, Nombre = "Cliente1", Tipo = 10, VolumenNegocio = 100.00m},
new Cliente {IdProvincia = 2, Nombre = "Cliente2", Tipo = 20, VolumenNegocio = 20.00m},
new Cliente {IdProvincia = 3, Nombre = "Cliente3", Tipo = 20, VolumenNegocio = 230.00m},
new Cliente {IdProvincia = 3, Nombre = "Cliente4", Tipo = 20, VolumenNegocio = 500.00m},
new Cliente {IdProvincia = 1, Nombre = "Cliente5", Tipo = 30, VolumenNegocio = 10.00m},
new Cliente {IdProvincia = 2, Nombre = "Cliente6", Tipo = 10, VolumenNegocio = 750.00m},
new Cliente {IdProvincia = 1, Nombre = "Cliente7", Tipo = 20, VolumenNegocio = 340.00m},
new Cliente {IdProvincia = 1, Nombre = "Cliente8", Tipo = 20, VolumenNegocio = 170.00m}
};


//obtenemos todos los clientes agrupados por provincias
var groupByProv = list.GroupBy(cliente => cliente.IdProvincia);

//tambien se puede expresar como:
//
//IEnumerable<IGrouping<int, Cliente>> groupByProv =
// from cliente in list group cliente by cliente.IdProvincia;

foreach (var cProv in groupByProv)//cProv es del tipo IEnumerable<IGrouping<int, Cliente>>
{
Console.WriteLine(
string.Format("Provincia {0}, {1} clientes", cProv.Key, cProv.Count()));

foreach(var cliente in cProv)
Console.WriteLine(cliente.ToString());
}

Console.ReadKey();

foreach (var cProv in groupByProv)//cProv es del tipo IEnumerable<IGrouping<int, Cliente>>
{
Console.WriteLine(string.Format("Provincia {0} ", cProv.Key));

IEnumerable<IGrouping<int, Cliente>> groupByTipo = cProv.GroupBy(cliente => cliente.Tipo);

foreach (var cTipo in groupByTipo)
{
Console.WriteLine(string.Format("tTipo {0} n", cTipo.Key));

foreach (var cliente in cTipo)
Console.WriteLine(cliente.ToString());
}
}

Console.ReadKey();
Console.Clear();

//volvemos a agrupar
var groupByInfo = list.GroupBy(
cliente => cliente.IdProvincia, //seguimos con el agrupamiento por provinicia
(provincia, clientes) => new //retornamos un tipo anónimo
{
//con info sobre el agrupamiento
Key = provincia,
Count = clientes.Count(),
Min = clientes.Min(c => c.VolumenNegocio),
Max = clientes.Max(c => c.VolumenNegocio),
Avg = clientes.Average(c => c.VolumenNegocio)
});

//mostramos los resultados
foreach (var res in groupByInfo)
Console.WriteLine(
string.Format("Provinicia:{0}ntCount:{1}ntMin Volumen:{2}ntMax Volumen:{3}ntAvg:{4}"
, res.Key, res.Count, res.Min, res.Max, res.Avg));

Console.ReadKey();

}

public class Cliente
{
public int IdProvincia { get; set; }
public int Tipo { get; set; }
public string Nombre { get; set; }
public decimal VolumenNegocio { get; set; }

public override string ToString()
{
return string.Format("tt-> Cliente: {0} - Provincia:{1} - Tipo: {2} - Vol.:{3}en",
Nombre, IdProvincia, Tipo, VolumenNegocio);
}
}
}
}

Nokia lleva a los tribunales al iPhone por violación de hasta 10 patentes

Y es que el 22 de octubre no sólo fue noticia el lanzamiento mundial de Windows 7. Nokia, por su parte, denunció ante los tribunales de EEUU a Apple por violar hasta 10 patentes que incorpora su teléfono móvil iPhone.

Por todos es sabido del liderazgo de Nokia en el mercado mundial de telefonia móvil, dónde practicamente 4 de cada 10 dispositivos vendidos en el mundo salen de la factoria finlandesa. Lo que probablemente no esté en la luz publica es que Nokia, quien ha llegado a invertir hasta 40 Billones de € en I+D, posee muchas de las patentes en telefonia móvil quién comparte con hasta 40 empresas del todo el mundo bajo contratos de colaboración.

Con todas excepto con Apple (supuestamente). Por lo visto los de Cupertino (California) han incorporado características al su dispositivo móvil al modo de Duty Free.  Encriptación, comunicaciones inhalambricas, seguridad o reconocimiento de voz son algunas de las patentes que (supuestamente) Apple ha violado.

Tambien cabe decir que Nokia ha presentado su primer semestre del año con datos negativos despues de más de una decada. Esta bajada se debe al mercado que ha conseguido tanto por el iPhone como su Marketplace y algunos expertos/analistas en mercados tecnologicos apunta a ésta como la causa principal de esta demanda.

De todas formas, el caso no se ejecutará hasta el 2011. A ver que pasará….

 

Microsoft Sync Framework 2.0 (Novedades de la nueva versión y adopción por SharePoint 2010 y Windows 7)

Se acaba de liberar la versión 2.0 de Microsoft Sync Framework. Esta esperadísima nueva versión de Sync Framework además de aportar nuevas características y mejorar (según dicen, habrá que probarlo) en cuanto a rendimiento, también es noticia por la adopción por parte de Windows 7 y Microsoft Office/SharePoint 2010.

Respecto a Windows 7, MS Sync Framework 2.0 será la plataforma de sincronización utilizada por Device Stage, nueva característica del sistema operativo que pretende ser el punto de conexión con los dispositivos móbiles. De modo que la sincronización de tareas, contactos y demás items se sincronizaran con cualquier orígenes de datos.

Por lo que respecta a SharePoint 2010, Sync Framework 2.0 jugará un papel importante en cuanto a la sincronización de Office Workspace (Groove) y SharePoint. Además, el propio servidor de SharePoint 2010 expondrá parte de las API de Sync Framework 2.0 para poder crear proveedores personalizados para integrar datos al propio SharePoint.

Sync Framework ofrece mejoras sustanciales respecto a la versión anterior:

Core Components

Sync Services for ADO.NET

  • Ahora ya sí (al fin) Sync Services for ADO.NET ofrece un proveedor de datos para SQL Server Express, además de los ya existentes SQL Server y SQL Server Compact. Para todos ellos con sus correspondientes adaptadores con lo que prácticamente no requeriremos escribir ningún comando de consulta o modificación.
  • Nueva API la sincronización de datos en batch, resolviendo los difíciles escenarios (en ocasiones irresolubles) que comportaba la utilización de batching en la versión 1.0. Además se ha optimizado de forma que podemos configurar el espacio máximo que un conjunto de cambios puede ocupar en memoria lo cual optimizará, y mucho, el rendimiento sobretodo en las inicializaciones de una sincronización. Esta característica será muy bien recibida por la comunidad .NET Compact Framework cuando aparezca la siguiente versión para dispositivo móviles.
  • Habilita las tareas de mantenimiento para por ejemplo limpiar los metadatos.
  • Dos opciones de inicialización de datos: inicialización  por sincronización normal (de una base de datos ya inicializada) o bien inicialización instantánea de una base de datos SQL Server Compact 3.5.

[OT] Tatuajes geeks

Impresionante documento trágico gráfico el que os traigo. En este mismo portal de geeks.ms se mostró no hace mucho una imagen de un tatuaje realmente curioso.

image

Pues por lo visto hay alguien que no se ha conformado únicamente con dos tag:

image

Incluso alguna ha hecho su propia interpretación:

image

Pero no solo de HTML vive el geek. Ahí va un poquito de C:

image image  
     

Y un “Hola Mundo!”

image

También hay lugar para los binarios:

image image  
     

 

Y un poco de código encriptado:

image 

Lo que tampoco podía faltar son los Fan Boys, empezando por los Linuxeros:

image image  
     

Pasando por los Appleros.

image image image
     

Googleros…

image image  
     

Yahooeros

image

Y por supuesto de los Microsofteros

image image  
     

Otros mas de principios, orgullosos de lo que son:

image

Los visionarios:

image

Los inconformista:

image

Bloggeros:

image image image
     

También tienen cabida “los del hierro” (hardware)

image

Y el mas de lo mas. Los auténticos geeks. Los que viven este mundillo como ninguno y sin duda uno de mis favoritos… los que se tatúan la Pantalla Azul de la Muerte en el brazo!!!! Que Grande!!!

image

En fín, ahí queda el tema.

Salud!

Del Modelo de Error Humano en las organizaciones TIC a los papanatas con corbata

 La industria aeronáutica invierte cada año una gran suma de dinero en una de las áreas más importantes, la seguridad. Pese a los fundamentos matemáticos y físicos en los que se basa la ingeniería aeronáutica, así como en otros campos de la ingeniería, los errores y los encadenamientos de actos de fortuitos suceden, lo que provocan grandes desastres casi siempre humanas.

Componentes electrónicos, mecánicos, computacionales, hidráulicos, una aeronave es un conjunto de dispositivos diseñados al milímetro dentro de una estructura física cuya finalidad no es únicamente la de volar, sino hacerlo de la forma más segura. Muchos de estos componentes y dispositivos, por no decir todos, requieren de un constante plan de mantenimiento para prevenir anomalías. Pese a ello, dichos componentes fallan y ante cualquier situación de fallida una aeronave puede seguir volando. El caso más conocido es el de los motores a reacción. Cualquier aeronave puede seguir volando si en pleno vuelo uno de los reactores deja de funcionar.

Pese a la alta fiabilidad de sus componentes, ocurren catástrofes aéreas dónde intervienen varios factores y de los cuales, además como piedra angular, la mayoría tienen como origen el factor humano. En realidad y a grosso modo se distinguen los siguientes factores:

  • Factores humanos a Más del 50%
    • Relacionados con el piloto
    • Otros
  • Factores meteorológicos
  • Factores mecánicos
  • Otros factores

clip_image002Más allá del dato puramente estadístico, lo que destaca es que más de la mitad de factores tienen un origen directamente humano. Los propios sistemas de equipamiento de la aeronave están diseñados para actuar y corregir dichos errores. Por ejemplo, los sistemas TCAS (Traffic alert and Collision Avoidance System) de las aeronaves son dispositivos que detectan, con antelación, peligro de colisión con otra aeronave en circulación equipada con TCAS. El TCAS no únicamente alerta sino que también propone una solución «negociada» con la otra aeronave (más concretamente con su TCAS) de forma que mientras a una aeronave le indicará que ascienda a la otra le indicara que descienda, evitando así la colisión. Por tanto estaríamos hablando de un sistema de defensa de errores provenientes de la persona, bien de los controladores aéreos o bien de los propios pilotos, por ejemplo.

En aeronavegación, todas las aeronaves en con rumbo entre 000 y 179 tienen una altitud o Nivel de Vuelo impar (FL330, FL350, FL370) y las aeronaves con rumbo entre 180-359 tienen un Nivel de Vuelo par (FL340, FL360, etc.). Básicamente y hablando en llano, nunca dos aeronaves chocaran «de frente» mientras estas se mantienen en altitud de crucero adecuado.

En base a esta regla básica de aeronavegabilidad, las colisiones cuando el avión está en altitud de crucero son sencillamente imposibles. Sin embargo durante esta fase (Crucero) es común el cambio del Nivel de Vuelo aumentándose o disminuyéndose según las condiciones meteorológicas o técnicas (ahorro de combustible) así como por razones ajenas e indicadas por el Control de zona (ATC) y es ahí dónde empiezan a haber los primeros riesgos, riesgos que se multiplican cuanto más cerca están de la fase de despegue o aproximación al aeropuerto de destino, debido al tráficos y a las variables de entorno.clip_image004

Si nos lo ponemos a pensar parece incrédulo que dos aviones comerciales choquen a más de 12.000 metros de altura en la fase de crucero y más con componentes como el TCAS ¿verdad?, pues desgraciadamente se han producido colisiones de aeronaves a una altitud de 36.000 pies (FL360).

El Modelo de Error Humano o Swiss Cheese Model

El modelo de error humano o Swiss Cheese Model fue acuñado por primera vez por el británico James T. Reason, quién es conocido cariñosamente como Swiss Cheese Man. Este modelo es utilizado en el análisis de riesgo de los sistemas humanos y también es conocido como el Efecto de Actos Acumulativos o el Modelo de Reason.

El Modelo de Error Humano parte de las premisas:

  • Los humanos no somos infalibles
  • Los errores son esperables

Es decir un error es una consecuencia de un acto preliminar (factores sistemáticos) no como un acontecimiento causal. En este modelo se representan las debilidades humanas como los agujeros de las lonchas del queso de gruyere catalogadas en cuatro niveles de errores:

  • Influencias organizacionales
  • Control de riesgos
  • Condiciones previas a actos inseguros
  • Los actos inseguros en sí

De esta forma, en el modelo se dibuja un escudo defensivo representadas por lonchas y cuyo objetivo no es el de desvelar quién se equivocó sino cómo y por que las defensas fallaron.

El uso metafórico del queso de gruyere no únicamente responde a la idea de las lonchas y sus agujeros y su representación, pues en dicho modelo los agujeros o debilidades humanas cambian, entre loncha y loncha, de forma, tamaño y posición y responden a la subjetividad de dichas debilidades. Gracias a esto se pueden prevenir “trayectorias lineales accidentales” debido a que se puede detectar una debilidad común en todas las defensas. La representación esquemática equivaldría a que de todas las lonchas de queso representando una capa de seguridad, todas tienen un punto común de debilidad por el que un acto casual puede ocurrir sin que haya ni una sola capa de seguridad que pueda evitarlo. Esto responde a errores o actos lineales.

El caso es que en un accidente intervienen diferentes factores y pese a que este modelo está ampliamente aceptado (es de origen psicológico), en muchos campos no únicamente de la ingeniería sino también de la medicina, los accidentes ocurren y cuando eso sucede tenemos la obligación de averiguar los factores que han fallado y han convergido en un desastre.

clip_image002[12]

Sistemas informáticos

La propia organización es la encargada de planificar y ejecutar sus propios sistemas de defensa y en la industria de la informática, de la misma forma que en otras industrias, dicha organización se sustenta en perfiles de mayor a menor responsabilidad. Ninguno de estos perfiles están exentos de responsabilidad y todos y cada uno de ellos forman una parte importante de los mecanismos de defensa.

clip_image009Es signo de fracaso las acusaciones de culpa por parte de los perfiles de más alta responsabilidad hacia los que están en la base del organigrama funcional de la organización. Son intolerables las tendencias a interpretar los actos de modo que confirmen las preconcepciones por parte de los perfiles de más alta responsabilidad dado que en la mayoría de los casos no son más intentos de exculpación. No debemos recordar nuestras propias decisiones como mejor de lo que realmente fueron y sobreestimarlas por encima del contexto de organización así como evitar el Efecto Foco, es decir desviar la predicción de resultados. En definitiva sesgar la información o los actos en base a prejuicios personales.

Contextualizando el Modelo de Error Humano en el ámbito informático, un error o falla es el resultado de la superposición de debilidades de los recursos humanos de una organización más las de la propia organización.

Como recursos humanos existen una multitud de categorías profesionales que abarcan desde los más experimentados (Arquitectos, Jefes de proyecto, Directores IT) a los recién licenciados/graduados (programadores/analistas junior, operadores). Todos y cada uno de ellos deben saber cuáles son sus limitaciones y responsabilidades y éstas deben ser tenidas en cuentas por las personas inmediatamente superior en el eslabón del organigrama organizativo y así sucesivamente. Cualquier acto producido que derive en una fallida debe ser contextualizado en base a si fue una equivocación (descuido, una distracción, una desconcentración, un error al seguir las reglas), un riesgo o un dolo.

clip_image011Las fallas de organización son aquellas cuyo origen las encontramos en el eslabón más alto del organigrama corporativo y la no actuación y prevención de estas fallas se propagan hacia los recursos inmediatamente inferiores del organigrama. Uno de los errores más graves que se cometen es el de la persuasión de recursos de nivel más bajo quedando impunes los de más alto nivel. Un error producido en un programador tiene su origen en los eslabones más altos de la organización. Todo esfuerzo dirigido al reconducir o castigar un recurso de bajo nivel bajo el pretexto de solución sin haber hecho lo propio desde un nivel más elevado, sencillamente será en vano.

Los orígenes de este tipo de fallas organizacionales se encuentran en el liderazgo. Se entiende como liderazgo como el conjunto de cualidades que definen el comportamiento de una persona y que intervienen positivamente en el ambiente laboral de un colectivo. Respeta y serás respetado.

Por otro lado, y siguiendo el hilo de fallas organizacionales, es importante crear una estructura jerárquica y equilibrada de mandos intermedios. Pese a que la experiencia es un grado, el «él lleva más tiempo que tú» es pretexto erróneo (sesgo). La selección y formación del personal así como la comunicación del mismo es uno de los procedimientos que menos importancia se les da, más son indirectamente improductivas y costosas. Por otra parte la calidad y el diseño de equipos así como las presiones operativas y/o comerciales de la propia organización con los clientes derivan en muchos casos, como factor de fallida de origen organizacional.

En busca del “TCAS” informático

Existen multitudes de mecanismos lógicos y físicos que debemos tener presente en todos los campos de las tecnologías de la información y comunicación. En caso del TCAS expuesto en la entradilla de este post tiene una interpretación libre dentro de nuestro campo. Cualquier componente lógico puede ayudarnos a evitar allí donde las debilidades humanas no pueden alcanzar pero también existen doctrinas dentro de la gestión de proyectos que contemplan nuestras limitaciones y las cuales TODAS se basan en la idea de equipo y perfiles y que abarcan y responde al termino CALIDAD.

Mi Opinión

Me preocupa especialmente la fabricación de ataúdes profesionales que algunos responsables de alto nivel llevan a cabo con sus subordinados debido a la falta de motivación y de formación. Esto deriva en una muerte lenta de la carrera profesional de los trabajadores que muchas veces olvidan la atención que  (especialmente en un campo dónde tan rápidamente evolucionan las tecnologías como lo es en el campo de la informática) el propio futuro profesional de un individuo requiere. Básicamente existen tres puntos en los que un empleado presta especial importancia por este orden:

  • Las pretensiones económicas
  • El ambiente de trabajo. Disfrutar con lo que se hace.
  • Su carrera profesional. Es decir la evolución personal dentro de su profesión.

Las descompensación exagerada de algunos de estos tres puntos (especialmente los dos últimos) será la sentencia a muerte (de su carrera profesional se entiende) de un empleado lo cual será catastrófico, primero para el propio empleado y segundo para la propia organización.

Pero, ¿Qué pasa con esos tipos de amplia experiencia que bajo la corbata dirigen y planifican la vida profesional de todos sus empleados?

En primer lugar, jamás sentiré más respeto por un compañero uniformado, por el simple hecho de serlo, que por otro cuya apariencia, sin ser violenta, esté fuera del estereotipo empresarial o social, esté por encima o no de mí. El respecto se gana con la confianza y la confianza se gana con oportunidades. En el momento en que un profesional empieza a tener mayores responsabilidades y mayor gente a su cargo automáticamente se otorga un rango de superioridad y poseedor de la verdad absoluta. Lo que dice él es lo correcto, porque lo dice él y por que la propia organización así permite ejercerlo. No hay lugar a discusión, su razón así como su responsabilidad, son superiores a los de los demás pero sin embargo (y curiosamente) es inversamente proporcional a sus excusas en caso de errores. El marrón se lo come el último y la verdad es que no se me ocurre nada más cobarde y ruin. Del que piensa y actúa así, no le deberé jamás ningún respeto.

Asumir las responsabilidades, defender a capa y espada a sus subordinados, confiar y respetar y recibir lo mismo, otorgar oportunidades y ayudar a descubrir sus debilidades y virtudes. Todo esto es trabajo humano, no productivo directamente pero que forja colectivos “indestructibles”, camaraderías de profesionales excelentes. El hoy por ti y mañana por mí. El “yo cubro tus espaldas”. El evitar el afán de protagonismo. Todo ello deriva en un EQUIPO. Un EQUIPO con mayúsculas pues se otorgan palabrerías de este tipo a colectivos que ni siquiera llegan a ser meros colegas profesionales sobre los que por encima suyo no hay más que un fósil profesional que oculta sus fracasos con su protagonismo inoportuno.

Si no se cumplen los requisitos humanos y éticos es imposible construir cualquier modelo de defensa. Sencillamente todo lo que toque dicha organización estará sentenciado a muerte y seguramente se llevará por delante a alguien (en el mejor de los casos).

 ¡Muerte a la hipocresía! ¡Viva el sacrificio!

¡Más de 200 asistentes registrados en el Code Camp Tarragona 2009!

Pues si, por encima de nuestras estimaciones iniciales, el Code Camp Tarragona 2009 se postula como uno de los eventos de comunidad más importantes del año 2009. Más de 30 sesiones y 30 speakers y con 9 patrocinadores y 3 colaboraciones el Code Camp Tarragon 2009 tiene todos los ingrendientes para ser todo un referente.

No hay escusas. Asistentes de Madrid, Sevilla, Galicia, Bilbao, Valencia, Malaga, Albacete,,, prácticamente desde todos los rincones de España van a estar con nosotros.

Un fin de semana en un Hotel de 4 estrellas en las espectaculares playas de La Pineda con los mayores expertos de .NET y de MONO de todo el país a nuestra disposición. ¿Que más podemos pedir?

¡Anímate y haznos compañia!

Más info: www.codecamp.es

 

 

Listado de recursos de desarrollo para Windows Mobile 6.5

 

A continuación detallo un conjunto de recursos para Windows Mobile 6.X/6.5:

 

Titulo

Tipo  

Descripción  

Programming for Windows Mobile 6.5

 

Artículo

Presenta todos los recursos Online para Windows Mobile 6.5

Developing Web Applications for Internet Explorer Mobile 6 on Windows Mobile 6.5

Artículo

 

Como sacar el máximo provecho a las nuevas características del navegador Internet Explorer Mobile de Windows Mobile 6.5.

Developing Widgets for Windows Mobile 6.5

Artículo

Desarrollar Widgets para Windows Mobile 6.5.

Creating Location-Aware Applications for Windows Mobile Devices

Artículo

Desarrollo de aplicaciones basadas en los Servicios Basados en Localización para Windows Mobile 6.x.

Creating a Compelling UI for Windows Mobile and the Microsoft .NET Compact Framework

Artículo

Aprende a utilizar las API’s de la plataforma Windows Mobile® para aumentar la experiencia de usuario.

 

 

Selecting a Windows Mobile API – .NET Compact Framework and Win32

Artículo

 

 

Este artículo habla acerca de Microsoft® Win32® API y las APIs de Microsoft .NET Compact Framework (NETCF) para Windows Mobile® 6 y posterior.

Getting Started with Building Windows Mobile Solutions with Visual Studio and Windows Mobile 6 SDK

Artículo

Como empezar en el desarrollo de aplicaciones para Windows Mobile® utilizando las mismas herramientas que entornos Desktop con Microsoft® Visual Studio® 2008, y específicamente para Microsoft .NET Compact Framework 3.5. También describe como utilizar las herramientas contenidas en el Windows Mobile SDK.

Optimizing Query and DML Performance with SQL Server Compact Edition 3.5 and SqlCeResultSet

Artículo

 

 

Comparación en la inserción y manipulación de filas utilizando Microsoft® SQL Server® Compact Edition 3.5 SP1, con un especial enfoque para el usuario acerca de cómo utilizar los objetos SqlCeResultSet.

Programming Microsoft Synchronization Services for ADO.NET (Devices)

 

 

Artículo

Una de las características más importantes de Microsoft® SQL Server® Compact Edition 3.5 SP1 es el soporte a Microsoft Synchronization Services for ADO.NET. Esta tecnología de sincronización permite la sincronización de diferentes orígenes de datos para entornos dos, N capas y arquitecturas orientadas a Servicios.

Porting the Amplitude Application from the iPhone to a Windows Mobile Device – a Case Study

Artículo

Case de estudio documentado de portación de aplicación iPhone a dispositivo Windows Mobile 6.5.

 

 

 

Application Verifier

Blog post

Detalles acerca de los pasos necesarios para la certificación de una aplicación al nuevo Marketplace.

GAPI Deprecation

Blog post

El Games API (GAPI) está obsoleto y este post habla de alternativas.

patterns & practices: Mobile Application Blocks – Community Release (was solution factory)

Codigo

Permite a los desarrolladores desarrollar aplicaciones mobile basadsa en VS2008, .NET CF 3.5 y WM6.1. Basado en el block de Mobile Client Software Factory v1, July 2006 e incluye mejoras realizadas por Microsoft Dynamics Mobile PU.

Using Gestures in Windows Mobile 6.5

Documentación

Documentación para la nueva API de Windows Mobile para el reconocimiento de trazas, Gesture API de Windows Mobile 6.5.

Windows Mobile 6 Professional and Standard Software Development Kits Refresh

Descarga

 

 

 

Requisito para Windows Mobile 6.5 Developer Toolkit (DTK)

Windows Mobile 6.5 Developer Tool Kit

Descarga

Windows Mobile 6.5 Developer Tool Kit (documentación, emuladores,…).

6.5 Developer Resource Kit: (External Order Page)

DVD

 
 

FAQ

FAQ de Marketplace

‘How Do I’ videos

Videos

 

Ramp Up, Windows Mobile 6

Webcasts & Hands on labs

Programa RampUp para desarrollo con Windows Mobile 6.x

Windows Mobile Webcasts

Webcasts

Dos webcast específicos para el nuevo API de Gesture.

Fluid – Windows Mobile 6.x Touch Controls

Codigo

Libreria para .NET 2.0 para Windows Mobile 6.0/6.1 con controles Touch.

Windows Mobile Line of Business Solution Accelerator 2008

Descarga

 

Windows Mobile Line of Business Solution Accelerator es un ejemplo de aplicación Windows Mobile que muestra el uso de diferentes tecnologias (WCF, Sync Services, multi idioma, etc.) en una misma aplicación.