EF Code First 6.1 – Estúdialo bien antes de usarlo
22/8/2014 17:36

Últimamente he estado trabajando parar intentar migrar nuestros modelos de datos a EF, la razón principal es que buscamos ser más productivos en desarrollo, reducir nuestro número de procedimientos almacenados y vistas porque su coste de mantenimiento comienza a ser bastante alto. 

Después de estudiar como se comportaba el modelo tradicional de EF con Edmx con modelos de más de 600 tablas, decidí que una aproximación mas adecuada seria utilizar EF Code First, la simplicidad, los metadatos escritos con Fluent Api, la posibilidad de realizar migraciones y aparentemente un rendimiento mayor, fueron algunas de las razonas para seleccionar esta tecnología. En Code First los metadatos de las entidades y toda la información sobre sus relaciones están escritas directamente en nuestras clases C#, así que comencé a pelearme durante algunos días con las plantillas T4 para realizar algunos cambios que requerían nuestras entidades, acceder a los metatados en Code First es mucho más sencillo que hacerlo sobre un modelo tradicional basado en un fichero Edmx, de hecho en el este último hay datos como el nombre del esquema de la tabla y el nombre real de los campos que no pueden ser consultados si no es a través de funciones propias a la base de datos o la lectura directa del fichero de configuración Edmx en formato xml. En nuestro caso necesitaba generar un enumerador en cada entidad con los nombres de los campos de las tablas y el nombre real de la tabla con su esquema. 

General.Divisas

public enum Fields { Codigo,Descripcion,Name,Simbolo,Pais,Grafico,Observaciones }

Algo inicialmente sencillo se complica un poco con aspectos como la pluralización y algunos cambios en los nombres de los campos que EF genera y a los que debemos prestar atención. La pluralización varia el nombre de algunas entidades y campos, si tienes una tabla llamada 'clientes' y un campo llamado 'cliente', la entidad pasa a llamarse cliente, el dbset clientes y el campo 'cliente1', así que hay que prestar atención si en algún momento queremos hacer cambios sin contar con el contexto de EF, lo bueno es que una vez generado, no cuesta mucho Refactorizar algunas entidades si queremos solucionar estos problemas, recordar que en EF Code First partimos de la base de que el modelo es escrito por nosotros. De momento la pluralización en Code First no se puede anular como en el modelo tradicional cuando lo generas a partir de la base de datos por primera vez, tampoco se puede generar el código de una o varias entidades previamente seleccionadas. Un pequeño truco para lograr esto es utilizar un login únicamente con permisos de acceso a las tablas que queramos generar.

La tabla anterior genera la entidad siguiente, o veis cambia el nombre del campo Test

namespace Entities.EntityFramework

{

using System;

using System.Collections.Generic;

public partial class Test

{
    public int Test1 { get; set; }
    public System.DateTime Fecha { get; set; }
    public string Zona { get; set; }
    public Nullable<System.DateTime> Fecha_alta { get; set; }
    public System.DateTime Fecha_modificacion { get; set; }
    public string Description { get; set; }
    public double Precio { get; set; }
    public decimal Cantidad { get; set; }
    public Nullable<double> Total { get; set; }
    public string Observaciones { get; set; }
    public byte[] Foto { get; set; }
}

}

Otros problemas surgen en las vistas, EF quiere que todos los registros tengan un campo clave para poder diferenciar cada uno, en vistas actualizables tiene sentido pero en vistas que solo realizan consultas no, cuando EF genera las entidades de las vistas establece la mayoría de los campos no nulos como campos claves, así que aplique la solución de añadir un rowId a cada vista y utilizar NullIf para identificar los campos que no quieras que sean claves, vamos un coñazo que no sé hasta qué punto tiene sentido, pero no quiero ver esos warnings en amarillo, la otra solución de cambiar el mapeo de las vistas a mano es también otra tarea tediosa y si vuelves a generar el modelo, lo deberás hacer de nuevo.

ISNULL(ROW_NUMBER() OVER (Order By fieldList),-1) as RowID, Nullif(Nombre,'')

Al menos casi todas mis vistas tienen un campo clave :), otras por temas de rendimiento no pude modificar, hay que analizar en detalle cada una, por los problemas de rendimiento que esto pueda ocasionar, sobre todo en aquellas que utilizan unión, recursividad y otros aspectos.

Surgieron también otros problemas con las relaciones, que aún hoy no he logrado explicarme bien y seguro que tienen algún motivo lógico en EF, pero tener que cambiar tu modelo de base de datos para que tu modelo de EF funcione bien no sé si tiene mucho sentido, por ejemplo relaciones de una tabla con solo dos campos en las que cada uno tiene relación con una tabla, provoca problemas al generar las relaciones.

Nuestro sistema trabaja con diferentes bases de datos, la mayor de mas de 700 entidades, la segunda con unas 70 y algunas otras con menos, así que definí un proyecto independiente para cada contexto con las mismas plantillas T4 para que las entidades que se generasen fueran iguales.

Después de resolver estas incidencias, comienzo a realizar algunos test, una simple consulta a la base de datos sobre el modelo mas grande que devuelve un solo valor y la primera gran sorpresa, nada más y nada menos que 65 segundos, investigar el por qué, comienzo a leer algunos artículos sobre bajo rendimiento de EF Code First en la primera query, al parecer el sistema, lo que hace es leer los metadatos de las clases de mapeo, luego genera un fichero Edmx internamente para guardar compatibilidad hacia atrás con EF, posteriormente lo compila y comienza a funcionar igual que EF tradicional, eso si esto se toma la friolera de 65 segundos para hacer todo esto y alguna cosilla mas, en mi maquina un I7 con 4 nucleos, 8 gigas de ram y un disco SSD, vamos , de asustar…

Utilizando el profiler de .net me di cuenta de que el problema estaba en el motor de EF ya que la penalización viene de una la linea similar a esta:

var metadata = ((IObjectContextAdapter) context).ObjectContext.MetadataWorkspace;

En ella EF carga todos los metadatos de las entidades, relaciones, campos compuestos, etc. así que en un principio no me queda mucho que hacer si no investigar un poco al respecto, de todos los artículos que he leído, os aseguro que no me quedan muchos, voy a destacar tres de ellos que os pueden ayudar un minimizar parte del problema. El primer blog de indispensable lectura para todos aquellos que trabajen con EF. Os aconsejo su lectura para entender el artículo al completo.

http://romiller.com/category/entity-framework/
http://www.fusonic.net/en/blog/2014/07/09/three-steps-for-fast-entityframework-6.1-first-query-performance/
http://www.dotnet-tricks.com/Tutorial/entityframework/J8bO140912-Tips-to-improve-Entity-Framework-Performance.html

De todas las ideas que se comentan aquí, la compilación de vistas proporciona algunos segundos de mejora, pero que queréis que os diga, sigue siendo una chapuza, cada vez que modificas algo en el modelo, tienes que volver a regenerar las vistas y lo cierto es que en nuestro modelo el rendimiento de unos pocos segundos más con los tiempos de los que hablamos apenas se notan.

Utilizar ngen con EntityFramework.SqlServer.dll en el GAC, también ahorra algunos segundos, pero tener que integrarlo en cada equipo cada vez que salga una versión de EF también tiene su tela. En resumen algunas mejoras pero que complican el trabajo con EF Code First.

Así que se me ocurrió la brillante idea de analizar exactamente las necesidades básicas de mi modelo, lo cierto es que los campos compuestos y relaciones para acceder a los datos, hacen que la escritura de las consultas en EF sea más cómoda, pero podía prescindir fácilmente escribiendo las relaciones yo mismo tal y como lo hago en Sql Server, ya sé que esto rompe con el modelo EF Code First y alguno pondrá el grito en el cielo, pues cuando haga una migración estas no se generan, pero no se me ocurría otra manera que aumentar el rendimiento, así que a matar pulgas a cañonazos….

Con el replace de Visual Studio y con ayuda de las expresiones regulares, voila, me cargue todo el código relativo a relaciones y campos de referencia a otras entidades.

Y por supuesto después de eliminar tanto código, logre una mejora sustancial, el tiempo bajo a los 32 segundos desde los 65, que le voy a hacer, tengo un montón de relaciones con integridad referencial, continúe y genere las vistas compiladas y metí la librería de Entity Framework en el GAC y logre bajar a la friolera de 14 segundos, (en este punto ya saltaba encima de la mesa pensando lo bueno que soy y blablabla...), pero aquí llegue a un punto de no retorno, ya no sabía cómo podía reducir mas el tiempo, con ayuda de Resharper me puse a buscar entidades no utilizadas y me encontré unas cuantas sobre todo derivadas de vistas que ya no se utilizaban, así que reduje mi modelo en casi 40 entidades más, no hay mal que por bien no venga y lógicamente, mejoro un par de segundos más hasta los 12 segundos.

Más contento que unas castañuelas, me pongo a probar en un virtual con menos memoria sin disco duro SSD para ver cómo se comporta el sistema y la temida sorpresa, el tiempo se incremento hasta los 25 segundos, algo que no entiendo muy bien, pues los dos procesadores no se pasan de un 25% en el proceso inicial, pero bueno, en este punto, casi que prefiero no saber lo que EF estará haciendo internamente, como soy muy positivo comienzo a pensar que los equipos que utilizamos son mejores, incorporan procesadores de 64 bits y 8 gigas de Ram y como el tiempo es solo en la carga inicial del sistema, decido asumirlo temporalmente hasta ver si el equipo de desarrollo de EF proporciona alguna solución, así que el miércoles por la noche lo pongo en producción.

A las 8 de la mañana ya tenía un par de mensajes de algunos usuarios para entrar en la aplicación tienen una demora de más de 2 minutos, incluso para abrir un formulario después de haber cargado los metadatos, la apertura de los contextos que apenas penaliza en mi equipo en la de ellos si lo hace, la única diferencia es que ellos utilizan Windows 7 64 bits y yo Windows 8 64, pues aunque parezca increíble sucede esto, compruebo que ambos tienen instalado .net Framework 4.5.1, lo curioso es que mientras en Windows 8 cargo el sistema en 14 segundos, la misma prueba en Windows 7 64 en un equipo sin SSD tarda 22 minutos!!!!!!, así que no me quedan más ganas de seguir luchando, con todo el esfuerzo invertido casi que me construyo un modelo propio...

Días atrás ya había pensado en una posible solución si todo se complicaba y menos mal que la tenía bastante avanzada, esta consistía en grabar los metadatos de cada contexto en una tabla de la base de datos solo me quedaba cargarlos desde ahí, por supuesto con un DataReader sin contextos ni nada que ponga EF, los metadatos los almaceno en un campo de formato Xml y los cargo al inicio de la aplicación, el modelo completo de más de 800 entidades de contextos diferentes son cargados en menos de dos segundos, evitando hacerlo desde EF Code First, no me queda más remedio que volver a utilizar mis entidades poco y no usar los contextos de EF Code First hasta encontrar una solución.

Cada entidad del modelo almacena la información de cada entidad en un campo XML, como ejemplo:

La parte positiva es que mis entidades, vistas de sql y otros aspectos han sido preparadas para en un futuro, poder utilizar EF Code First, (el que no se conforma es porque no quiere....),

Espero que en algún momento corrijan estos problemas, algo que empiezo a dudar, pues buscando información he encontrado incidencias sobre el rendimiento con modelos de muchas entidades desde el 2011, como ejemplo http://social.msdn.microsoft.com/Forums/en-US/d6edb32d-8479-4a0d-8dc0-caa50f181e5d/extremely-slow-performance-using-codefirst-with-entity-framework-41-release?forum=adodotnetentityframework, así que pondré una vela a San Judas Tadeo…

Sobre los metadatos de EF en el modelo Edmx, todo hay que decirlo, es una auténtica aberración, hasta Rowan Miller Product Manager de EF lo reconoce en algunas de las incidencias en codeplex, pero están trabajando para mejorar esto, pienso que Code First debería ser en parte un modelo desacoplado del actual Entity FrameWork, pues si tiene que generar un archivo edmx desde las clases de mapeo nunca aprovechara todo su potencial, hace algunos años hice algunas pruebas de concepto para cargar los metadatos de esta manera y los resultados son espectaculares, es una pena no poderle sacarle partido.

No puedo entender como sacan una tecnología de acceso a datos sin probarla a fondo con modelos de muchas entidades sobre todo ahora que las necesidades de las bases de datos son cada vez mayores, quizás es que la mayor parte de la gente trabaja con modelos que no exceden las 100 tablas y no se preocupan de más, personalmente sigo pensando que la idea de EF Code First es excelente, desgraciadamente les queda bastante trabajo todavía, sobre todo para modelos como el mío.

Tengo alguna tentación para hacer algún comentario en numerosos post que hablan sobre las bondades de EF Code First, como en http://www.itworld.com/development/405005/3-reasons-use-code-first-design-entity-framework, pero voy a contenerme.. :), pese a todo confió en que algún día solucionen estos problemas y estoy seguro de que EF Code First sera una apuesta de futuro.

Lo cierto es que el equipo de Entity Framework sobre todo Rowan Miller ha contestado a todas y cada una de las dudas e incidencias que he comentado, de hecho han asignado a una persona del equipo de EF para analizar nuestro modelo y ver si podemos optimizarlo de alguna forma, el soporte técnico ha sido excelente.

Mi consejo es que si utilizas modelos pequeños de menos de 100 entidades sin muchas relaciones EF Code First puede ser una buena alternativa, pasando de aquí hay que estudiar en detalle los problemas de rendimiento que se puedan producir. Espero que en la versión 7 se corrijan algunos de estos.

 

por Juan Irigoyen | con no comments
Archivado en:
VisualStudio.com is down
14/8/2014 20:30

Desde las tres de esta tarde ha caído el servicio de VisualStudio.com, podéis tener mas información sobre el estado de todos los productos integrados en Azure en http://azure.microsoft.com/en-us/status/

 

 

Maldivas - Implantación
10/1/2013 0:27

Hace ya casi un año que Maldivas comenzó a funcionar, me gustaría deciros que todo el proyecto ha sido un camino de rosas y que todo ha funcionado a la perfección, sin embargo en estos últimos años hemos luchado lo indecible para sacar este proyecto adelante.

Por el camino y a pesar del conocimiento de muchos de los problemas que se producen en el desarrollo de un proyecto y aunque no es intención de este post buscar responsabilidades, si me gustaría comentar que hemos vuelto a cometer muchos de los errores que se pueden realizar en una gestión de proyectos (si no todos), estimaciones erróneas realizadas por personas ajenas al desarrollo, constantes interrupciones, múltiples cambios de contexto, problemas con la arquitectura y con las herramientas de trabajo, problemas con el equipo de desarrollo, decisiones como dejar de lado la calidad para intentar hacerlo más rápido, muchas horas de trabajo sin descanso, etc.

Maldivas-Grafico1

Maldivas – Erp

La parte positiva es que hemos aprendido de primera mano la importancia de una buena gestión de proyectos, de la utilización de pruebas unitarias, de la aplicación de reglas con herramientas como FxCop y ReSharper que tanto nos han ayudado, de la utilización de algunos patrones de diseño, de la importancia de las reglas de estilo en un equipo de trabajo, de la aplicación de metodologías de trabajo, de la automatización de procesos, de las ventajas de una formación continua y sobre todo, de la importancia de la colaboración entre todas las personas que participan en el proyecto.

No tiene sentido hablar del éxito o del fracaso del proyecto, ya que en este apartado y aunque me pese en cierto sentido, son los usuarios los que han de responder a esta cuestión, también aquí hemos tenido diversidad de opiniones, desde los que dicen que es una maravilla respecto al sistema anterior, algunos que no notaron ningún cambio o aquellos que argumentan que a pesar de las mejoras prefieren sin lugar a dudas el sistema de gestión antiguo. Todas las opiniones son válidas y debemos valorarlas, es importante entender que a lo largo de un proceso de desarrollo, todos cometemos errores y estos deben ayudarnos a mejorar, recuerdo el Sprint Retrospective basado en la mejora continua.

Un aspecto que si he aprendido en este proyecto es el relativo al equipo de trabajo, casi siempre diferenciamos el equipo de desarrollo (‘los raritos y frikis de la empresa’) de los demás, pero aquí más que en ningún otro proyecto en los que he trabajado, he aprendido la importancia que tiene el hacer partícipes a todas las personas del proyecto desde el inicio y que quizás, es mejor pararse o no hacer algo si no contamos con el suficiente apoyo e implicación de estos. Si alguien piensa que tener un buen equipo de desarrollo es garantía de éxito en un  proyecto es que no tiene ni idea de lo que está hablando, el cliente es parte indivisible del equipo, podemos tener un equipo de desarrollo de nivel medio y un cliente que colabore con nosotros y nos aporte feedback para mejorarlo, si tuviera que elegir apostaría siempre por lo segundo. Sin colaboración no hay proyecto posible, da igual lo buenos o malos que sean los desarrolladores, será un fracaso total, al menos hasta el día que estos puedan leer la mente del cliente, que pensándolo bien, quizás con mi Kinetic y aplicando cierta técnica Jedail todo es posible…

Maldivas-Grafico2

Maldivas – Erp

Respecto a los usuarios, muchos realizaron su trabajo correctamente lo que nos permitió anticiparnos y resolver los problemas al finalizar cada entrega, mucho antes de la puesta en funcionamiento del sistema, de esta forma su transición fue mucho mejor, sus problemas minimizados y algunos mejorados porque nos aportaron Feedback y los costes fueron menores pues los abordamos en el momento adecuado, sin embargo, otros usuarios alegaban tener una carga de trabajo alta, lo que les impedía destinar tiempo a comprobar y testar sus aplicaciones al finalizar cada sprint, algunos por diversos motivos creían que sus atribuciones no eran la de testar los módulos con los que iban a trabajar y otros pocos simplemente pasaban de hacerlo. Por supuesto para este segundo grupo, la transición al nuevo sistema fue mucho peor, corrijo, ‘para nosotros fue mucho peor’, ya que tuvimos que trabajar más horas en corregir aquellas incidencias no detectadas para que estos pudieran realizar su trabajo a tiempo, por supuesto su coste fue mucho mayor, pues ha veces tuvimos que modificar ciertas reglas de negocio que afectaban a muchos módulos relacionados y tuvimos que abordarlas en un tiempo muy limitado.

Un aspecto en el que también sufrimos fue la migración de datos que comenzamos al inicio del desarrollo utilizando Data Transformation Services y que finalmente tuvimos que abandonar para utilizar scripts ya que las reglas de integridad y los cambios constantes en las estructuras hicieron de la migración un problema muy complejo que abordar. Finalmente conseguimos realizar una actualización completa de un sistema a otro, que pudimos ejecutar varias veces hasta poner en marcha el proyecto, esto mejoro también el testeo de los usuarios ya que podrían hacerlo con datos reales un factor importante a tener en cuenta en futuros desarrollos, logramos hacer la migración completa sin que ni uno solo de los usuarios introdujese ningún dato, todo un logro para un sistema con más de 500 tablas.

Maldivas-Grafico3

Maldivas – Erp

Sigo pensado que la presión en el trabajo no hace que este mejore sino todo lo contrario, nos hace equivocarnos y cometer más errores. Creo que este debe ser un aspecto a reflexionar con detenimiento, algo que también he observado aplicando Scrum y es la presión que ha veces se ejerce al finalizar cada Sprint, a veces, si la estimación no es adecuada hace que esta aumente cuando el equipo de desarrollo trata de finalizar cada Sprint, es importante tratar de mejorar en las estimaciones para que estos cada vez se adapten mejor, aunque muchas veces cuando hacemos algo nuevo de lo que no tenemos información es ciertamente difícil acertar, debemos recordar que en el Sprint Review también se analizan aquellas tareas que por los motivos que sean no han podido ser finalizadas y trabajar en disminuir la presión del equipo de desarrollo, esta solo nos entorpece y bloquea.

Al final, mucha de la parafernalia de una gestión de proyectos ya sea utilizando Scrum, CMMI o cualquier otra metología se puede resumir en una sola palabra ‘confianza’, la mayor parte de lo que hacemos solo sirve para convencer a nuestros clientes de nuestro buen hacer, me pregunto, si tuviéramos confianza plena, ¿Sería necesario esforzarse tanto para tener una buena gestión de proyectos?, seguro que se pueden argumentar mil y una razones para hacerlo, que si queremos controlar su coste o conocer las desviaciones, que si los requerimientos deben quedar claros, etc., etc., pero no nos engañemos, la respuesta es ‘no’. Lo cierto es que los desarrolladores no ofrecemos demasiada confianza y esto es porque hay algo que todavía no hacemos bien. Estoy convencido de que la confianza de un cliente, debe basarse en entregas constantes de software, estas entregas son las que deben convencer al cliente, si no hay entregas, que más dan los análisis, la documentación y todo el trabajo que hayamos realizado, las entregas demuestran nuestro trabajo, hay algo que funciona y que hemos terminado, que a veces  el cliente puede comenzar a amortizar y a utilizar mucho antes de que el proyecto finalice, que esta abierto a mejoras con la aportación del feedback del cliente, minimizando los costes al asumir cambios de forma temprana, que mejor demostración de nuestro trabajo que la entrega de software, aunque lo cierto es que también hay clientes complicados, pero bueno, el mundo no es perfecto.

Maldivas-Terminales 1 Maldivas-Terminales 3 Maldivas-Terminales 2

Maldivas – Dispositivos móviles

Desde la puesta en marcha del proyecto, a pesar de las pruebas unitarias y del trabajo que hemos realizado por escribir código de calidad, se han resuelto más de 1600 incidencias y se han realizado unas 800 nuevas propuestas de mejora. Día a día continuamos progresando y adaptando el sistema a nuevas especificaciones. Debemos recordar que las pruebas unitarias no garantizan el correcto funcionamiento de un programa, existen muchos tipos de pruebas mas que debemos abordar para que una aplicación funcione correctamente, la aportación de la visión de los usuarios es siempre indispensable para asegurar un correcto funcionamiento, es muy difícil simular todo aquello que puede hacer un usuario con un programa y si encima es lunes o ha bebido un par de copas la cosa se torna imposible… Sonrisa

Hemos aplicado diversas tecnologías, como sabéis, nuestro modelo de datos está basado en entidades POCO, utilizando un data-mapper propio basado en generics y reflexión, lo cierto es que si hubiéramos contado con Entity FrameWork nos hubiéramos ahorrado un montón de trabajo pero así es la vida unas veces por delante y otras muy por detrás, pensar que un proyecto que nos ha llevado varios años y finaliza en Windows Forms, una tecnología actualmente en ‘desuso’, me entran hasta escalofríos de pensarlo, aunque supongo que en la mayoría de proyectos a largo plazo esto es así.

El desarrollo se comenzó en el 2006 con VS 2005 y se ha finalizado con VS 2010, aunque actualmente ya funciona con VS 2012, utilidades como FxCop, ReSharer, CodeRush, Stylecop, Pex and Molex, Visual Studio for Database Developers, nos han ayudado mucho a mejorar la calidad, como gestor de proyectos hemos utilizado TFS, hemos integrado la suite de controles de Devexpress, Sql Server como servidor de base de datos e IIS 7 como servidor web. Hemos implementado procesos en segundo plano utilizando programación asíncrona, paralelización, cache, Servicios Windows, Servicios web, Linq, Serialización de archivos, etc.,

Maldivas-Web 1   Maldivas-Web 2

Maldivas-Web 3

Maldivas – Comercio electrónico

La aplicación tiene múltiples opciones Gestión de usuarios y permisos, enlaces con Office Outlook, Excel y Word, Gestor documental, Estructuras de fabricación, Gestión de órdenes de trabajo, Planificación en base a la demanda basada en sistemas Lean Manufacturing, , Multiempresa con bases de datos diferentes, Generación automática de asientos contables, Gestión de rutas, Enlaces bancarios norma 58 y Gestión de remesas de Confirming, Generación automática de asientos contables, Scheduler, Envió de información automatizado, Gestión de costes, Modulo de consultas y estadísticas, Diseño de Informes por usuarios avanzados, Gráficos interactivos, Cubos OLAP, Picking a través de dispositivos móviles, Comercio electrónico y muchas de las opciones que se integran en un ERP, desde el control de stocks, pasando por la Calidad, Compras, Ventas, Financiera, Recursos Humanos, etc.

Y para el futuro… pues Maldivas continuara creciendo y actualizándose, nos quedan muchas mejoras que realizar, intentaremos aumentar la cobertura de código con pruebas unitarias, integración con Sharepoint, desarrollo de parte del sistema de producción, aumento de las aplicaciones con Dispositivos móviles y porque no, quizás hasta alguna aplicación en Tablet, migración del sistema de comercio electrónico a ASP MVC, introducción de EF como modelo de entidades, creación de y adaptación de formularios en WPF, etc.

Aprovecho este post para dar las gracias especialmente a mi compañero Eduardo Obregon, que tanto me ha aguantado, sobre todo en los momentos difíciles de estos últimos años y que gracias a su calidad personal y trabajo ha contribuido a que este proyecto fuera posible, a los usuarios que nos han ayudado aportando Feedback y que han contribuido con sus ideas a mejorar este programa, a mi jefe que siempre me ha escuchado y con el que he podido discutir abiertamente de mis problemas y aquellas personas que siempre han confiado en que pese a los problemas y el tiempo invertido lograríamos realizar este proyecto del que más de una vez pensé en abandonar.

Bueno, si habéis llegado hasta aquí, (vaya rollo que os he contado), espero que al menos echéis un vistazo a unos videos que diseñamos para formación interna que os permitirán haceros una idea del proyecto. Todos los datos del video de formación son ficticios. Se realizaron pensando en que la mayor parte de los usuarios no disponía de tarjeta de sonido sin audio, pero tienen subtítulos que podéis activar desde el menú inferior de YouTube, también os aconsejo subir la resolución para visualizar correctamente el video, estos se han filmado en 1280 x 800 aunque la resolución óptima del programa es de 1440 x 900, así que algunos formularios se verán bastante comprimidos.

Video 1 - Maldivas - Características generales

La primera versión del sistema de terminales se desarrolló en el 2002 con Compaq Framework Beta 1, este ha sido adaptado para su integración con Maldivas

Video 2 - Maldivas - Terminales móviles

Video 3 - Maldivas - Terminales gestión

La primera versión del sistema de comercio electrónico se desarrolló en ASP.Net 2.0 en el año 2005 y actualmente estamos trabajando para su integración completa en Maldivas con ASP Mvc.

Video 4 - Maldivas - Comercio electrónico

Espero que os gusten y os aporten alguna idea en vuestros desarrollos.

 

Para adaptar la configuración en Youtube:

clip_image001

El icono amarillo muestra donde activar la resolución.

clip_image002 
El icono amarillo muestra como activar los subtítulos.

Scrum - Comparte tu Backlog con el Cliente
29/8/2012 20:22

Los mayores problemas que se producen en la gestión de proyectos se dan en el flujo de información, ocurre muchas veces que esta se tergiversa cuando pasa entre las diferentes personas que trabajan en el proyecto y al final se desarrolla algo que muchas veces no ofrece una solución para el problema presentado por el cliente. Esto hace que la relación con tu cliente se degrade y al final tu proyecto se demore haciendo que este tenga un mayor sobrecoste y perjudicando tu relación con el cliente.

Creo que todos conocéis la graciosa imagen que representa esto:

clip_image001

Un problema habitual se origina en el control de la entrada de información. Se dice, que normalmente debe existir una sola persona que trate con el cliente, yo pienso que esto es algo complicado de gestionar, sobre todo en grandes proyectos, en los que participan muchas personas, pues el cliente a veces, prefiere tratar con miembros del equipo de desarrollo con los que ha tenido mayor relación, con lo que la entrada de información puede originarse a través de los diferentes miembros del equipo y de esta forma las alteraciones con seguridad serán mayores, pues cada uno tendemos a interpretar la información a nuestra manera. Cuanto mas cercano se encuentra el equipo con respecto al cliente y mayor número de personas participan en el proyecto más difícil es controlar esta entrada de información.

Yo creo que la información debe introducirse solo por un sitio, y a ser posible sin interaccionar con más personas, para evitar filtros, modificaciones o interpretaciones personales y que esta sea fiel reflejo de los pensamientos del cliente, inclusive si esta presenta algún error para que posteriormente pueda ser analizada por todo el equipo. Pienso que debemos huir del pensamiento de que sea una sola persona la que hable con el cliente, que procese, filtre y finalmente traslade la información al equipo de desarrollo. Esto traslada toda la responsabilidad a una sola persona que puede cometer errores en la planificación y el diseño, al no contar con información relevante de otros miembros del equipo de desarrollo que seguramente conozcan a fondo áreas del cliente en las que han estado trabajando. Creo que deber ser el equipo al completo, el que analice la información y tome las decisiones en conjunto pues entre todos contaremos con una visión general mas completa para resolver el problema.

A veces el cliente llama directamente o la persona encargada del proyecto habla con el personalmente, el cliente traslada cualquier problema o necesidad con una prioridad determinada para resolverla. En este caso se producen varios problemas adicionales:

- Por un lado el cliente interrumpe el trabajo que estas haciendo y aquí se producen las mayores pérdidas de productividad, porque estas interrupciones nos obligan a veces a dejar tareas importantes. haciendo que la productividad decaiga en picado, no solamente se pierde el tiempo de la interrupción, si no que después obliga a que la persona tenga que volver a concentrarse para poder continuar el trabajo que estaban realizando. Debemos intentar eliminar estas interrupciones, cuando veo equipos de desarrollo en los que habitualmente hay una o dos personas hablando constantemente por teléfono suelo pensar que las cosas se están haciendo mal. Debemos eliminar estas interrupciones, las reuniones de scrum están para algo y debemos tratar de minimizar las conversaciones con el cliente, sobre todo aquellas que son por teléfono y que no quedan debidamente registradas o pueden sufrir diferentes interpretaciones y que además, afectan al rendimiento de las demás personas del equipo que se encuentra en el mismo entorno. Pienso que una buena solución aunque a algunos les suene un poco radical es simplemente descolgar el teléfono y bloquear las entradas de información como skype, en nuestro caso intentamos centrarnos solo en el email que nos permite estar al tanto de cualquier incidencia urgente que requiera una atención inmediata, las conversaciones con un cliente no aportan absolutamente nada, la información no queda registra y esta normalmente llega alterada al repositorio, lo que si puede aportar valor como veremos mas adelante es un diálogo con un cliente que quede registrado en el sistema y que no obligue a ninguna de las dos partes a interrumpir su trabajo.

- Puede ser además, que cuando el cliente llame le atienda una persona que no conozca a fondo su contexto de trabajo y de esta forma no sepa captar adecuadamente sus necesidades trasladando información incompleta o errónea al equipo de desarrollo.

- La información que nos traslada el cliente no queda registrada, con lo cual nunca sabremos si esta ha sufrido alguna alteración, es importante que todos los diálogos sobre un ítem determinado queden registrados y esta información sea accesible tanto por el propio cliente como por los miembros del equipo de desarrollo.

- Por otro lado a veces el cliente establece una prioridad determinada abduciendo que la necesidad es urgente y prioriza tu trabajo, de manera que esto nos obliga a dejar de lado aquello que estamos haciendo, para solucionar el problema lo antes posible, dejando aquello que teníamos planificado y que a veces puede tener una mayor prioridad.

- Muchas veces, parte del equipo de trabajo no cuenta con esta información a tiempo, ya que se comienza a desarrollar mucho antes de que el equipo pueda evaluar su solicitud. En estos casos a lo mejor no conocemos toda la información necesaria y ofrecemos una solución errónea debido a dependencias desconocidas y hacemos algo que debería haber sido correctamente planificado y estudiado.

Este y otros problemas son derivados del flujo de información y se convierte en una de las principales causas por la que muchos proyectos fracasan.

Una solución que a nosotros nos ha funcionado muy bien es la de intentar trasladar y compartir el backlog del proyecto con el cliente, con ello evitaremos la mayoría de estos problemas y lograremos varias ventajas:

- Se minimizan las interrupciones: Ya no tenemos que atender al cliente por teléfono o skype cada vez que nos llame, podemos visualizar las incidencias y requisitos que van llegando y pararnos solo si detectamos que estas requieren una atención inmediata, de esta forma podemos trabajar sin constantes interrupciones, el cliente también se beneficia del mismo sistema de trabajo, si tenemos que realizar alguna pregunta sobre un requisito en concreto utilizaremos el mismo sistema de dialogo con el, evitando interrumpirle en su trabajo y minimizando nuestro tiempo para contactar con el.

- Registro del flujo de información: Por un lado tanto el cliente como el equipo son los que escriben la información y esto queda registrado, con lo que evitaremos las alteraciones en la información cuando las filtra cualquier persona que hace de intermediario.

- Una mejor información disminuye los tiempos de desarrollo: Muchas veces una llamada no es suficiente para describir adecuadamente un problema, si el sistema de gestión del backlog permite adjuntar archivos, el cliente puede fácilmente introducir un documento, un gráfico o cualquier tipo de información que considere de interés para facilitar su comprensión, esto facilita mucho que la información este localizada en un lugar determinada y que el equipo entienda el problema adecuadamente evitando que perdamos el tiempo buscando o intentando entender mejor el proceso.

- Seguimiento del proceso: El cliente puede conocer en tiempo real la situación de su incidencia, mejora o el desarrollo de una nueva funcionalidad que haya solicitado, pudiendo además obtener información adicional, fecha de planificación, personas que lo desarrollaran, estado actual, etc, etc. Esto es muy importante pues evita constantes interrupciones con preguntas del tipo: ¿Ya has terminado aquello?, ¿Por qué no se ha hecho? ¿Qué problemas habéis tenido en el desarrollo?, de esta forma el cliente tiene constancia de las incidencias que ocurren, puede ocurrir que el desarrollo de un módulo tal y como propone el cliente afecte a otros módulos que el desconoce y es importante que si no se realiza como él ha solicitado pueda conozca las causas o los motivos por los que se ha realizado de otra manera.

- Por otro lado esta información va quedando almacenada en un histórico, de manera que otros usuario pueden acceder a esta información sobre problemas que ya tienen una respuesta determinada. Este debería ser un proceso que el cliente debe hacer antes de introducir una nueva incidencia, de manera que pueda beneficiarse de soluciones que ya hayan sido realizadas obteniendo una respuesta inmediata evitando requerir al equipo de trabajo.

- La información fluye hacia todos los miembros del equipo: Esto es fundamental en un equipo de desarrollo, algunos miembros del equipo desconocen como se han desarrollado otros módulos y las dependencias entre ellos, todo el equipo debe conocer el trabajo de los demás para así poder ofrecer la información relevante a otros miembros del equipo que la desconocen y lograr la solución mas adecuada.

- Filtrado de información: Normalmente no nos interesa compartir toda la información con toda la gente que participa del proyecto, nuestro sistema permite compartir solo aquellos ítems que deseemos con determinadas personas que trabajan en el cliente, de manera que el director financiero quizás no quiera visualizar información que solo es relevante para el responsable de nóminas, es importante que podamos controlar con quien queremos compartir esta información, no todas las personas que trabajan en el proyecto necesitan estar informadas de todos los aspectos de este. Con lo que logramos que la información fluya solo a aquellas personas relevantes evitando sobrecargar de información a otras que no la necesitan.

- El sistema de alerta nos avisa de cualquier incidencia urgente: Es importante que existan ciertos mecanismos que nos permitan notificar rápidamente una incidencia urgente, que se bloquee un servidor de BD requiere atención inmediata, nuestro sistema de alertas a través de email hace que estemos informados en tiempo real de cualquier incidencia grave y esto nos permite reaccionar con rapidez.

- El equipo de desarrollo planifica y prioriza: Somos nosotros los que debemos priorizar, no el cliente, el cliente no tiene toda la información relevante del desarrollo del proyecto y el equipo si, muchas veces ocurre que para el cliente es muy importante la realización de una tarea en concreto, pero en el proyecto pueden existir otras tareas que tengan una prioridad mayor, con un backlog compartido podemos cambiar la prioridad y notificar al cliente del porqué de estas decisiones, para justificar y hacerlo participe de nuestro trabajo.

Voy a poner un ejemplo de un ítem de un backlog para ver su funcionamiento, en este caso hemos implementado un pequeño programa para realizar esta operación, que notifica de forma automática a los usuarios a través del correo electrónico de cualquier cambio en el backlog, he leído en alguna parte que en la nueva versión del TFS, esto va a ser posible, seguro que El bruno puede avanzarnos algo sobre este tema.

1º - El cliente notifica un nuevo ítem.

Código: 4212 Fecha: 12/07/2012 9:12 Prioridad: Urgente

Usuario: Jose Angel García (Cliente - Agente comercial)

Descripción: Necesitamos que en el informe de facturación aparezca el número del agente de aduanas. Te adjunto un pdf con el informe de la factura para que veáis como debe quedar.

2 º - Hemos recibido su notificación con fecha 12/07/2012

3º - Respuesta de Ana Martínez (Responsable del proyecto) a la notificación nº 4212 el día 13/07/2012 10:00

La propuesta indicada será realizada por Julio Otero (Desarrollador).

Uno de los miembros del equipo comenta que las facturas pueden contener varios albaranes y estos podrían utilizar un agente de aduanas diferente, como procedemos en este caso.

4º - Respuesta de José Ángel García (Agente comercial) a la notificación nº 4212 el día 12/07/2012 11:45

Este caso no se puede dar, ya que antes de hacer la factura se comprueba que todos los albaranes tengan el mismo agente de aduanas, si existiesen albaranes con diferente agente se generarían varias facturas.

5º - Respuesta de Ana Martínez (Responsable del proyecto) a la notificación nº 4212 el día 12/07/2012 12:25

Bien, en este momento no podemos hacerla pues existen dos incidencias prioritarias que debemos resolver antes, cambio la fecha de planificación para el día 16/07/2012, para salir del paso podéis editar el PDF de la factura e introducirlo de forma manual.

6º - Respuesta de Julio Otero (Desarrollador) a la notificación nº 4212 el día 17/07/2012 10:25

La notificación 4212 ha sido resulta, te envió el pdf adjunto para que verifiques si todo esta correcto.

7º - Respuesta de José Ángel García (Agente comercial) a la notificación nº 4212 el día 17/07/2012 11:00

             Lo he verificado y funciona correctamente.

8º - Cerrada la notificación número 4212 por José Ángel García (Agente comercial)

De esta forma la información fluye sin que tengamos que controlar por donde entra y quien la procesa, ya que existe un solo punto de entrada (la aplicación que permite acceder a nuestro backlog), se disminuyen las interrupciones ya que no tenemos que hablar directamente con el cliente, la información sobre los cambios se distribuye de forma automática notificando al cliente por email de cualquier cambio que se produce, nos permite planificar y cambiar la prioridad de la tarea y estudiar mejor los cambios a aplicar, es el cliente quien escribe sus necesidades, y estas no se tergiversan, el registro guarda la información tal y como el cliente la ha introducido, el equipo trabaja como un conjunto en la planificación de tareas y la corrección de errores evitando errores en el diseño por el desconocimiento de las dependencias y ofrece entre todos sus miembros una solución mas adecuada y el sistema de alertas notifica en tiempo real de cualquier incidencia grave que pueda surgir para permitirnos reaccionar con rapidez.

He puesto Scrum porque es la metología que utilizamos, pero creo que este sistema de trabajo es trasladable cualquier metodología Ágil, si habéis llegado hasta aquí, espero vuestros comentarios.

Visual Studio 2012 – Primeras impresiones
29/8/2012 17:02

Llevo ya varios días trabajando con la nueva versión de VS, lo cierto es que después de las últimas versiones, me esperaba mas de lo mismo, los mismos errores sin corregir versión tras versión, los cuelgues con el diseñador de formularios que se producían a diario, la carga eterna de los controles del toolbar, los enormes tiempos de compilación, etc, etc, nada mas lejos de la realidad, por fin, después de estos años parece que las cosas han empezado a cambiar, los desarrolladores somos un valor al alza, (me gustaría saber cuanta culpa tiene Google y Apple) en todo esto.

La primera vez que arrancas VS 2012 y observas el menú, ya te dan ganas de salir corriendo, vaya un diseño que han aplicado, colores grises, fuentes del menú principal en mayúscula, etc, he leído que se están acercando el diseño Metro, yo creo que el diseñador principal debería acudir a un par de desfiles de Victoria Secret, a ver si se le pega algo sobre la combinación de colores, aunque lo cierto es que después de unos pocos días de trabajo, el diseño es, con diferencia lo que menos importa, por mi, como si en la siguiente versión solo funciona en una pantalla de fosforo verde.

En lo que al entorno de trabajo se refiere, han corregido los errores de las versiones anteriores y han mejorado en gran medida el performance general de todas las operaciones, verificación de las reglas de fxcop, unit test, el diseño de los formularios ya no da errores constantemente debido a la carga en memoria de librerías, la carga del toolbar ya no te hace esperar varios minutos, algunos de nuestros proyectos tienen un gran número de controles y esto hace que cada vez que querías diseñar un formulario después de compilar se tuviera que regenerar de nuevo toda la tabla de controles, la carga de los proyectos se realiza en paralelo y en soluciones con muchos proyectos el tiempo de espera se reduce considerablemente, mi conexión remota al servidor de TFS utilizando una VPN a funcionado a la primera, por fin no pierdo las credenciales cada dos por tres, los tiempos de compilación han mejorado mucho, increíblemente no he encontrado ni un solo problema, he instalado Coderush y Resharper y funcionan de maravilla a pesar del aumento de los recursos que requieren.

En el desarrollo diario con Visual Studio 2010, os puedo asegurar que muchos de estos problemas suponían unas perdidas de tiempo enormes, hemos calculado que mas de una hora diaria por persona, esto supone para algunas empresas de desarrollo unas perdidas enormes, no entiendo porque no han corregido estos problemas hasta ahora, pero al menos lo han logrado en esta versión, ya era hora, en estos días no hemos tenido ni un solo problema trabajando con VS 2012, de hecho acabo de borrar de mi equipo la versión de VS 2010, a su favor diré que era mucho mas bonito...

Por fin, Entity FrameWork 5, permite realizar diferentes diagramas, al fin podremos trabajar en el diseñador con bases de datos que contiene muchas tablas, aunque los nombres de estas siguen sin incorporar el esquema de seguridad, algo con lo que sigo sin estar de acuerdo, no es lo mismo una tabla llamada dbo.Articulos que gestion.Articulos y en este caso EF llama a la primera Articulos y a la segunda Articulos1 y no muestra el nombre completo con su esquema, algo que para nosotros es importante, pues forma parte del esquema de seguridad de la tabla y siempre debe ser reflejado en las consultas.

Uno de los problemas que he visto y que no me ha gustado nada, es que después de actualizar uno de los proyectos a la versión 4.5 del FrameWork basado en Windows Forms, nos hemos dado cuenta que al instalar este en equipos que usen XP no funciona, en la información de Microsoft aparece que solo se da soporte a versiones que parten desde Windows Vista hacia adelante, parece que Microsoft quiere forzar a que los usuarios actualicen a Windows Vista o Windows 7, pienso que es un gran error no dar soporte a Windows XP, hay muchos equipos que funcionan muy bien con este S.O. y que no tienen ninguna necesidad de actualizarse o que su hardware no les permitirá hacerlo, pienso que deberían haberse esforzado en hacerlo compatible al menos para soluciones realizadas en Windows Forms, que todavía hoy siguen siendo la mayoría.

Sigo sin entender que pasa con el desarrollo de los dispositivos móviles industriales en Windows CE y Pocke PC, están abandonando un sector que tiene un potencial increíble, no he visto que Windows Phone se integre todavía con estos dispositivos, pero en fin, ya llegara alguien para hacerse con este hueco y luego llegaran las prisas como con Windows Phone y Windows 8, parece que algunos no reaccionan hasta que viene alguien y se hace con su mercado.

No he tenido tiempo de ver mucho mas, algún proyecto en ASP.NET y ASP MVC que han funcionado sin problemas, pero si os diré que en general, la primera impresión ha sido muy positiva, pienso que han realizado un excelente trabajo en esta versión, así que animaros Visual Studio 2012 supone un cambio enorme respecto a las versiones anteriores, solo las mejoras de rendimiento ya justifican el cambio, espero que continúen así.

Flexibilidad laboral
27/5/2011 15:44

Me asombra ver como a día de hoy con la gran crisis en la que estamos inmersos, la mayoría de empresas siga optando por los métodos de control hacia sus empleados y no utilicen métodos para aumentar la flexibilidad de sus trabajadores, esta es una de las razones del porque España y otros países nos encontremos a la cola en lo que a productividad se refiere.

No puedo entender cómo, ya no las Empresas, si no algunos compañeros e incluso amigos, se asombren cuando les comentas que trabajas fuera de tu centro de trabajo, la mayoría llegan rápidamente a la conclusión de que esto es totalmente improductivo y se quedan perplejos ante este tipo de prácticas.

En mi caso, tengo la “suerte”, (parece como que me haya tocado la lotería…), de que mi Empresa me permite realizar este tipo de prácticas, es curioso como mi productividad y mi calidad de vida aumentan cuando trabajo fuera del entorno laboral, bajo mi punto de vista se producen varias ventajas:

Por un lado este planteamiento me permite eliminar los límites de horarios y tu trabajo se convierte en algo cotidiano y más cercano, dejas de ver el trabajo como una obligación con el que tienes que vivir.

Una de las mayores ventajas, es que el individuo se siente mucho más valorado pues entiende que hay una gran relación de confianza y de esta manera se siente más integrado con su entorno laboral.

Hay momentos en que uno está centrado y se encuenta cómodo trabajando más y otros sin embargo, en los que no tienes la cabeza para resolver un problema determinado, en este trabajo, muchas veces creativo, todos sabemos que hay momentos en el que podemos solucionar un problema al cabo de toda una semana y otros, en tan solo unas horas, la flexibilidad laboral nos permite adaptar nuestro estado y maximizar nuestra productividad. Comentaba Joel Spolsky en uno de sus artículos en los que analizaba sus ratios de productividad que entre reuniones, llamadas, aspectos burocráticos y otros factores, concluía que sus ratios de trabajo real estaban en torno a las 2 y 3 horas diarias, “en el caso de los Españoles lo tendríamos que dividir por PI…”,así que contamos con un gran marguen de mejora.

Supone un ahorro de costes para las dos partes, la empresa disminuye sus gastos en medios, energía, oficinas y otros factores y los empleados el gasto enorme en combustible, mantenimiento y amortización del vehículo.

Se produce un importante ahorro de tiempo en desplazamientos que podemos utilizar en otras tareas lo curioso es que hay gente que todos los días pierde dos o tres horas diarias en desplazamientos a sus centros de trabajo para realizar trabajos administrativos que fácilmente pueden estar sujetos al tele-trabajo.

Por otra parte, es sumamente importante maximizar nuestro tiempo libre, esto nos permite despejar la mente y disfrutar más de nuestra vida y se convierte en uno de los principales motivos para aumentar nuestra productividad, si llegamos contentos y despegados a nuestro trabajo, este se convierte en un elemento más de nuestra vida cotidiana y desaparece como tarea para convertirse en algo importante en nuestras vidas.

Las interrupciones disminuyen, en tu empresa, ya no te llaman para cualquier cosa sino para las que realmente te necesitan, ocurre muchas veces cuando te encuentras en el centro de trabajo que mucha gente demanda tus servicios para cosas sin importancia, solo por el hecho de que estas ahí y presuponen que para ti, solucionar un problema es más fácil que para ellos, así que prefieren llamarte a intentar solucionarlo por ellos mismos, esto aumenta las interrupciones en tu trabajo y te impide ser productivo. Si te encuentras fuera, te suelen llamar o convocar para aquello en lo que eres realmente necesario disminuyendo los recesos.

Para los empresarios se convierte también en un elemento que permite incentivar a sus trabajadores. Estos valoran mucho este tipo de prácticas, a veces muy por encima incluso de los incentivos dinerarios, para mi es un factor determinante a la hora de plantearte siquiera cambiar de trabajo, la flexibilidad laboral supone un arma muy potente a la hora de negociar un contrato laboral.

Pero con todo, también existen desventajas, no todos cumplimos con un perfil para trabajar en un entorno de este tipo y no todos los trabajos permiten la flexibilidad laboral, para ello se deben dar una serie de circunstancias, tu implicación con la empresa y tu trabajo debe ser alta, debes ser responsable e intentar cumplir con los objetivos, existen individuos que sin control no son capaces de trabajar en un entorno de flexibilidad o están habituados a trabajar en entornos controlados, cuando eliminas estas barreras lejos de mejorar la productividad, esta disminuye. Habría que preguntarse también si queremos contar con estas personas en nuestro entorno laboral, aunque a veces no queda más remedio.

Algunos individuos, cuando se encuentran lejos del entorno laboral se sienten en la obligación de trabajar a todas horas y esto, aunque cueste creerlo, al final también disminuye la productividad y empeora la calidad de vida, pues la presión del trabajo constante se va haciendo mayor, es muy importante aprender a que todas las actividades diferentes con tu familia, el deporte, los amigos, tus hobbies y por supuesto el trabajo se complementan ayudando a las personas a conseguir un equilibrio que posteriormente les permitirá abodar mejor los diferentes problemas de su vida laboral, debe existir un equilibrio en la vida de cada persona para poder sacar lo mejor de cada uno, algunos necesitaran más tiempo libre, otros en cambio necesitaran estudiar o trabajar más, es importante aprender a conocernos mejor para aumentar nuestro bienestar y consecuentemente nuestra productividad, esto es algo que han entendido a la perfección empresas como Microsoft, Google y otras, por algo son ellas las que mayores beneficios obtienen.

Entiendo que siempre debe existir cierto control y para ello contamos con infinidad de herramientas, debemos habituarnos a estimar e intentar cumplir con los objetivos marcados, en la mayor parte de los trabajos no utilizamos ninguno de estos métodos, no existe evaluación continua ni por objetivos. La utilización de metodologías puede ayudarnos mucho en este aspecto. En resumen, creo en el control, pero en el control intentado dotar al individuo de una mayor libertad y confianza para incentivarle y ayudar a mejorar su desarrollo profesional.

Creo que los empresarios, al menos yo cuando lo era, lo único que buscaba eran personas de confianza que resuelvan los trabajos que había que realizar, lo demás es completamente secundario. Las Empresas tienen la obligación de utilizar todos estos métodos para mejorar sus ratios de productividad y deben de empezar a comprender que aquellos basados en el “control” son completamente improductivos, y está siendo sobradamente demostrado por todos aquellos Países más avanzados que nosotros que utilizan este tipo de prácticas de forma natural y logran indices de productividad mayores. Debemos cambiar la forma de trabajar, pienso que muchos de los problemas existentes hoy en día, podrían resolverse fácilmente si todos fuésemos un poco más “flexibles”. Sigo creyendo que el verdadero valor de las empresas esta en las personas que las forman y será el conjunto de todas ellas las únicas que podrán hacer que estas tengan un futuro.

Productividad-forg

Quiero con este post animar a las Empresas para que utilicen estos métodos que por otra parte son “gratis”, como elementos que les permitan mejorar la productividad, la captación de mejores empleados y la mejora del ámbito laboral. También animaros a todos vosotros para que la flexibilidad se convierta en un elemento de negociación importante a la hora de trabajar para una empresa, no solo hay que negociar el sueldo, debemos luchar porque las empresas apliquen estos métodos que permitirán mejorar nuestra productividad.

Un saludo.

 

Pd. Es increíble que desde hace años las empleadas de líneas eróticas realizan el trabajo desde su casa. Curiosamente a nadie le choca este hecho…

Utilizando Arrays de parametros en Procedimientos Almacenados con Sql Server
17/10/2010 22:46

Una característica muy solicitada por los desarrolladores en Sql Server es la de poder pasar varios valores a un procedimiento almacenado en forma de array. Desde la versión 2000 utilizaba una función de Sql que me permitía trabajar con Arrays a través de una cadena de texto delimitada por comas, normalmente los utilizaba en procesos de selección como en el ejemplo siguiente:

CREATE PROCEDURE GetCustomers @codes VARCHAR(MAX) AS
SELECT CustomerID, Name, Phone, Country
FROM Customers
WHERE CustomerID IN (SELECT * FROM [dbo].[ArrayToTable] (@param))

 
En este procedimiento el parametro @codes recibe una cadena delimitada por comas con los valores ’12,54,89,104,221,423,1239’, el sp devuelve todos los clientes con estos códigos, la definición del parametro ‘@codes’ se realiza con varchar(MAX), para que la cadena pueda almacenar la mayor cantidad de códigos posible, sin embargo varchar(MAX) tiene la limitación de 8000 caracteres y en algunas situaciones se nos puede quedar pequeño.
 
La definición de la función en Transact-Sql es la siguiente:
CREATE FUNCTION [dbo].[ArrayToTable] (@delimStr NVARCHAR(max))
RETURNS

@StrValTable TABLE
(
-- Add the column definitions for the TABLE variable here
StrVal VARCHAR(20)
)
AS
BEGIN
-- Fill the table variable with the rows for your result set
DECLARE @strlist NVARCHAR(max), @pos INT, @delim CHAR, @lstr NVARCHAR(max)
SET @strlist = ISNULL(@delimStr,'')
SET @delim = ','

WHILE ((len(@strlist) > 0) and (@strlist <> ''))
BEGIN
SET @pos = charindex(@delim, @strlist)

IF @pos > 0
BEGIN
SET @lstr = substring(@strlist, 1, @pos-1)
SET @strlist = ltrim(substring(@strlist,charindex(@delim, @strlist)+1, 8000))
END
ELSE
BEGIN
SET @lstr = @strlist
SET @strlist = ''
END

INSERT @StrValTable VALUES (@lstr)
END
RETURN
END

GO

Básicamente lo que hace es crear una tabla temporal conformada por un campo y cada valor en un único registro, de esta forma la consulta de arriba puede ser ejecutada sin problemas, hay que tener en cuenta que el uso de tablas temporales puede reducir el rendimiento, sin embargo es mejor esto a llamar al SP muchas veces. Podriamos tambien optar por pasar los arrays con XML y readaptar la función.

Sin embargo en la versión 2008 aparecen los User-Defined Table Type, que permiten definir la estructura de una tabla, que posteriormente puede ser utilizada para pasar valores a un SP.

clip_image001

Para el ejemplo partimos de la tabla siguiente:

clip_image002

La definición de este tipo de estructura es relativamente sencilla, similar a la creación de una tabla, el tipo anterior se definiría con la siguiente instrucción transact-sql

CREATE TYPE [dbo].[UsersTable] AS TABLE
(
[UserID] [int] NOT NULL,
[Postal] [char] NULL
PRIMARY KEY([UserID])
)
GO


Este nuevo tipo de estructura nos aporta varias ventajas, podemos definir la tabla con varios campos  y limitar el contenido del campo [UserID] utilizando primary key para que no se repitan los valores.

Una vez definida la estructura podemos utilizarla como un parámetro más.

La definición del SP que utiliza la nueva estructura es la siguiente:

CREATE PROCEDURE [dbo].[GetUsers] @users dbo.UsersTable READONLY
AS
SELECT * FROM Users WHERE UserID IN (SELECT userId from @users)

GO
 
El programa para llamar al SP desde c# podria ser similar al  ejemplo siguiente:
using System;
using System.Data;
using System.Data.SqlClient;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            using (SqlConnection sqlConnection = new SqlConnection("Server=(local);Integrated Security=SSPI;Initial Catalog=Database"))
            {
                using (SqlCommand sc = new SqlCommand("dbo.GetUsers", sqlConnection))
                {
                    using (IDataReader idr = GetParams())
                    {
                        sc.Parameters.Add("@users", SqlDbType.Structured).Value = idr;
 
                        sqlConnection.Open();
                        if (sqlConnection.State == ConnectionState.Open)
                        {
                            sc.CommandType = CommandType.StoredProcedure;
                            using (SqlDataReader sqlDataReader = sc.ExecuteReader())
                            {
                                if (sqlDataReader != null && sqlDataReader.FieldCount > 0)
                                {
                                    while (sqlDataReader.Read())
                                    {
                                        Console.WriteLine(String.Format("Código {0}, Nombre {1}", sqlDataReader[0], sqlDataReader[1]));
                                    }
                                    Console.ReadLine();
                                }
                            }
                        }
                    }
                }
            }
        }
 
        public static DataTableReader GetParams()
        {
            using (DataTable dt = new DataTable("Prueba"))
            {
                dt.Columns.Add("UserID", typeof(int));
 
                DataRow dr1 = dt.NewRow();
                dr1["UserId"] = 3;
                dt.Rows.Add(dr1);
 
                DataRow dr2 = dt.NewRow();
                dr2["UserId"] = 1;
                dt.Rows.Add(dr2);
 
                DataRow dr3 = dt.NewRow();
                dr3["UserId"] = 4;
                dt.Rows.Add(dr3);
 
                dt.AcceptChanges();
 
                return dt.CreateDataReader();
            }
        }
    }
}

Limitaciones de los User Defined Table Type:

- No se pueden pasar parámetros table-valued a user-defined functions

- Las estructuras solo pueden ser indexadas para soportar valores únicos o primary keys. Sql server no mantiene estadísticas sobre parámetros table-valued.

- Los parámetros table-valued son de solo lectura en el código transact-sql, no se pueden actualizar valores de filas y no se pueden insertar datos.

- No se puede alterar o modificar el diseño de una table-valued, para conseguir esto se debe borrar y volver a crear la estructura.

No debemos olvidar que en Entity FrameWork este problema se resuelve de una forma mucho más sencilla sin la utilización de SP, como usuarios de EF debemos huir del uso de procedimientos almacenados siempre que podamos, ya que debemos abstraernos de la base de datos y habitualmente la perdida de rendimiento es inapreciable, sin embargo pueden existir algunas ocasiones en que el uso del Store Procedure esté justificado, si bien, la mayoría de las veces podemos resolverlo de forma muy sencilla tal y como demuestran este par de ejemplos.

int[] customerIds = new int[] { 1, 2, 3 };

var customers = from customer in context.CustomerSet
where customerIds.Contains(customer.Id)
select customer;

---------------------------------------------------------------------

string[] cities = new string[] { "New York", "London", "Seattle" };

var query = context.Orders.Where(c => cities.Contains(c.Customer.Address.City)).Select(o => o);

 
Y recordar, alegaros de algunas practicas, si bien funcionan, son fruto de muchos errores en las aplicaciones de hoy en dia, como muestra el siguente código:
 
SqlCommand("SELECT UserID, Name, Phone FROM Users WHERE UserID IN (2,4,5,24)", sqlConnection);
por Juan Irigoyen | 1 comment(s)
Archivado en:
Constrúyete tu propio gestor documental
25/3/2010 9:09

Uno de los programas más utilizados en nuestro sistema de gestión es el gestor documental, como todos sabéis Sharepoint se conforma entre otras cosas como un gestor de contenidos, que permite almacenar todo tipo de documentos, pero hay veces que buscamos una mayor integración en nuestros sistemas o que simplemente no queremos depender de Sharepoint. En estos casos, desarrollar un gestor documental puede ser una buena alternativa y el trabajo para construir este programa lejos de parecer complicado es relativamente sencillo.

El gestor que os propongo se basa en el mismo sistema que utiliza sharepoint, los ficheros se serializan, se encriptan si es necesario y finalmente se guardan en una tabla de una base de datos tal y como hace sharepoint, posteriormente se leen desde la base de datos y se guardan en una ruta local o se utilizan directamente, aprovechándonos del almacenamiento en la base de datos con todas las ventajas que esto conlleva, copias de seguridad, particionado de tablas, indexación de contenidos, etc.

El gestor que vamos a desarrollar debe tener capacidad para almacenar cualquier tipo de fichero, documento Word, hojas de cálculo, archivos pdf, archivos comprimidos, emails, jpgs, archivos de autocad, etc.

Para comenzar hemos creado una tabla llamada Documentación en una base de datos independiente, porque como supondréis esta puede llegar a ser muy grande y en un momento determinado quizás tengamos que alojarla o particionarla en otro servidor por escalabilidad,  tamaño o rendimiento.

clip_image002

El campo [documento] (varbinary(max)) será el encargado de almacenar los ficheros serializados.

Buscamos un método sencillo para poder subir los archivos a la base de datos, con lo que queremos arrastrar uno o varios ficheros a un contenedor para que la aplicación pueda traspasarlos posteriormente a la BD.

Para llevar a cabo esta operación, hemos creado un formulario con el control System.Windows.Forms.WebBrowser que hace referencia a una ruta temporal en el disco, en este caso hemos mapeado una unidad temporal en nuestro PC ‘c:\temporal’, aunque esta podria ser tambien una ruta compartida de red. La configuración de esta carpeta se realiza a través de la propiedad “Path” del control WebBrowser. Este control ya tiene por defecto implementados el sistema Drag & Drop, que nos permite arrastrar, copiar o pegar cualquier tipo de archivo de sistemas Windows, así podemos arrastrar varios correos desde Outlook, una hoja de cálculo de Excel o cualquier fichero simplemente utilizando el ratón, al realizar esta operación sobre los archivos seleccionados estos se mueven o se copian a la ruta temporal que hemos establecido, podemos además utilizar los atajos para copiar archivos Ctrl-c / Ctrl-v, etc.

El control se puede configurar para que muestre diferentes vistas, hemos configurado una que muestra el nombre de los archivos, su tipo, la fecha, el tamaño, esta vista se puede alterar cambiando las propiedades de la carpeta temporal.

Esta primera parte que parecía complicada queda resuelta facilmente sin apenas tener que escribir un par de lineas de código, correspondientes a la configuración del control Webbrowser.

clip_image004

Una vez hemos arrastrado los archivos y estos se copian automáticamente a la ruta temporal pasamos al proceso de verificación, en esta opción se nos permite asociar cada uno de los archivos a varios metadatos, de esta forma podemos añadir información adicional a cada elemento como una descripción más detallada, observaciones, usuario, fecha o cualquier información que nos parezca relevante.

clip_image006

Finalmente los ficheros se procesan uno a uno y se van traspasando a la base de datos, para realizar esta operación podéis utilizar Directory.GetFiles(path) que permite obtener los nombres de los archivos de una ubicación determinada y FileInfo(file) que permite obtener información detallada sobre cada uno de los ficheros, fecha de creación, tamaño, etc. No debemos olvidar guardar el nombre completo con la extensión para identificar su tipo cuando vayamos a utilizarlo. 

Con todos estos datos formados por los nombres de los ficheros, sus atributos y los metadatos que podemos variar conformamos una colección temporal, lógicamente estos se grabaran posteriormente en la base de datos con lo que tendrán que tener un campo asociado en la tabla que creamos inicialmente.

Para realizar las operaciones de serialización de un fichero utilizamos la siguiente función:

//Cargar en un array de bytes el documento.
using (FileStream archivoStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
    byte[] documento = new byte[(int) archivoStream.Length];
    archivoStream.Read(documento, 0, (int) archivoStream.Length);
}

Despues de realizar este paso, si deseamos encriptar el documento para mayor seguridad podriamos hacerlo en este punto, utilizando las librerias de .net o aprovechando Sql Server para realizar esta operación.

Posteriormente grabamos el archivo y todos los datos adjuntos al documento (Metadata) utilizando un Procedimiento almacenado.

cmdOrden.Parameters.Add("@documento", SqlDbType.VarBinary).Value = documento.Archivo;
cmdOrden.Parameters.Add("@descripcion_modulo", SqlDbType.NVarChar, 100).Value = documento.Descripcion_modulo;
cmdOrden.Parameters.Add("@descripcion", SqlDbType.NVarChar, 200).Value = documento.Descripcion;
cmdOrden.Parameters.Add("@ruta", SqlDbType.NVarChar, 200).Value = documento.Ruta;
cmdOrden.Parameters.Add("@archivo", SqlDbType.NVarChar, 200).Value = documento.Archivo;
cmdOrden.Parameters.Add("@modulo", SqlDbType.NVarChar, 50).Value = documento.Modulo;
cmdOrden.Parameters.Add("@codigoAuxiliar", SqlDbType.Int, 10).Value = documento.Codigo_auxiliar;
cmdOrden.Parameters.Add("@codigoAsociado", SqlDbType.Int, 10).Value = documento.Codigo_asociado;
cmdOrden.Parameters.Add("@usuario", SqlDbType.NChar, 5).Value = documento.Usuario;
cmdOrden.Parameters.Add("@tipo", SqlDbType.NVarChar, 100).Value = documento.Tipo;
cmdOrden.Parameters.Add("@observaciones", SqlDbType.NVarChar, 1000).Value = documento.Observaciones;
cmdOrden.Parameters.Add("@codigo", SqlDbType.Int, 10).Direction = ParameterDirection.Output;

De esta forma tan sencilla los documentos se traspasan a la base de datos.

Pensando que este proceso puede ser de varios ficheros y que además algunos pueden tener un tamaño considerable, hemos dotado al programa de un mecanismo asíncrono utilizando BackGroundWorked, de forma que si el proceso tarda un tiempo la aplicación nunca llegue a bloquearse y los usuarios puedan continuar realizando su trabajo mientras se trasladan los ficheros a la BD.

Una vez hemos procesado los ficheros, lo unicó que nos queda por hacer es explotarlos, para ello tenemos que realizar la operación inversa:

Creamos otro formulario, en nuestro caso hemos utilizado un control TreeView para poder visualizar los datos de forma jerarquica, habitualmente los documentos estan relacionados con un registro de una o varias tablas, en la foto de abajo se muestran varios registros relacionados con la ficha de un artículo. Si el usuario pulsa abrir, se lee el registro de la base de datos, se deserializa el contenido del campo [documento], se desencripta si fuera necesario y finalmente se guarda en una ruta temporal o se abre directamente en memoria. Para deserializar el documento utilizamos la siguiente función, donde [doc.Documento] hace referencia al campo de tipo byte[] de nuestra entidad y [fichero] a la ruta y nombre del archivo que se va a crear como por ejemplo ‘c:\temp\estadisticas.xls’.

using (FileStream archivoStream = new FileStream(fichero, FileMode.Create))
{
    archivoStream.Write(doc.Documento, 0, doc.Documento.Length);
    archivoStream.Close();
}

Finalmente abrimos el fichero, para realizar esta operación y que el programa relacionado (word, excel, outlook), realice esta operación automáticamente utilizamos la siguiente función.

if (File.Exists(fichero))
{
    Process process = new Process { StartInfo = { FileName = fichero } };
    process.Start();
}

 

clip_image008

Y voila, ya tenemos nuestro gestor documental. En nuestro caso para complementar la utilidad vamos a llamar a un webservice que nos permite almacenar el fichero también en sharepoint de manera que este accesible en los dos gestores, podemos además implementar filtros para realizar búsquedas no solo por los metadatos si no por el contenido de los ficheros, implementar un control de versiones, etc, etc., pero si continuamos al final lo que tendríamos es otro “Sharepoint”.

La ventaja de esta utilidad además de la integración con nuestro sistema y la facilidad de uso es que podemos asociar el contenido a nuestros registros de la base de datos y posteriormente visualizarlos o agruparlos en otro registro para facilitar el acceso a la información.

image

En nuestro caso cada registro de cada mantenimiento tiene accesible el gestor documental de manera que en el ejemplo de la foto posterior cada registro de artículos tiene asociados varios documentos, otra ventaja es que en ciertos mantenimientos podemos visualizar la información de forma jerárquica, por ejemplo en un cliente se verían de esta forma, con lo que acceder a la información es muy sencillo.

clip_image010

Así que animaros, construiros un pequeños gestor documental como este es muy sencillo, y permitira dotar a vuestras aplicaciones de una herramiena muy potente para centralizar y acceder a todo tipo de información.

Macro sustitución en C#
22/1/2010 12:43

Una de las características de Visual Foxpro (mi anterior lenguaje antes de .net) y del que todos los días me acuerdo cuando me peleo con .net, era la utilización de macro sustitución, esta permitía realizar cosas como la siguiente:

   1: FOR i = 1 TO 12
   2:    xcam = 'Formas_pago.poraplaza' + ALLTRIM(STR(i))
   3:    IF &xcam > 0
   4:    ENDIF
   5: ENDFOR

De esta forma utilizando el símbolo &, podía evaluar el contenido de los campos sin tener que escribirlos uno a uno y ahorrando líneas de código.

Por desgracia c# no posee esta característica con un uso tan sencillo, se pueden realizar aproximaciones compilando el código al vuelo con codedoom o similares, pero personalmente evitaria utilizar estas técnicas si no es absolutamente necesario.

Ya metidos en harina, estaba en .net transcribiendo un bloque de código desde Fox y claro el pequeño programa de arriba daba lugar a un programa similar a este:

   1: /// Carga la configuración dependiente de la forma de pago correspondiente
   2: if (!string.IsNullOrEmpty(cvc.Forma_pago))
   3: {
   4:     using (ManagerBI<Formas_pago> manager = new ManagerBI<Formas_pago>() )
   5:     {
   6:         if (manager.GetRecord(cvc.Forma_pago))
   7:         {
   8:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_1);
   9:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_2);
  10:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_3);
  11:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_4);
  12:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_5);
  13:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_6);
  14:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_7);
  15:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_8);
  16:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_9);
  17:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_10);
  18:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_11);
  19:             cvc.PorcentajesAplazamientoAdd(manager.Data.Porcentaje_aplazamiento_12);
  20:  
  21:             cvc.DiasPagoAdd(manager.Data.Dia_pago_1);
  22:             cvc.DiasPagoAdd(manager.Data.Dia_pago_2);
  23:             cvc.DiasPagoAdd(manager.Data.Dia_pago_3);
  24:             cvc.DiasPagoAdd(manager.Data.Dia_pago_4);
  25:             cvc.DiasPagoAdd(manager.Data.Dia_pago_5);
  26:             cvc.DiasPagoAdd(manager.Data.Dia_pago_6);
  27:             cvc.DiasPagoAdd(manager.Data.Dia_pago_7);
  28:             cvc.DiasPagoAdd(manager.Data.Dia_pago_8);
  29:             cvc.DiasPagoAdd(manager.Data.Dia_pago_9);
  30:             cvc.DiasPagoAdd(manager.Data.Dia_pago_10);
  31:             cvc.DiasPagoAdd(manager.Data.Dia_pago_11);
  32:             cvc.DiasPagoAdd(manager.Data.Dia_pago_12);
  33:  
  34:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_1);
  35:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_2);
  36:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_3);
  37:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_4);
  38:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_5);
  39:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_6);
  40:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_7);
  41:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_8);
  42:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_9);
  43:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_10);
  44:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_11);
  45:             cvc.DiasAplazamientoAdd(manager.Data.Dias_aplazamiento_12);
  46:         }
  47:     }
  48: }

Qué horror, 36 líneas para hacer lo mismo, pero imaginar que en lugar de 36 campos tuviéramos 100. Se me ocurrió la idea de usar reflection para poder evitar la escritura de tantas  líneas y resulto relativamente fácil, la solución es interesante y en casos similares os permitirá reducir en gran medida vuestro código. El rendimiento de reflexión apenas penalizará la aplicación.

   1: /// Carga la configuración dependiente de la forma de pago correspondiente
   2: if (!string.IsNullOrEmpty(cvc.Forma_pago))
   3: {
   4:     using (ManagerBI<Formas_pago> manager = new ManagerBI<Formas_pago>() )
   5:     {
   6:         if (manager.GetRecord(cvc.Forma_pago))
   7:         {
   8:             Type t = manager.Data.GetType();
   9:  
  10:             for (int i = 1; i < 12; i++)
  11:             {
  12:                 string contador = i.ToString().Trim();
  13:                 decimal porcentajeAplazamiento = (decimal)t.InvokeMember("Porcentaje_aplazamiento_" + contador, BindingFlags.GetProperty, null, manager.Data, null, CultureInfo.CurrentCulture);
  14:                 cvc.PorcentajesAplazamientoAdd(porcentajeAplazamiento);
  15:                 byte diaPago = (byte)t.InvokeMember("Dia_pago_" + contador, BindingFlags.GetProperty, null, manager.Data, null, CultureInfo.CurrentCulture);
  16:                 cvc.DiasPagoAdd(diaPago);
  17:                 Int16 diasAplazamiento = (Int16)t.InvokeMember("Dias_aplazamiento_" + contador, BindingFlags.GetProperty, null, manager.Data, null, CultureInfo.CurrentCulture);
  18:                 cvc.DiasAplazamientoAdd(diasAplazamiento);
  19:             }
  20:         }
  21:     }
  22: }
Espero que os sirva.
 

por Juan Irigoyen | 2 comment(s)
Archivado en:
Database Professionals 2010. Pruebas Unitarias de Bases de datos y materiales de la charla.
25/10/2009 20:30

El otro día tuve el placer de compartir una charla sobre Visual Studio 2010 organizada por Juan Carlos Gonzalez del CIIN con Rodrigo Corral e Ibon Landa. Os dejo los materiales de la charla y un pequeño artículo sobre las diferentes pruebas de calidad en Base de datos comentado durante la presentación. Realice tres ejemplos, basados en un procedimiento almacenado que actualizaba un registro en la tabla Employee de AdventureWorks2008. Su definición es la siguiente:

 
CREATE PROCEDURE [HumanResources].[uspUpdateEmployeePersonalInfo]
    @BusinessEntityID [int], 
    @NationalIDNumber [nvarchar](15), 
    @BirthDate [datetime], 
    @MaritalStatus [nchar](1), 
    @Gender [nchar](1)
WITH EXECUTE AS CALLER
AS
BEGIN
    SET NOCOUNT ON;
 
    BEGIN TRY
        UPDATE [HumanResources].[Employee] 
        SET [NationalIDNumber] = @NationalIDNumber 
            ,[BirthDate] = @BirthDate 
            ,[MaritalStatus] = @MaritalStatus 
            ,[Gender] = @Gender 
        WHERE [BusinessEntityID] = @BusinessEntityID;
    END TRY
    BEGIN CATCH
        EXECUTE [dbo].[uspLogError];
    END CATCH;
END;

El ejemplo básico consistía simplemente en llamar al SP con unos datos ficticios que no realizaba ninguna actualización, esta prueba solo cubría que la llamada al SP se realizase de forma correcta.

El segundo ejemplo consistía en insertar un determinado registro antes de la prueba, llamar al SP para que realizase la actualización sobre ese registro y finalmente eliminar el registro de prueba insertado, esta prueba cubría que la llamada al SP se realizase de forma correcta y además permitía conocer si el sp funcionaba correctamente actualizando un registro de la BD.

El tercero y más interesante consistía en blindar el SP frente a cualquier cambio, uno de los problemas más habituales que sufrimos es que los SP, se suelen modificar a menudo y muchos de los fallos no detectados vienen derivados al cambiar las longitudes de los campos, el orden, tipo de dato y otros aspectos del procedimiento.

Para testar el SP, realice la consulta siguiente para averiguar la configuración completa procedimiento:

SELECT DISTINCT dbo.sysobjects.name, dbo.sysobjects.xtype AS type, dbo.syscolumns.name AS param, dbo.syscolumns.colorder AS corder, 
dbo.syscolumns.length, dbo.syscolumns.colstat AS keyc, dbo.syscolumns.isoutparam AS colisout, dbo.systypes.xtype, dbo.syscolumns.prec as precision, 
dbo.syscolumns.scale, dbo.syscolumns.isnullable, dbo.syscolumns.iscomputed, dbo.syscolumns.number 
FROM dbo.syscolumns 
INNER JOIN dbo.sysobjects ON dbo.syscolumns.id = dbo.sysobjects.id 
INNER JOIN dbo.systypes ON dbo.syscolumns.xtype = dbo.systypes.xtype 
WHERE (dbo.sysobjects.name = 'uspUpdateEmployeePersonalInfo') AND (dbo.systypes.status <> 1) 

image

Con los datos obtenidos podemos desarrollar una consulta que utilize los valores mostrados para comprobar que el procedimiento almacenado tiene la configuración mostrada por la consulta.

SELECT COUNT(DISTINCT dbo.syscolumns.name) 
FROM dbo.syscolumns 
INNER JOIN dbo.sysobjects ON dbo.syscolumns.id = dbo.sysobjects.id 
INNER JOIN dbo.systypes ON dbo.syscolumns.xtype = dbo.systypes.xtype 
WHERE (dbo.sysobjects.name = 'uspUpdateEmployeePersonalInfo') AND (dbo.systypes.status <> 1) 
AND ((dbo.syscolumns.name = '@BirthDate' AND dbo.syscolumns.colorder = 3 AND dbo.systypes.xtype = 61 AND dbo.syscolumns.length = 8 and dbo.syscolumns.prec = 23 and dbo.syscolumns.scale = 3)
OR (dbo.syscolumns.name = '@BusinessEntityID' AND dbo.syscolumns.colorder = 1 AND dbo.systypes.xtype = 56 AND dbo.syscolumns.length = 4 and dbo.syscolumns.prec = 10 and dbo.syscolumns.scale = 0)
OR (dbo.syscolumns.name = '@Gender' AND dbo.syscolumns.colorder = 5 AND dbo.systypes.xtype = 239 AND dbo.syscolumns.length = 2)
OR (dbo.syscolumns.name = '@MaritalStatus' AND dbo.syscolumns.colorder = 4 AND dbo.systypes.xtype = 239 AND dbo.syscolumns.length = 2)
OR (dbo.syscolumns.name = '@NationalIDNumber' AND dbo.syscolumns.colorder = 2 AND dbo.systypes.xtype = 231 AND dbo.syscolumns.length = 30))

La consulta devuelve (5), el numero de campos del procedimiento uspUpdateEmployeePersonalInfo que cumplen las condiciones especificadas. Si el valor retornado por la consulta no es 5, supondra que hemos alterado algun aspecto de configuración del procedimiento almacenado, longitud, tipo de valor, orden del campo en el store procedure, etc.

La prueba completa quedaría de esta forma:

PreTest

/* Desabilita el trigger que impide el borrado de registro en la tabla .[HumanResources].[Employee] */
DISABLE Trigger [HumanResources].[dEmployee] ON [HumanResources].[Employee] 
 
/* Borra el registro de pruebas si por alguna razon estuviera ya insertado */
DELETE [AdventureWorks2008].[HumanResources].[Employee]
WHERE [BusinessEntityID] = 2292
 
/* Realiza la inserción del registro de pruebas, hay que analizar los datos de la insercción ya que hay campos que tienen restricciones a nivel de tabla
como MartitalStatus que slo acepta M (Male)  F (Female) */
 
INSERT INTO [AdventureWorks2008].[HumanResources].[Employee]
           ([BusinessEntityID]
           ,[NationalIDNumber]
           ,[LoginID]
           ,[OrganizationNode]
           ,[JobTitle]
           ,[BirthDate]
           ,[MaritalStatus]
           ,[Gender]
           ,[HireDate]
           ,[SalariedFlag]
           ,[VacationHours]
           ,[SickLeaveHours]
           ,[CurrentFlag]
           ,[rowguid]
           ,[ModifiedDate])
     VALUES (2292,'1231231398','adventure-works\lyxnr',0x95EF,'Sales Representative',cast('1965-10-31' as date),'M','F',cast('1996-10-31' as date),1,34,37,1,newid(),getdate())
 
/* Comprueba que el registro de pruebas ha sido insertado correctamente */
SELECT [BusinessEntityID] FROM [AdventureWorks2008].[HumanResources].[Employee] WHERE [BusinessEntityID] = 2292 

Test

DECLARE @return_value int
 
EXEC    @return_value = [HumanResources].[uspUpdateEmployeePersonalInfo]
        @BusinessEntityID = 2292,
        @NationalIDNumber = N'13412343ZN',
        @BirthDate = N'01/01/1934',
        @MaritalStatus = N'S',
        @Gender = N'F'
 
SELECT @return_value, COUNT(DISTINCT dbo.syscolumns.name) 
FROM dbo.syscolumns 
INNER JOIN dbo.sysobjects ON dbo.syscolumns.id = dbo.sysobjects.id 
INNER JOIN dbo.systypes ON dbo.syscolumns.xtype = dbo.systypes.xtype 
WHERE (dbo.sysobjects.name = 'uspUpdateEmployeePersonalInfo') AND (dbo.systypes.status <> 1) 
AND ((dbo.syscolumns.name = '@BirthDate' AND dbo.syscolumns.colorder = 3 AND dbo.systypes.xtype = 61 AND dbo.syscolumns.length = 8 and dbo.syscolumns.prec = 23 and dbo.syscolumns.scale = 3)
OR (dbo.syscolumns.name = '@BusinessEntityID' AND dbo.syscolumns.colorder = 1 AND dbo.systypes.xtype = 56 AND dbo.syscolumns.length = 4 and dbo.syscolumns.prec = 10 and dbo.syscolumns.scale = 0)
OR (dbo.syscolumns.name = '@Gender' AND dbo.syscolumns.colorder = 5 AND dbo.systypes.xtype = 239 AND dbo.syscolumns.length = 2)
OR (dbo.syscolumns.name = '@MaritalStatus' AND dbo.syscolumns.colorder = 4 AND dbo.systypes.xtype = 239 AND dbo.syscolumns.length = 2)
OR (dbo.syscolumns.name = '@NationalIDNumber' AND dbo.syscolumns.colorder = 2 AND dbo.systypes.xtype = 231 AND dbo.syscolumns.length = 30))

De esta forma la condición de prueba del segundo valor de la consulta sera 5 (Numero campos que cumplen las condiciones especificadas), si en cualquier momento el valor no es 5, supondra que hemos alterado algun valor de configuración del procedimiento almacenado, longitud, tipo de valor, orden del campo en el store procedure, etc.

PostTest

/* Elimina el registro de pruebas insertado */
DELETE [AdventureWorks2008].[HumanResources].[Employee]
WHERE [BusinessEntityID] = 2292
 
/* Habilita el trigger, hay que realizarlo sobre la clausula EXEC porque la prueba no acepta 'GO', despues del borrado */
EXEC('ENABLE TRIGGER [HumanResources].[dEmployee] ON [HumanResources].[Employee]')

Comprobamos que al alterar la longitud de un campo la prueba fallaba, mientras que las dos primeras pasaban sin problemas. Se garantiza el correcto funcionamiento del SP, ya que inserta un registro de pruebas, testea el SP eliminando el registro de pruebas al finalizar y además blinda este sobre cualquier cambio en la configuración del SP.

Quiero agradecer a los asistentes su presencia, a Juan Carlos Gonzalez por la organización y porque gracias a el tenemos un evento cada poco tiempo en Santander y como no, a mis compañeros Rodrigo Corral e Ibon Landa también conocidos como Grupo Pimpinela, (haber si adivináis ¿quién es quién?…), que animaron la presentación con sus charlas y desparpajo, debido a la emoción los primeros minutos sufrí un pequeño colapso, me gusto especialmente la última parte, pude recuperar el video que hizo uno de los presentes, solo recordalo me emociono… :)

Adjunto la PPT de la charla:

Presentación en formato Powerpoint 2003.

Presentación en formato Powerpoint 2007.

Presentación en Adobe Acrobat PDF.

Como fracasar con éxito
27/9/2009 22:21

Recuerdo que llevábamos varios meses encerrados en una de las habitaciones donde vivía con un par de amigos, con la intención de desarrollar software de gestión, apoyados por una pequeña empresa que quería comercializar el producto, ninguno de nosotros cobraba sueldo alguno y manteníamos un estricto horario, similar al de cualquier otra empresa, teníamos el sueño de que algún día podríamos ganar lo suficiente como para establecer una empresa que nos permitiera vivir cómodamente, el trabajo se hacía cada día más duro, pues, además de no contar con ningún incentivo, a final de cada mes, debía asumir algunos gastos derivados de nuestro trabajo, teléfono, gasolina, luz, etc.. La empresa interesada en el producto, nos surtía de material y un poco de equipamiento, algún router para la red, material ofimático y otras cosas. Al cabo de casi un año de trabajo, uno de los compañeros se fue a realizar el servicio militar y nos quedamos solo dos, encontramos la posibilidad de alquilar un local, para nosotros era prácticamente impensable, ya que no disponíamos de ningún ingreso, pero el alquiler era muy bajo y buscábamos la independencia de un lugar para trabajar más concentrados, el local era simplemente una habitación sin ventanas de unos 12 metros cuadrados ubicado en la parte baja de un edificio, decidimos arriesgarnos y sacar la licencia fiscal para poder vender software y equipamiento informático, pensamos que con que lográsemos vender dos o tres equipos al mes y algún programa, podríamos pagar el alquiler y tendríamos lo suficiente como para poder continuar con lo que verdaderamente nos gustaba, desarrollar software, fue curioso como, primero a través de un amigo nos compraron un equipo, luego otro y otro. En poco tiempo las ventas fueron incrementándose, aunque seguíamos sin un nivel de beneficios aceptable, ni siquiera sacábamos lo suficiente para asumir un sueldo. Aun con estos problemas y debido a la ilusión que teníamos por nuestra empresa, decidimos arriesgarnos y alquilar un local más grande de cara al público, solicitamos un préstamo avalados por nuestros padres y comenzamos nuestra primera aventura empresarial.

Lógicamente los gastos se dispararon, tuvimos que contratar a alguien que estuviera permanentemente en la oficina y asumir diversos impuestos y costes derivados de la actividad, acondicionamiento del local, luz, teléfono, etc., así que empezamos a salir a la calle en busca de empresas que nos permitiesen aumentar nuestros ingresos, el camino fue muy duro, establecer una simple entrevista era muy complicado ya que normalmente preferían empresas conocidas o consultoras con mayor experiencia, la mayor parte de los empresarios no veían valor añadido al desarrollo de software, preferían un paquete estándar en el que el coste del software fuese menory habitualmente descartaban cualquier tipo de desarrollo que pudiera aportarles mayor valor. Por el medio, intentamos un poco de todo, desde dar cursos de formación a empresas o cualquier colectivo, hasta llegar a acuerdos comerciales con otras entidades del sector y colaborar en el desarrollo de sus aplicaciones.

Los clientes entraban en la tienda con el fin de informarse sobre los costes de un ordenador personal y demandaban al mismo tiempo que les instalásemos todo el software necesario, (sistema operativo, paquete de ofimática, antivirus, etc.), por supuesto totalmente 'gratis', yo me indignaba con esto, pues la mayor parte rehusaban a realizar la compra en nuestra empresa debido a que otras, les ofrecían estos servicios de “valor añadido”.

Recuerdo que yo entonces era un “soñador”, soñaba con tener una empresa, con trabajar duramente y en pocos años, aspiraba a vivir cómodamente, cuando me hablaban de dinero yo les respondía que para mí no era importante, que el dinero era lo de menos, el dinero ya vendría después del trabajo, nunca me preocupo especialmente. Después de un tiempo, me di cuenta de que la empresa había tomado un camino muy distinto del que tenia planeado, nos habíamos convertido en una empresa de informática habitual y habíamos dejado de lado el desarrollo de software, lo único que podría diferenciarnos y aportarnos valor. Finalmente después de un tiempo y muchos problemas, abandone la empresa.

Este fracaso, me permitió más adelante, reflexionar sobre los errores que cometí.

Cuando conformamos la empresa no teníamos una idea clara del negocio, teníamos una idea general, pero no contábamos con un proyecto claro, ni siquiera con un pequeño estudio de mercado, nos lanzamos con un desconocimiento total, carecíamos de un plan estratégico, no teníamos un sector determinado al que atacar, ni una idea clara que seguir, tan solo, hacer lo que fuera para subsistir y luego, dependiendo de la situación que alcanzásemos, tomaríamos posteriores decisiones.

En principio, la idea era desarrollar software de gestión y más adelante, aprovecharlo para realizar algún vertical. Desarrollamos un programa similar a otros que ya existian en el mercado y que, aunque no era tan completo como el nuestro, cumplía con los objetivos básicos y logicamente al ser mas sencillo también era mucho más barato.

Destinamos la mayor parte de los recursos a desarrollar el software y posteriormente intentamos comercializarlo. Este fue uno de los mayores errores que cometimos, realizamos un producto, sin analizar el mercado ni a la competencia, sin recursos económicos, sin un sponsor, asumiendo que, como nuestro software sería mucho más completo que los demás, se vendería sin problemas. Es decir, primero producimos el producto y posteriormente intentamos comercializarlo. Al cabo de unos años y debido a este fracaso, deducí que lo mas adecuado seria invertir el orden, “vender y luego producir”, curiosamente el sistema LEAN se basa en una idea similar, fabricar en base a la demanda, es decir ‘vender antes de producir’.

No teníamos un plan comercial viable. Contar con un estudio de mercado, para atacar a sectores en los que la competencia no estuviera presente, hubiera sido mucho más inteligente que intentar competir con un producto que ya existía en el mercado contra empresas solventes, mucho mejor posicionadas que nosotros, en un mercado que dominaban desde hacía algunos años. Estoy convencido de que si hubiéramos dedicado un poco de tiempo a estudiar y analizar en detalle el mercado, podríamos haber llegado a tener una idea clara de negocio, posteriormente lo pude ver claro con empresas que triunfaron, porque orientaron sus desarrollos a hacer programas de gestión a Concesionarios, Hoteles, Abogados, Dentistas y otros sectores que no disponían de ninguna solución de software.

El desconocimiento del mercado hizo, que cuando terminamos el desarrollo, nos encontramos con que la mayor parte de nuestros posibles clientes, se había decantado por otros productos más sencillos y baratos. La competencia opto por hacer todo lo contrario, desarrollo un producto sencillo que no requiriese mucho tiempo y lo puso en el mercado un precio mucho menor, de esa manera, comenzaba a retornar parte de la inversión y poco a poco iban aumentando la funcionalidad, además, sus clientes se convertirían en usuarios potenciales de sus versiones más avanzadas que habitualmente tenían precios mucho más elevados. Esto les aporto feedback para mejorar sus versiones, ‘me acuerdo de Scrum con las entregas continuas de software…’, la penetración era mucho más rápida, porque al cliente no le importaba desembolsar un poco de dinero por el software y posteriormente si sus requerimientos aumentaban podrían ampliar a versiones más avanzadas, todo esto, hizo que en poco tiempo nuestro producto fuese menos competitivo. La estrategía comercial de nuestros competidores fue mucho mas acertada.

Los programas que realizaba la competencia, cubrían tan solo aspectos básicos que la gente necesitaba, la mayor parte de los clientes empezaba a trabajar con computadoras personales con lo que un programa muy complejo hubiera fracasado. Nos ocurría a menudo que cuando alguien veía nuestro programa comentaba: ‘es excelente, pero tiene demasiadas opciones…’, a mi no me hacen falta tantas, nunca modificare un informe, no sé si podre manejarlo. Resulto que nuestro mercado, no estaba preparado para un producto tan complejo. Nos olvidamos de estudiar los requerimientos de los clientes, en lugar de esto, intentamos hacer un programa que cubriese todas las necesidades existentes, esto hizo que nuestro producto fuese mucho más complejo de entender y manejar.

Nos olvidamos de evaluar el tiempo de desarrollo, el tiempo es un factor determinante, el desarrollo duro más de dos años, en este periodo, la competencia se hizo con un mercado potencial de clientes muy grande y que mas adelante fue imposible de recuperarar, la mayoria ya se había habituado a su uso, y nuestros competidores iban incrementando la funcionalidad en base a la demanda de los clientes.

Como necesitábamos dinero para mantener la empresa y no logramos que el software desarrollado se vendiese como queríamos, intentamos buscar una empresa que estuviera interesada en comercializar el producto, viajamos a Madrid y se lo ofrecimos a varias, la mayoría rehusaba, pues ya contaban con algún producto que si ser tan completo, conocían perfectamente y les resultaba fácil adaptarlo a las necesidades de sus clientes, aunque hubo un par de ofertas serias de compra que pasaban por hacerse con todo el código fuente y controlarlo completamente. Las ofertas fueron de bastante dinero, pero no quisimos renunciar a su control, así que lo descartamos. Si hubiéramos vendido el producto, el dinero nos hubiera permitido continuar, desarrollando la empresa durante unos años cómodamente y podíamos haber dedicado otros recursos a realizar otros productos, pero no queríamos desprendernos de un programa que considerábamos como uno de los mejores del mercado y éramos demasiado ambiciosos, queríamos hacer mucho en muy poco tiempo.

A partir de aquí, para subsistir nos dedicamos a vender hardware, dar soporte y mantenimiento a empresas, formación, instalación de redes, etc., en fin todos aquellos servicios que dan las empresas de informática, pero en esto, no aportábamos ningún factor diferenciador importante.

Además de esto, nuestra inexperiencia hizo que en varias ocasiones, aceptásemos proyectos en los que posteriormente descubrimos que los clientes eran auténticos profesionales del engaño, aceptaban el presupuesto sin pestañear, pero a la hora de cobrar descubríamos que muchos nos engañaban, recuerdo que hubo un proyecto, en el que después de finalizarlo nos enteramos que el cliente estaba en la ruina y que debía dinero a mucha gente realizando prácticas similares, no creáis que fue solo un caso, sufrimos varios, alguno de ellos, de importantes sumas de dinero que nos complicaron mucho la vida. La importancia de realizar un estudio del cliente es fundamental, cobrar a la firma de un contrato un porcentaje del proyecto y asegurarnos de la solvencia del cliente son aspectos muy importantes que se deben realizar antes de aceptar cualquier proyecto, existen empresas como Crédito y Caución que aseguran el pago de un determinado porcentaje de la cantidad facturada a cambio de un porcentaje de la operación.

No logramos convencer a las empresas de que nuestros servicios ofrecían valor añadido, les ofrecíamos lo mismo que las demás, algo que los demás hacían igual que nosotros. Y, ¿Por qué una empresa va a confiar en alguien que no conoce y que además no ofrece nada nuevo ?.... Estaba claro, nuestro objetivo inicial había variado, ahora ya no desarrollábamos software, tan solo hacíamos lo que fuera para subsistir y nos olvidamos del verdadero objetivo de nuestra empresa.

No supimos analizar bien nuestros costes, cuando comenzamos la actividad nos dimos cuenta de todos los gastos que debíamos soportar, pago de autónomos, IAE, gastos de luz, agua, teléfono, nóminas, seguros sociales, mobiliario, acondicionamiento del local, declaración de IVA, seguro del local, asesoría contable, alarma, gastos por líneas de crédito y transacciones bancarias, recuerdo que pusimos un aparato para pagar con tarjeta, nos enteramos que VISA llega a cobrar un 4 % por cada transacción que realicen los clientes, recuerdo que algunos productos informáticos apenas tenían ese marguen comercial. Os aseguro que, por pequeño que sea el negocio, la lista de gastos es interminable, y claro, podéis esperar ‘sentados’ que los Ayuntamientos y otros Organismos Oficiales os ayuden, lo único que les interesa es ampliar sus ingresos. Así que debéis tener claro todos los gastos antes de comenzar vuestra actividad.

No contábamos con una estrategia comercial seria, no podíamos permitirnos un agente comercial especializado, vender software o servicios informáticos requiere profundos conocimientos técnicos y comerciales, encontrar un comercial en este sector es muy complicado, al carecer de medios, hizo que tuviésemos que dedicarnos a realizar esta labor, carecíamos de la suficiente experiencia, el desconocimiento del perfil de los empresarios de la zona, que no creían como yo, en el valor que podría aportarles el software a medida, hizo que la mayor parte de las empresas rehusasen a aceptar nuestros servicios y que posiblemente un comercial con experiencia podría haber triunfado donde yo fracase.

No contábamos con un sponsor que financiase nuestro proyecto y desde luego no teníamos medios económicos, con lo que solamente subsistir mes a mes ya era un logro para nosotros, pero siempre nos obligaba a estar en la cuerda floja, si un mes no realizábamos el objetivo de ventas, la empresa se tambaleaba y varias fueron las veces que estuvimos a punto de cerrar, dedicábamos todas nuestras energías a llegar a fin de mes.

No dedicábamos tiempo a innovar, a poner en la mesa ideas diferentes y realizar algo que nos distinguiese de nuestros competidores. Esto hizo que nos incorporásemos a un mercado en el que nuestros competidores tenían mucha ventaja, disponían de mayor experiencia y habitualmente contaban con una cartera de clientes. La mayoría no tenían que preocuparse por subsistir, con lo que podían contar con más recursos para competir en el mercado.

Debido al poco tiempo que teníamos, empezamos a dejar de formarnos, tan solo dedicábamos un poco de tiempo cuando podíamos, así que con el tiempo fuimos perdiendo valor en nuestro mercado, pero nuestro trabajo no daba para más, así que pasamos de ser desarrolladores a ‘empresarios de poca monta'.

Los problemas económicos, administrativos y comerciales fueron aumentando y hacían que dedicásemos prácticamente todos nuestros recursos a subsistir y apenas teníamos tiempo para pensar, no nos paramos a ver cómo mejorar, como hacer cosas que nos aportasen valor, nos movíamos por impulsos, a petición de la demanda de algunos clientes que tan solo nos permitían subsistir y con el único objetivo de llegar a fin de mes. Nos fue prácticamente contratar personal adicional, desde técnicos especializados hasta comerciales con conocimientos del entorno, esto hacia que tuviésemos que hacer de todo, desde barrer hasta encargarnos de realizar presupuestos de equipos informáticos, con lo que fuimos dejando en otro plano aquello que nos podría diferenciar de los demás.

No logramos convencer a otras empresas del sector de que la colaboración podía hacer que estableciendo ciertas reglas de compromiso, nuestros márgenes comerciales mejorasen y ofreciesen mayor valor añadido. La incapacidad para llegar a acuerdos con nuestros competidores hizo que tuviésemos que renunciar a la mayoría de la venta de software y esto elimino un mercado que podría habernos ayudado en nuestros objetivos.

La parte positiva, es que al final, este y otros fracasos, me ayudaron a lo largo de toda mi trayectoria profesional a entender mejor cómo se comportan los mercados, la importancia del cliente y la competencia, de la colaboración, del trabajo en equipo, de la innovación, que de otra forma, difícilmente hubiera podido aprender. He tenido el privilegio de poder “intentarlo”, algo que muchas personas ni siquiera se han atrevido o que su condición económica no se lo permitirá a lo largo de su vida, he aprendido mucho de las personas que nos rodean y que los errores, nos enseñan aspectos que de otra forma, serian muy difíciles de aprender, por eso pienso, que aquel que ha fracasado, tiene más valor que él no lo ha hecho nunca, los errores del pasado, nos enseñan cómo mejorar nuestro futuro y a no cometer los mismos errores, de ahí la importancia del conocimiento de la historia.

He aprendido que en la colaboración y en el valor de las personas está la clave de todo, en que pensar antes de hacer las cosas es mucho más importante que hacerlas y luego pensar…, aunque a veces haya que arriesgarse, que el trabajo en equipo, la formación continua, la innovación y por supuesto, ‘los fracasos’, son aspectos que conducen al éxito.

Este es un sector proclive al cambio y la innovación y tenemos un mercado inmenso esperando a ser explotado, así que animaros, no tengáis miedo al fracaso, pero cuidado, no os engañéis, nadie os va a regalar nada, el dinero es el primer objetivo de una empresa, que una empresa tenga éxito pasa solo por una cosa: ganar dinero. Si la empresa no gana dinero, no podrá alcanzar sus objetivos, para poder establecer una empresa debemos tener un plan establecido que asegure la viabilidad de esta, desde el principio, sobre todo al inicio, que es, cuando más falta nos va a hacer.

Mis fracasos me han enseñado mucho, si tuviera que poner en marcha una nueva empresa de desarrollo de software, desde luego haría cosas muy diferentes, algunas de ellas serian:

Buscar una idea y desarrollarla, intentar que esta sea innovadora o que aporte algo que marque la diferencia frente a vuestros competidores, establecer una línea de negocio clara realizando un plan estratégico con su análisis de costes y beneficios, estudiar las ventajas e inconvenientes del negocio, analizar cómo, después de un tiempo, podéis dotar a vuestra idea de mayor valor añadido, trazar un par de planes alternativos por si no funciona como teníais planeado, realizar un pequeño estudio de mercado estudiando a vuestros posibles clientes y el entorno en el que se encuentran, si es posible contar con alguno de ellos para comenzar, compartir los riesgos con un sponsor, estudiar a vuestra competencia antes de actuar y el mercado al que va destinado vuestro producto, compartir vuestra idea con alguna persona con experiencia en el sector para obtener otros puntos de vistas y evaluar los posibles riesgos que pueden aparecer y que de otro modo desconoceríais, hay que tener en cuenta que cuando alguien tiene ilusión por una idea solo ve la parte positiva, debemos contar con opiniones externas para contar con un punto de vista mas objetivo y me atrevería a decir 'mas real'. Así mismo, es muy importante rodearse de un equipo adecuado, contar con personas preparadas que sean innovadoras, proclives al cambio y que compartan la visión de la empresa. Es también muy importante que los miembros del equipo mantengan una buena relación y tengan un nivel de educación aceptable, pues el acercamiento siempre da lugar a roces. En el área del desarrollo, el tiempo es un factor determinante, apostar por desarrollos de larga duración es un riesgo muy alto, es mucho mejor resolver las necesidades básicas y posteriormente ir incrementando la funcionalidad y optimizando el producto, esto permitirá retornar la inversión más rápido y disminuir vuestros riesgos.

En resumen, ‘pensar antes de actuar’, ‘vender antes de producir’, ‘innovar’, ‘apostar por el valor del equipo y la colaboración', ‘reducir vuestros riesgos’, 'tener en cuenta que el tiempo, es un factor determinante'.

Espero que mis experiencias os ayuden a no cometer los mismos errores, si lo logro, habré fracasado con éxito.

por Juan Irigoyen | 19 comment(s)
Archivado en:
Cuestión de velocidad…
15/9/2009 16:48

Velocimetro

Creo que todos los desarrolladores, alguna vez hemos estado obsesionados con la velocidad, la velocidad es un tema importante, incide en prácticamente todas las facetas de la computación, realizar un programa veloz normalmente marcará el éxito o el fracaso de un desarrollo, Google es un claro ejemplo de esto. Si lo comparamos con la velocidad de un coche, la verdad es que no tiene mucho que ver, prácticamente todos los coches pueden viajar a 100-120 km/hora, lo suficiente para realizar cualquier viaje, por grande que sea.

En el ámbito de las conexiones de red comenzamos con velocidades de 50 bps que utilizaban los antiguos teletipos, en cambio ahora la mayoría de los canales de comunicaciones, desde una simple Ethernet con velocidades de  1000 Mbps full dúplex, hasta las Wifi que con la nueva norma n podrán llegar a los 300 Mbps. El avance es espectacular hemos pasado de 300 bps al descargarnos algún archivo de las primeras BBS a disponer de ADSL con velocidades de hasta 20 Mbs.

Me pregunto que pasara cuando la velocidad de internet, llegue a ofrecernos una velocidad suficiente para poder ejecutar cualquier tipo de servicio con fluidez, y como sucede hoy en día con las redes de fibra en la que ni los discos duros más veloces sean capaces de procesar. Existe hoy en dia algunos lugares, como Japón, donde se pueden conseguir velocidades de hasta 100 Mbps, lo suficiente como para hacer casi cualquier cosa, es cierto que para ello todas las infraestructuras de internet tendrán que readaptarse, pero a la velocidad que esto se mueve apenas notaremos el cambio.

Pese a que el incremento de la velocidad ha sido paulatina, las necesidades han ido aumentando quizás hasta más que la propia velocidad, pasamos de descárganos algún pequeño fichero de 15 Kb desde las antiguas BBS a varios Gygabytes de alguna aplicación, el video bajo demanda, las redes P2P, voz Ip y otros servicios han ido surgiendo a medida que la velocidad a permitido su funcionamiento. Los avances de velocidad en los procesadores, la utilización de múltiples núcleos, la incorporación de grandes procesadores en las tarjetas de video han permitido que en poco tiempo hayamos pasado de programas simples a modernas y complejas aplicaciones que nos permiten trabajar con objetos 3D, video, etc.

Sin embargo, después de tantos avances, algunos programas parecen cada vez más lentos, creo que todavía hoy en día el área del desarrollo en general no ha sido capaz de asumir la velocidad del hardware, el ejemplo más claro es que las aplicaciones de 64 bits todavía no han despegado. Actualmente se acaba de presentar la programación paralela destinada a aprovechar todos los núcleos de los procesadores que nos permitirá conseguir mejores ratios de rendimiento y aprovechar todas las ventajas de nuestro hardware, veremos cómo evoluciona y si le sacaremos el partido que merece.

Me pregunto, cuándo internet permita conseguir velocidades de 100 Mbps o más como en Japón, si la velocidad dejara de tener tanta relevancia como hoy en día, la mayoría de los programas en Internet, incluso ayudados de nuevas tecnologías como Ajax, Silverlight, Flex y otras, todavía no permiten una interacción muy fluida con los usuarios, si bien han mejorando mucho, pero en poco tiempo, creo que tal y como sucede con los coches esto dejara de tener tanta relevancia. Pienso que estará al alcance de todos obtener la mayoría de servicios de una forma fluida, desde tv bajo demanda con alta calidad, algo que hoy en día ya es una realidad con la mayoría de proveedores de Internet que ofrecen servicios de TV, manejar objetos 3D, acceder a recursos compartidos como si de una red Ethernet se tratase, utilizar servicios de voz IP sin interferencias y todo el conjunto de servicios que hoy en día utilizamos mejorados por las capacidades de la red.

En este supuesto, para el que creo, no queda mucho tiempo, pienso que las arquitecturas volverán de nuevo a reinventarse ya que la capacidad de comunicación, permitirá que cualquier programa tanto Web como de escritorio tenga una capacidad de comunicación prácticamente ilimitada similar a nuestras redes de trabajo locales.

Estoy convencido de que el Software as Services (SAAS) es el futuro, y la mayor parte de los programas que existen, pasaran tarde o temprano a alojarse en la red, este paso masivo de aplicaciones marcara un antes y un después en nuestra vida, ya que la mayoría de los servicios pasaran a administrarse por especialistas y el coste de su mantenimiento bajara progresivamente, esto permitirá que de algún modo nos podamos abstraer de las necesidades de hardware y software necesario (actualizaciones, copias de seguridad, gestión de errores e incidencias, mantenimiento, etc). Creo que estos servicios serán mucho más baratos que contar con una infraestructura propia y por ello serán utilizados de forma masiva.

Uno de mis sueños y creo que el de mucha gente es la de desarrollar un programa sin demasiado esfuerzo que sea multiplataforma y que funcione por cualquier canal de comunicación establecido. Espero que con el aumento de la velocidad y de la progresión del SAAS esto se convierta en una realidad muy pronto.

En España, como no podría ser de otra forma, seguimos por debajo de la media de los países Europeos en velocidad y precio del ADSL, increíble, nos gana hasta Portugal, espero que poco a poco nos vayamos poniendo al día, ya que la importancia de la velocidad en Internet va a ser un punto clave para que podamos evolucionar con todas estas tecnologías. Os dejo la tabla comparativa del 2008.

clip_image001

Pienso que el Grid Computing se vera tambien beneficiado por el aumento de velocidad, como sabeis el Grid Computing es una tecnología que permite acceder a una gran capacidad de proceso y otros recursos utilizando equipos distribuidos, tal y como realiza Google con sus búsquedas. Uno de los ejemplos más antiguos es el proyecto SETI para la búsqueda de vida extraterrestre que utiliza ordenadores personales de la gente que quiera participar en el proyecto, para procesar datos, creo que el aumento de velocidad hará que esta tecnología vaya asentándose cada vez más.

Parece que está de moda hablar de la Nube, y a mi juicio todo indica que Azure será el primer paso para asentar todas estas ideas que comenzaron hace algunos años cuando los Web Services empezaron a tomar mayor relevancia y que ahora debido sobre todo al aumento de la velocidad se pueden hacer realidad.

Todo indica que Internet continuara progresando de forma exponencial en los próximos años y su importancia será cada vez mayor, en pocos años, quizás, hasta cobre vida propia…, ya hay televisiones que permiten conectarse a internet, pienso que dentro de poco se conectaran desde los coches hasta las cafeteras y lavadoras, veremos lo que nos depara el futuro.

Aún con esto, sigo teniendo mis dudas:

¿Dejara de tener importancia la velocidad tal y como ha pasado con los coches o el aumento de los requisitos seguirá aumentando conjuntamente con la mejora de la velocidad como ha sucedido hasta ahora?

¿Se asentara definitivamente el Grid Computing y dejaran los grandes servidores de tener tanta importancia?

¿Dejaran de utilizarse masivamente los protocolos de comunicación soap y tecnologías como http y xml, para dejar paso a protocolos más avanzados en forma binaria?

¿Lograra el SASS comerle el terreno a las aplicaciones locales y se asentara definitivamente para convertirse en la plataforma más utilizada?

Espero vuestras opiniones...

Un saludo.

Innovar sí, pero como…
14/9/2009 1:55

A raíz del post de Rodrigo hablando sobre innovación, me he animado a escribir este artículo, la verdad es que el tema me apasiona, recuerdo una conferencia sobre trabajo e innovación hace un par de años, en el que el ponente , un Consejero de Telefónica y varias empresas importantes de España, hablaba sobre la necesidad de innovar, en concreto comento un caso de una Empresa Catalana galardonada con un premio Europeo a la entidad más innovadora, comentaba que la empresa disponía de un equipo de personas que se pasaban el día estudiando la viabilidad de nuevos productos, los desarrollaba y empezaba a comercializarlos, y cuando veían que el producto llegaba al máximo de ventas, es decir su curva de ventas comenzaba a descender automáticamente lo retiraba del mercado, recuerdo que a mí y creo que a muchos otros, se nos quedo cara de tontos, pensando cómo, cuando un producto alcanza su máximo de ventas lo abandonaban, la idea subyacente es sencilla, era en este momento cuando la competencia y otros factores externos empezaban a comerles terreno, y porque luchar contra algo imparable, siempre habría alguien que lograría realizar el producto más barato e incluso mejor, simplemente lo retiraban y pasaban a dedicar todos sus esfuerzos a desarrollar nuevos productos.

Recuerdo una reunión en una empresa, donde se habría un debate para ver cómo entre todos los componentes, la mayor parte responsables de cada uno de los Departamentos podían aportar ideas para intentar mejorar una situación delicada, la mayor parte de los componentes no decían nada, en cambio, algunos empezaron a lanzar ideas, mejorar el departamento comercial, intentar fabricar otros productos con los medios productivos que tenían, abrir nuevos mercados, eliminar los canales de distribución para llegar al cliente final y obtener mayores beneficios, realizar acuerdos con competidores o con empresas relacionadas con el sector, mejorar la calidad para poder acceder a mercados más exigentes, adquirir alguna empresa de la competencia, etc. La mayor parte de estas ideas eran rebatidas rápidamente por algunos miembros descartándolas rápidamente aduciendo que algunas se habían puesto en marcha y habían fracasado años atrás, que no veían su rentabilidad inmediata y que otras simplemente eran totalmente erróneas por el desconocimiento de las personas que las planteaban y que desconocían el mercado. Al final todas y cada una de las ideas se fueron descartando y se llego a la conclusión de que lo mejor sería ‘ahorrar costes’, si ahorran costes podrían continuar manteniendo un nivel de beneficios aceptable y aguantar el tirón en espera de tiempos mejores. Para ello deberían optimizar algunos procesos con los que trabajaban, reducir los gastos de algunos departamentos, paralizar ciertas inversiones, seguramente reducir parte de la plantilla, etc.

No digo que en la reunión no se llegaron a conclusiones que pudieran aportar mejoras a la empresa, pero lo cierto es que la palabra innovación se esfumo… y ¿por qué?, por el miedo a nuevas inversiones de dudosa rentabilidad, a apostar por algo sin la suficiente seguridad, en resumen por el miedo al fracaso.

Creo que este es un claro ejemplo de lo que ocurre con muchas empresas actualmente, se agarran a un clavo ardiendo con tal de no cambiar su negocio, la resistencia al cambio es el mayor enemigo de la innovación, aceptar que un negocio que ha funcionado durante muchos años, ya no es rentable y que hay que hacer cosas diferentes es algo muy difícil de asumir. Incurrir en proyectos que pueden fracasar de dudosa rentabilidad es algo que la mayoría suele reusar. Según mi opinión, creo que la mayor parte de las ideas que se presentaron seguramente podrían haber fracasado, pero estoy seguro de que si entre todas, solo una llegase a buen fin, seguramente la situación de la empresa hubiera cambiado considerablemente.

Para Innovar debemos arriesgarnos, debemos escuchar las ideas de los demás por absurdas que estás nos parezcan, debemos eliminar aquellas reglas que dicen, porque hacerlo de otra forma si de esta siempre nos ha funcionado bien o planteamientos como, ‘bueno, nosotros no vamos muy bien pero fíjate en los demás...’.

Para Innovar debemos dedicar parte de nuestro tiempo productivo a pensar cómo hacerlo mejor, como sacar valor añadido, como mejorar nuestro trabajo, si no nos paramos a pensar cómo mejorar, jamás lo haremos.

Desgraciadamente las empresas suelen tener un objetivo que les impide ver más allá, ‘la rentabilidad de los proyectos’, si de antemano no presentamos un proyecto rentable será muy difícil apostar por él, convencer de esto a los directivos de las empresas es algo muy difícil de conseguir. Lo primero que hacen es preguntarse: ya, pero y ¿si no sale bien?… ¿cuánto dinero nos va a costar?, estoy desacuerdo en que la rentabilidad es un factor muy importante, pero para innovar tampoco es necesario realizar grandes inversiones, hay muchas formas de minimizarlas realizando proyectos pilotos, maquetas, simulaciones, estudios de mercado, o mejor vender la idea, convencer a un sponsor y llévala a cabo, si, se que suena como un sueño de hadas pero muchos proyectos han conseguido ver la luz siguiendo este método, comparte el beneficio y disminuye tus riesgos, pero si todo esto no es posible, siempre llegara un punto en que habrá que arriesgarse. Si aún así, no somos capaces de llevar a cabo el proyecto solo nos quedara una cosa por hacer,”nada”, esta es la opción más utilizada, y como es gratis y no cuesta ningún esfuerzo, a esperar como el avestruz que entierra su cabeza en la tierra cuando viene un león…

Todo esto, me hace preguntarme una cosa. ¿Somos los desarrolladores innovadores?, en mi opinión y después de más de 20 años de profesión puedo afirmar que no. Creo que la mayoría de nosotros destinamos la mayor parte de nuestro tiempo a aprender a utilizar nuevas tecnologías para no perder el tren, el constante bombardeo de las grandes empresas de Software como Microsoft, Google, Adobe y algunas otras, hace que estemos constantemente estudiando lo que ellos nos proponen, en mis 20 años, tan solo he realizado 3 o 4 proyectos que pudiesen definirse como innovadores y solo por la aplicación temprana de nuevas tecnologías de reciente aparición, en contraposición somos muy abiertos al cambio, estamos siempre en predisposición de adoptar nuevas tecnologías y cambios, pues nuestra profesión así lo requiere, pero realmente apenas innovamos nada, no hacemos nada diferente, tan solo copiamos aquello que nos proponen las grandes empresas de software, y en el mejor de los casos a veces lo mejoramos un poquito. En mi opinión para innovar deberíamos renunciar a estar siempre a la última y destinar parte de nuestro tiempo a proponer ideas, escoger alguna interesante y llevarla a cabo, en lugar de dedicar todo nuestro tiempo a aprender lo que nos proponen los demás, si bien es necesario estar al día, para no cometer el error hacer algo que los demás ya han construido, un error muy frecuente en nuestra profesión.

Deberíamos también dejar a un lado muchas de las reglas que aplicamos, cuando desarrollo, sobre todo en estos últimos años, tengo un pensamiento que constantemente me dice “demasiadas reglas”, el desarrollo es cada vez menos fluido, menos intuitivo, esto, me hace preguntarme si estaré haciendo las cosas bien, en mi opinión demasiadas reglas limitan la innovación ya que en muchos casos la rigidez de algunas de ellas y el tiempo que destinamos a aplicarlas, evitan que destinemos nuestros recursos a innovar o ser mas creativos.

Debemos hacernos estas preguntas de forma habitual, ¿Cómo puedo mejorar?,¿Cómo puedo hacerlo más rápido?, ¿Cómo puedo sacar mayor valor añadido?, y dedicar parte de nuestro recursos a responder a estas preguntas.

En general, el desarrollo de software de las grandes empresas de desarrollo es un área muy innovadora, ellos han entendido mejor que nadie la necesidad de innovar constantemente y por ello son ellos y no nosotros los que logran el éxito, y no me refiero solamente a obtener un buen salario…

El área del desarrollo de software es un mercado sumamente competitivo, pero con gran potencial, no hay más que fijarse en empresas que en pocos años pasan de no ser nada a cotizar en bolsa, en ver cuántos productos nuevos aparecen y otros que en poco tiempo desaparecen, como cambiamos de un año para otro nuestra forma de trabajar, como tenemos que obligatoriamente apostar por una formación continua para poder mantenernos en este mercado, pero no lo hacemos porque somos innovadores, lo hacemos porque es un requerimiento de mercado, me pregunto cuántos desarrolladores de los que escribimos aquí o de los que nos leen, realizan proyectos innovadores si no es por petición de un cliente, creo que muy pocos son los que llegan a alcanzar este status, que envidia tengo de Miguel Llopis que trabaja en el desarrollo de nuevas tecnologías y puede destinar gran parte de su tiempo a ser innovador.

Para innovar debemos trabajar en equipo, las relaciones personales son fundamentales para poner una idea en funcionamiento, saber convencer, incentivar y hacer participes a la gente de un equipo con una idea es algo fundamental, y estoy desacuerdo que la mayor parte de las veces hace falta la figura de un Líder que incentive y mantenga unido al equipo para llegar a obtener mejores resultados, si bien tener un objetivo común en el que todos los componentes creen puede hacer que esta figura se reparta entre todos los miembros del equipo, en un equipo innovador todos deben escuchar y debatir las ideas de los demás, la política de la empresa debe otorgar libertad en la toma de decisiones, conozco muchas personas a los que se les limita la capacidad de innovación en pro de la rentabilidad, así pues es necesario que todos desde el primero al último apueste por la innovación.

La necesidad es también un factor que nos llama a innovar, solo cambiamos cuando tenemos la obligación de mejorar, ponemos en marcha nuevas ideas cuando las que tenemos no sirven o no nos aportan lo suficiente, desgraciadamente en la mayoría de los casos, es, en estos momentos cuando es demasiado tarde.

Es curioso ver los gráficos de las patentes en España, está generalmente admitido que el número de solicitudes de patentes originadas en un país constituye un indicador bastante significativo de la situación de su sistema de I+D+I,

Fuente: http://www.oepm.es/cs/Satellite?c=Page&cid=1213455385201&classIdioma=_es_es&idPage=1213455385201&pagename=OEPMSite%2FPage%2FtplListaDocumentos&numPagActual=1

clip_image002

clip_image004

BSH Electrodomésticos España es la primera empresa industrial en solicitar patentes, con un total de 65 en 2008.

Solo la Empresa IBM, la que más patentes realizo en 2008 tiene 4000, observando estos gráficos no me estraña que nos encontremos en la situación actual, lo extraño es que no hayamos llegado antes.

Una cosa esta clara, España tiene mucho camino que recorrer y actualmente estamos a la cola de la mayor parte de países desarrollados, debido a que las políticas de formación y de I+D+I desde el gobierno y las empresas han sido desastrosas.

En estos tiempos que corren y creo que en un futuro cercano si no somos capaces de innovar, nunca llegaremos a tener éxito y tarde o temprano fracasaremos, el miedo al cambio, el riesgo de invertir en nuevas ideas nos impiden innovar, hay que enfrentarse a estos miedos para poder llevar a cabo nuevas ideas, la mayor parte seguro que fracasaran, pero con que tan solo una llegue a buen término merecerá la pena.

Creo que el fracaso conduce al éxito, hace muchos años que leía un artículo del Newsweek que decía que los empresarios de EEUU preferían contratar a alguien que hubiera establecido tres empresas y hubiera fracasado que a un candidato que tuviese un Curriculum excelente.

Innovar es hacer cosas diferentes, arriesgarse, no temer a fracasar, cuestionarse que aquello que funciona hoy, no lo hará mañana o que siempre se puede mejorar, y como decía Albert Einstein, si quieres cambiar algo no hagas siempre lo mismo…

¿Qué opináis?

Sobre el porqué utilizar metologías Agiles (Scrum) no es una moda...
14/7/2009 14:54

Escribía el otro día David Arrollo (Ddaz) sobre si las metodologías agiles, en concreto Scrum estaban de moda, me he animado a realizar este post para plasmar mi opinión sobre este tema.

Como sabéis las metodologías ágiles evolucionaron sobre el año 1990 en respuesta a los métodos estructurados y estrictos extraídos de los modelos de desarrollo en cascada, aunque sus principios se establecen en el año 1986, no es hasta hace unos pocos años que se empieza a adoptar por multitud de empresas.

Pienso que la adopción masiva de metodologías en el área del desarrollo de software no es una moda tal y como comenta Fran en su blog, creo que cada vez mas empresas están adoptando estos métodos de trabajo con el único fin de mejorar su gestión optimizando sus procesos para intentar lograr ser más competitivos. Hasta hace relativamente poco a la mayoria de empresas  todo esto les daba igual, sobre todo debido a la bonanza económica, pero los mercados, cada vez más difíciles y competitivos, y la crisis actual estan provocando que algunas entidades se centren en la búsqueda del ahorro de costes y la mejora de la rentabilidad y poco a poco estas empresas se están dando cuenta de que mejorar su gestión interna es un aspecto cada vez mas importante, que puede llegar a marcar la diferencia, una ahorro de tan solo un 10-20 % puede hacer que la empresa sea competitiva o no.

No hace muchos años el conocimiento de los procesos en las empresas era aglutinado por unos pocos, algunas se han comenzado a dar cuenta de que el verdadero valor recae en todas las personas que la conforman y que en la mayor parte de los casos son los operarios de las maquinas, los técnicos cualificados y personas cercanas a los procesos los que más saben del trabajo que están realizando y consecuentemente los que conocen mejor como poder mejorarlo. Esta situación está provocando que las empresas empiecen a contar con la opinión de estas personas que antes eran meros ejecutores de los procesos para formar parte activa en la toma de decisiones.

Algunas metologías de trabajo, en este caso "Scrum", ya que es la mencionado por Fran, explota precisamente estas ideas, basan su gestión en la creencia de que su valor esta en las personas que conforman los equipos de trabajo tal y como comento en el post y la reducción de la burocracia apoyada en la simplicidad.

Pero esto no es nada nuevo, en los sistemas Lean, los equipos de mejora continua, trabajan con la misma idea que la mayor parte de las metologías agiles, intentan eliminar la burocracia y optimizar los procesos en base a sus objetivos más cercanos ayudados por las personas que realmente los conocen en profundidad.

Algunas empresas de desarrollo de software están comenzando a adoptar una metodología por necesidad comercial, porque para sus clientes es un requisito, muchos organismos oficiales están comenzando a demandar la adopción de metodologías de trabajo cuando contratan un desarrollo, pero esto no es por moda, si no por necesidad, por la necesidad de evitar errores cometidos en el pasado, con aplicaciones que han sido un autentico fracaso, que han costado autenticas barbaridades, que han pasado de una empresa a otra y nunca han funcionado, estos errores y fracasos están haciendo que muchos de estos organismos hartos ya de "tirar" el dinero en informática empiecen a exigir la adopción de mejores sistemas de trabajo que les aseguren la viabilidad de sus proyectos.

Otras entidades realizan la adopción simplemente, porque obtener un certificado en una determinada metodología les hará distinguirse de sus competidores. En este último caso lo comparo con la ISO 9001, conozco varias empresas que únicamente disponen de este certificado únicamente por una razón comercial o porque alguno de sus clientes se lo exige, que lejos de hacerles mejorar tan solo les aporta burocracia y que al final desgraciadamente certificarse se convierte en una cuestión de dinero, con dinero se puede contratar más personal para gestionar todos los requisitos, se puede invitar a comer a buen restaurante al responsable de la certificación e incluso en algunos casos se puede llegar a "comprar" la certificación, he visto empresas con la ISO 9001, que ni siquiera son capaces de gestionar el stock de su almacén o encontrar un pedido en sus ficheros , desgraciadamente esto ocurre con multitud de empresas y hace que al final el valor de estas "certificaciones" quede en entredicho. También he visto algunas empresas que le han sacado valor a este tipo de certificaciones, con ellas han aprendido a gestionar de forma más adecuada sus recursos. En cualquier caso con certificación o no, todas tienen una razón para su adopción, si bien es cierto que la mayoria lo único que buscan es un título que avale lo bien que trabajan.

En cambio otras ven en la adopción de las metodologías de trabajo una forma de llegar a ser mas "competitivos", mejorando su gestión interna y evitando cometer errores. En el área del desarrollo de software venimos arrastrando desde hace mucho tiempo una serie de problemas que además de ir minando un mercado de clientes cada vez mas descontentos, hacia que el coste de los desarrollos de software aumentase de forma exponencial, en muchos casos los proyectos se convertían en trabajos de dudosa rentabilidad y en otros, eran los clientes los que debían asumir los costes derivados de su mala planificación. Algunos de los problemas más habituales vienen derivados de estimaciones erróneas, problemas de trabajo en equipo, relaciones con los clientes, gestión de errores, gestión de versiones, cambios de contexto, etc.

Las metodologías ágiles nacen para dar solución a todos estos problemas, se conforman como una necesidad para todos aquellos que desarrollamos software, marcan las pautas y las reglas necesarias para poder minimizar todos estos problemas. No quiere decir que seán la solución mas adecuada, serán mejores o peores en base a las necesidades, capacidad y funcionamiento de cada empresa, y estará en su mano sacarles verdadero partido.

Scrum se conforma como una metología sencilla de aprender, ofrece gran valor añadido sin demasiado esfuerzo, eliminando la burocracia y centrándose en la productividad a través de iteracciones cortas, el valor del equipo, la gestión de las estimaciones y la relación con el cliente, hacen de Scrum una metrología facil que puede resumirse en una hoja y que es simple de adoptar si se cree en ella tal y como explica Jorge Serrano en Explicando scrum a mi abuela o Rodrigo en Porque me gusta Scrum, para hacerlo, no es necesario ningún tipo de certificación, cualquiera puede aplicar Scrum, los requisitos son sencillos y las reglas, no demasiadas, es por ello que Scrum es una metodología que se centra en la mejora continua y que permite gestionar varios proyectos sin una burocracia y costes excesivos. Por estas razones y no por otras, creo que Scrum se está empezando a utilizar de forma masiva, aunque todavía son muy pocos los que la sacan partido de verdad.

Por otra parte las nuevas tendencias y formas de trabajar se están empezando a trasladar a muchos sectores industriales y laborales, no solamente a la informática, en mi empresa, por ejemplo, estamos implantando un sistema LEAN MANUFACTURING, pero no por la moda de Toyota, que desde luego ha influido enormemente en su adopción (de hecho actualmente es el primer fabricante de automóviles del mundo), 'por algo será', si no en la búsqueda de mejorar nuestro sistema de trabajo y ahorrar costes, en resumen hacer que la empresa sea más competitiva y que tiene muchas similitudes con las metodologías de trabajo que utilizamos en desarrollo, de hecho se utilizo como base de algunas. Al final todos buscamos lo mismo, mejorar la productividad, ahorrar costes, ser más competitivos, mejorar nuestra relaciones laborales con nuestros clientes y el trabajo en equipo, hacer entender a aquellos que nos rodean que el trabajo que realizamos es complejo y difícil y que cada vez es más importante mejorar nuestra gestión de proyectos y evitar muchos de los errores que venimos cometiendo desde hace años. Que utilicemos Scrum o cualquier otra metología que nos permita realizar esto es indiferente, la utilización de una metologías no garantiza el éxito del proyecto, tan solo nos marca las pautas para evitar errores e intentar llegar a ser más competitivos.

Las metodologías de trabajo proponen soluciones para resolver problemas comunes, es algo así como la aplicación de patrones de diseño, ¿ porque no utilizar una solución ya probada para resolver un problema similar?. Sin embargo cuando hablamos de diferentes metodologías, parece que se desencadene una guerra, si un fontanero tiene que instalar una tubería de cobre la forma de hacerlo será en base a los elementos y el entorno que tiene delante, en cambio si la tubería es de otro material seguro que el método es diferente, con las metodologías pasa lo mismo, habrá metodologías que se adapten mejor a un tipo de cliente y un entorno determinados y en otras que puedan suponer un autentico fracaso ya que las ideas de las metologías deben ser coincidentes con la política de la empresa, este es el factor que hace que muchas fracasen en su adopción, "adoptamos algo en lo que no creemos", pero no tienen porque ser unas mejores que otras, tan solo se adaptaran mejor en base a la forma de trabajar de las empresas, el entorno y otros factores. En todo caso, nacen para ofrecernos soluciones a los problemas con los que tratamos habitualmente, en los que aspectos tan importantes como la estimación, la colaboración y mejora del trabajo en equipo son factores fundamentales que nos permitirán adaptarnos y ser más competitivos.

Lo verdaderamente triste es que parece que en algunos países estamos a la cola y que hablar de la adopción de metologías de trabajo provoca una gran controversia, creo que la mayor parte de las veces por desconocimiento total de lo que implica la adopción de estos sistemas de trabajo.Sin embargo, algunas personas y empresas, quizás las menos, se han empezado a dar cuenta de la importancia que tiene la adopción de estos métodos de trabajo, que nos permiten optimizar y mejorar nuestro ámbito laboral. Esto es fundamental para el área del desarrollo de software ya que la complejidad de los sistemas y las diferentes tecnologías conjuntamente con el progreso, hacen que el desarrollo de software sea una de las aéreas que más cambios sufren . Estoy seguro de que aquellas empresas que apuesten por mejorar sus sitemas de trabajo marcaran la diferencia, para las demás creo que sus días están contados, apoyado por la ley de Darwin, 'solo los que mejor se adapten al medio sobrevivirán'.

En cualquier caso si queréis seguir el ejemplo de General Motors, aquellos que creáis que la crisis actual es un invento del gobierno o que las empresas van a seguir exactamente igual, independientemente de su forma de trabajar, no hagáis nada, seguir trabajando igual.

No digo que Scrum sea la solución a todos vuestros problemas, pero que es un buen punto de partida para acercarse a las metologías agiles, robusta y relativamente facil de adoptar frente a otras. Si no usáis ninguna, hará que en poco tiempo no podías vivir sin ella, así que animaros, esto no es una moda, es una necesidad para todos aquellos que queremos mejorar nuestra forma de trabajar.

Windows Presentation Foundation. El final de Windows Forms…
17/6/2009 0:56

Últimamente cada vez leo más artículos que hablan sobre las ventajas de construir aplicaciones en WPF frente a la utilización de Windows Forms, para aquellos que no lo conozcan, WPF es una tecnología que nos permite aprovechar al máximo las características gráficas de nuestros equipos ofreciendo interfaces más ricas de las que estamos acostumbrados. El objetivo de Windows Presentation Foundation es proporcionar avances en el entorno de Windows que permitan crear interfaces que incorporen documentos, componentes multimedia, gráficos bidimensionales y tridimensionales, animaciones, características tipo web, etc.

Sobre la afirmación de que WPF marcará el final de Windows Forms, me parece arriesgada, aunque la evolución que está teniendo esta tecnología frente a Windows Forms no solamente desde Microsoft sino de la mayor parte de empresas de controles de terceros, me hace pensar hasta que punto es cierta esta afirmación.

En los últimos años Microsoft viene acostumbrado a sacar nuevas tecnologías casi por arte de magia y a relegar otras de la misma forma, lo cierto es que el cambio no es tan fácil como se pueda pensar, la adopción de una tecnología como WPF, cambia por completo la forma habitual que teníamos para desarrollar aplicaciones Windows Forms. Los diseñadores gráficos pasan a formar parte casi indispensable de los equipos de desarrollo si queremos sacarle todo el partido a esta tecnologia, si bien es cierto que la mayor parte de empresas dedicadas a desarrollar controles de terceros como Infragistics, DevExpress y otros están apostando seriamente por esta tecnologia  con la inclusión de Skins y controles que nos facilitaran mucho esta labor.

En mi opinión son muy pocos los sistemas de gestión que requieran hacer un uso intensivo de la interface gráfica, sin embargo, en algunos ámbitos como científico o el médico, las capacidades 3D y las animaciones permiten obtener información de forma más eficaz. También es cierto que la mayor parte de los sistemas de gestión actuales suelen tener carencias precisamente en este apartado.

Glenn Block de Microsoft afirma que WPF es de largo la solución recomendada para el desarrollo de aplicaciones de línea de negocio para un futuro inmediato.

Algunas ventajas de WPF son las siguientes:

  • Estilo potente y estructurado.
  • Facilidad para crear estilos y aspectos.
  • Soporta Windows Forms.
  • Es el futuro para el desarrollo de aplicaciones de Vista.
  • Tiene capacidad de reutilización del código existente.
  • Databinding avanzado, que permite enlazar datos con cualquier control.
  • Programación declarativa vs procedural.
  • Capacidades avanzadas para la Web. (WPF/E)
  • Apuesta clara de Microsoft para su implantación.

Desventajas

  • En muchas ocasiones vamos a necesitar el trabajo de diseñadores gráficos para beneficiarnos del potencial de WPF, lógicamente este será un coste que debemos repercutir a nuestros clientes.
  • Modificar código en AXML es un infierno o al menos para mí es bastante complicado.
  • Los requerimientos de los equipos en el apartado gráfico serán mayores, deben soportar DirectX y disponer de una tarjeta gráfica con suficiente capacidad, sin embargo, estos son la mayoría de los pc´s de hoy en día, aunque todavía existen muchos equipos, sobre todo portátiles que no soportan del todo estos requerimientos.
  • Al tratarse de la primera versión, tiene muchos aspectos en los que mejorar sobre todo en el apartado de los diseñadores de formularios y entorno gráficos. De hecho se encuentra aún en fase de desarrollo.
  • La curva de aprendizaje es alta.

¿ Debo migrar mi apliación a WPF ?

No hace mucho tiempo que Miguel Jiménez solicitó que le enviase algunos formularios de la aplicación actual que estábamos desarrollando para ver la posibilidad de realizar un proyecto paralelo de migración a WPF, lógicamente le envié algunos de los formularios más grandes y complejos que teníamos, su respuesta fue: buff estas pantallas con tantos controles, pestañas y funcionalidad para realizarlos con WPF, sería un trabajo demasiado arduo, no se hasta que punto merecerá la pena, tendríamos que dividir algunos para integrarlos en WPF, esto me hace pensar, si WPF está lo suficientemente maduro para abordar sistemas de gestión complejos y si realmente merece la pena realizar este cambio sin una necesidad comercial seria. Creo que existen muchos desarrolladores migrando sus aplicaciones a WPF, sin una razón que justifique la adopción de esta nueva tecnología, todavía son pocos los entornos de gestión empresarial que necesiten verdaderamente un cambio de arquitectura y que son incapaces de articular una necesidad comercial.

Lo cierto es que algunas de las interfaces que he probado son verdaderamente impresionantes, no solo en cuando a mejora del interface gráfico, la velocidad de refresco y la interacción con el usuario mejoran notablemente. Como ejemplo os dejo un par de pantallas de los controles que usamos.

image

image

image

¿ Cuanto apoyo le queda a Windows Forms ?, he leído en alguna parte que Microsoft solo está apostando por WPF ahora y manteniendo Windows Forms, si esto es cierto, WinForms esta condenado a desaparecer y deberemos centrarnos poco a poco en la adopción de WPF, por otra parte el número de aplicaciones existentes hoy en día, hará que el soporte de WinForms persista durante mucho tiempo.

En mi opinión WPF es una nueva tecnología que se está asentando en estos momentos y como tal, no carente de problemas. Su curva de aprendizaje para aquellos que venimos de Winforms es alta. Quizás el verdadero reto no este en aprender como usar esta nueva tecnología, sino en pensar cómo, a través de ella, podemos enriquecer las aplicaciones para alcanzar determinados objetivos, como mejorar la productividad, mejorar la interacción con el usuario, aumentar la satisfacción, mejorar el rendimiento, etc. No debemos olvidar que la adopción de WPF, tendra un coste muy alto si tenemos que incorporar diseñadores gráficos a nuestros equipos de desarrollo. En cualquier caso parece que Microsoft ha realizado una apuesta clara por la utilización de WPF, su adopción en nuevas herramientas como Visual Studio 2010 y el nuevo diseñador de WorkFlow así lo demuestran y que además de confirmarse, ya habria abandonado la mejora de Winforms, con lo que de una forma u otra estaríamos abocados a utilizarla tarde o temprando.

Por otra parte me quedan varias preguntas sin contestar que creo que son comunes a las de muchos desarrolladores y que me gustaría con vuestra ayuda resolver:

¿ Deberiamos comenzar a estudiar a fondo WPF, para la adopción de esta tecnología en un futuro cercano ?

Si tuvieraís que realizar un nuevo proyecto similar a los anteriores desarrollados en Windows Forms, ¿ utilizarías WPF o esperarías a nuevas versiones ?

¿ Sera WPF el sustituto definitivo de Windows Forms o tan solo una nueva tecnología para realizar programas diferentes ?

¿ Sera WPF una tecnología más, que quizas en poco tiempo se vea relegada por otras como Silverlight o que debido a su alta curva de aprendizaje o sus costes no lograra asentarse lo suficiente como para convertirse en el sustituto de Windows Forms ?

¿ Esta lista esta tecnologia para abordar desarrollos similares a los que venimos realizando en Windows Forms ?

¿ Si no tenemos ni idea sobre diseño gráfico o nuestro equipo no puede disponer de diseñadores, podremos sacarle partido a WPF ?, ¿ Tiene sentido utilizar WPF en estos casos ?

En fin, quizas os dejo mas preguntas que respuestas, pero confio que entre todos conformemos una idea mas clara de lo que es WPF y de lo que va a suponer esta tecnología en los próximos años.

 

Pd. Y pensar que todo esto comenzo con CSI….

por Juan Irigoyen | 15 comment(s)
Archivado en:
Manual de detección del Australopithecus
11/6/2009 0:23

image

Según la wikipedia, vivió aproximadamente hace 4 millones de años, al comienzo del Pleistoceno. Creerme todavía existe, yo sigo tropezando con alguno de ellos.

En mis primeros años profesionales dedicados a la informática (digo profesionales no porque fuera un profesional, sino porque intentaba ganarme la vida con este trabajo), no sé si debido a mi juventud o inexperiencia, me tropecé con innumerables especímenes de este género, la mayor parte convertidos en “Empresarios de éxito” con un nivel de formación y educación que no sobrepasaba al de los grandes simios.

Recuerdo una anécdota en especial que me llamó mucho la atención, todo comenzó con una reunión con un homínido de esta especie (aunque yo entonces no me había percatado de nada, es más, me parecía increíble todo lo que contaba), después de haberlo escuchado hablar durante varias horas sobre la importancia que tenía la informática para ellos, la necesidad urgente de dotar a su Empresa de medios adecuados para su gestión y escuchar frases como: “yo, me he hecho a mí mismo”, “cuando dejé la cueva, solo me lleve lo puesto”, “cazaba las aves con tiragomas y no con escopetas calibre 458 como ahora…”, etc.

Después de la reunión, la entrega del presupuesto (“¿no sé por qué?, si los informáticos no tenemos derecho a cobrar por nuestro trabajo.”). Enseguida ví como frunció el ceño, me miró con cara de asombro y pocos amigos y me dijo: después de nuestra conversación no has entendido nada, (“claro, si yo vengo aquí a aprender, no a trabajar, gracias Dios por esta oportunidad…”), me dijo: esto no es lo que esperaba de tí, pensaba que eras un tipo inteligente, este proyecto tiene valor añadido, si realizas el programa podrás vendérselo a todas las empresas del sector en las que estoy muy bien considerado, tienes que mirar esto con "perspectiva".

 ¿Pero como podeis cobrar tanto?, joder vosotros los informáticos estais hechos de otra pasta y mirando a la secretaria le comento: ¡mira!, estos “ingenieros” que acaban de salir de la facultad y no saben hacer la "o" con un canuto, quieren cobrarnos hasta por respirar…

Incauto, trate de explicarle las razones del coste del proyecto, y que valorar las 300 horas de trabajo por 4 gallinas, media docena de buitres leonados, un cráneo de mapache y un cuerno de alce, no era ni con mucho un gran presupuesto, pero claro no tenía “perspectiva", finalmente dijo: bueno ya te llamaremos… Me fuí a casa, pensando: “joder me habré pasado, quizás tuviese razón, tendría que haberle aceptado solamente 1 cabra y el cuerno de alce, al fin y al cabo después podría comercializarlo en otras aldeas…”.

Paso bastante tiempo y el “eslabón perdido” vuelve a llamar y me dice: ¿te acuerdas de mí?, pues nada, que me he decido por fin y voy a contratar tus servicios, y vuelta a otra reunión interminable en la que aguanto estoicamente sus logros y conquistas, ahora la necesidad de tener un sistema informático es imperiosa, ya que cometió el error de “contratar” a un amigo del primo del tío de la novia de su excuñado que había trabajado en la cabaña del Tio Tom y en su tarjeta decía “Product Manager”, además, era campeón del mundo en tiro con arco. El desgraciado, sin motivo aparente le había dejado en la estacada. Seguimos hablando y comento: “bueno, pero, lo del presupuesto aquel, tendríamos que revisarlo…”. Pensé, ("desde luego, han pasado dos años y al menos hay que incrementarle el IPC"). Continuó: pues hoy en día las cosas no son como antes y bla, bla, bla.

Como mi situación era complicada decidí aceptar un generoso descuento, "solo cobraría 1 cabra, las gallinas y el cuerno de alce, que les den a los coño buitres leonados...", y me puse manos a la obra, de lo malo, malo, al menos, aprendería muchas cosas sobre su negocio, ya tendría tiempo de ganar mucho dinero cuando me convirtiera en un buen profesional…, aprovecharía para aplicar alguna nueva tecnología con la que poder sacar mayor valor añadido al software desarrollado y con suerte quizás, podría venderlo a otras tribus de la zona.

Esa misma semana me comunica que las reuniones periódicas semanales no iban a poder ser realizadas los lunes, ya que, debido a sus logros en la gestión de la aldea le han hecho jefe de la tribu y tiene que dedicar todo su tiempo productivo a fabricar herramientas, palitos para "pescar" hormigas, tiras de corteza para cazar termitas, martillos para cascar nueces, ramitas para espantar moscas, etc. y que además el sábado tiene que ir al consejo tribal, así que solo podría reunirse conmigo el domingo por la mañana, pues por la tarde tenia la fiesta "canival...".

Como ya había dedicado mucho tiempo al proyecto y debido a mi complicada situación económica, decido aceptar y reunirme con él todos los domingos por la mañana para tratar de conocer en detalle los procesos más complejos de su negocio, después de un par de sesiones domingueras en las que sólo me explica cómo ha llegado a convertirse en un “Empresario de éxito”, me llama diciendo: “A partir de ahora no voy a poder atenderte, así que mejor trata de todos estos asuntos sin importancia con mi secretaria”, “¡Dios! que alivio”, por fin voy a tratar con alguien que al menos tiene graduado escolar… y además usa minifaldas…. si, si, en la aldea del tipo este, todas las secretarias iban con minifaldas y enseñando… bueno mejor me callo, una de sus frases decía: “hay que saber sacar verdadero partido de los recursos que disponemos…”

Después de un par de reuniones con su secretaria, ésta me comenta que el tal Australopithecus, tiene un tinglado montado de miedo, no paga a nadie, ella lleva seis meses y tan sólo ha cobrado el primero y el tío se acaba de comprar una balsa supermirafiori, para navegar por el río y visitar a una novia que tiene en la tribu ubicada 10 millas más arriba y que además no rema, que le duele mucho la espalda y que tiene que venir tarzan con la chita y el elefante para remontarle por el río. El sujeto intenta cada poco tiempo hacer la vida imposible a sus empleados para que muchos se tengan que ir, renunciando incluso a la indemnización, y que el “informático” que había estado antes que yo, lo había dejado porque llevaba más de un año trabajando y no le había pagado nada, que unicamente le había contratado porque exigia 2 buitres leonados menos que yo.

Ante la situación, decido paralizar al proyecto hasta no cobrar al menos el trabajo realizado, cuando hablo con él para comentarle la situación, le empieza a salir espuma por la boca, los ojos se le hinchan y enrojecen y los colmillos le crecen 4 cm, tembloroso le digo que tiene que asumir la deuda del trabajo realizado, que no estoy dispuesto a continuar hasta haber cobrado al menos un par de gallinas y el putísimo cuerno de alce que por supuesto ya formaban parte de mis deudas, responde que no está dispuesto a pagarme nada, ya que no ha recibido nada a cambio, es más, que si alguien debe algo, ese soy yo, ya que me ha dedicado gran parte de su valioso tiempo y claro, este, era muchísimo más costoso que el mío, ante la peligrosa situación que se fue agravando poco a poco, decido irme y darle un poco de tiempo para pensar con tranquilidad.

Al cabo de unos meses y viendo que las gallinas y el cuerno de alce seguían sin aparecer, decido armarme de valor y acercarme un domingo por la mañana a la choza, a ver si podíamos solucionar la situación de alguna forma, cuando llegó al lugar, aparece una mujer, le preguntó por el sujeto y me dice que ella es su mujer y que este se ha fugado a la tribu del río de arriba dejándola con sus dos hijos, que se ha llevado las dos vacas que tenían, para entregárselas al Jefe de la otra tribu y hacerse con los servicios de un par de mujeres y que ha les ha dejado sus deudas y otros problemas, me enseña lo que queda del negocio, los empleados hartos ya de la situación, habían arramplado con todo y no habían dejado títere con cabeza, incluso la habían amenazado si no aparecía pronto….

No penséis que esta fue la única vez que me han pasado situaciones similares, de hecho yo pensaba que jamás me podría pasar algo parecido, pues este sólo fue el comienzo de varios casos que me ocurrieron posteriormente. Así que he decidió redactar un pequeño manual para que podáis detectar este tipo de homínidos tan perjudiciales para el hombre:

1 – El Australopithecus suele comerciar con cuerno de alce, no entiendo como lo hacen, el alce es mucho más inteligente que el Australopithecus ...

2 – Suele despreciar a los sujetos de su misma especie, incluso a sus empleados y familiares cercanos, ten cuidado, lo mismo hará contigo.

3 – Se siente el más listo del mundo, es el único que sabe hacer fuego, los que le rodean no tienen ni *** idea de nada, ellos son los mejores.

4 – Si oyes frases similares, ¡cuidado!, se trata de la especie más peligrosa:

  • Me he hecho a mí mismo...
  • Cuando me fuí de la cueva sólo me lleve lo puesto.
  • En mis tiempos cazaba los leones a mordiscos…
  • No tengo una empresa, tengo un grupo empresarial.... (El equivalente a una Choza y 4 pringaos distribuidos por la peninsula que no cobran hace 6 meses)
  • El nombre de su tribu comienza por “Asociación de ….”
  • Nosotros somos pioneros en….
  • El dinero no es importante, yo me fuí sin nada y mira en lo que me he convertido...
  • He construido yo solito este imperio…
  • Tienes que entender que ésta, no es una empresa cualquiera…
  • Yo invente la rueda...
  • Tu, no estás aquí para pensar...
  • Si a un trabajador no le da tiempo a terminar su trabajo, es su deber continuar hasta finalizarlo...
  • La formación no sirve de nada con estos mendrugos..., eso es para intelectuales...
  • Si quieren estudiar que lo hagan en casa, que yo les pago por trabajar...

5 – Los gestos son fundamentales, a veces, echan espuma por la boca, acostumbran a gritar de forma habitual, y si continuas sin entenderlos te atizan un garrotazo.

6 – Si sacan fajos de billetes y te dicen: ¿cuánto necesitas?, cógelos rápido, suele ser un truco muy habitual. Los sacan y los introducen de nuevo en la billetera a la velocidad del rayo. Pero a ti te queda el mensaje subliminal, cuando te vas solo ves los billetes que te debe...

7 – Si quedan contigo el domingo, mucho cuidado, es de los que no van a misa..., además acostumbran a cazar ese dia.

8 – Si se compra una balsa supermirafiori, ojito, estás sólo se otorgan a los homínidos más peligrosos que militan en algún partido político.

9 – Hay una prueba que nunca falla, cuando hableis con él, decir la palabra “gratis”, si sus ojos empiezan a dar bandazos de un lado a otro y aparecen dólares en la cornea como a tío Gilito, es uno de ellos.

10 – Cuando le visitas suele hacerte esperar, tranquilo, está ocupado con otras cosas mucho más importantes que ni con 20000 años de evolución llegariamos a entender.

11 – No le dan ninguna importancia al dinero, total ellos disponen de todo el necesario.

12 – Sus empleados los “adoran”.

13 - Son muy difíciles de reconocer, ahora se depilan con laser y algunos no se parecen a las fotos de carnet de la parte superior.

14 - Si te invita a la fiesta "canival" y te dice que vas a ser el protagonista, ¡ojito!...

Si teneis la suerte de tropezaros con algún especimen de este tipo, recordar, nosotros, los simples mortales estamos en este mundo para ayudarlos, nuestro trabajo y sacrificio no tienen ningún valor, con esta especie podemos aprender a hacer de todo, he visto informáticos que lo mismo instalan una centralita de teléfono, te hacen una paella valenciana o cazan un búfalo con arco y flechas, si no podeis ganar dinero y vuestros hijos tienen que ponerse a trabajar, pues nada, que dejen los estudios y se pongan, total estudiar no tiene ningún sentido, con garrote, mano dura y sin tener ni *** idea de informática se podrán ganar mucho mejor la vida tal y como demuestra esta especie.

Un último consejo, nunca comiences a trabajar bajo ningún concepto si al menos no te hace entrega de un pequeño porcentaje del coste del proyecto, 4 gallinas o una cabra suelen ser suficientes. Y recordar llevar siempre el garrote a mano, podeis acabar así:

  image

Recursividad con Sql Server
22/5/2009 22:25

Una función muy interesante de Sql Server es la de poder seleccionar un conjunto de datos de forma recursiva de manera que podemos obtener una serie en estructura de arbol.

Partimos de una tabla que tiene dos campos, llamados clave y padre, el campo clave se relaciona con el padre para formar la estructura en arbol.

El siguiente procedimiento almacenado muestra un ejemplo de como conseguir esto:

ALTER PROCEDURE [dbo].[Usuarios_seguridad_seleccionar]
AS
BEGIN    
    DECLARE @minClave int
    SELECT @minClave = MIN(Clave) FROM dbo.Usuarios_seguridad;
    
    WITH UsuariosAccesos AS
    (
        SELECT top 1 us1.Padre,us1.Clave,us1.Variable,us1.Modulo,us1.Contenido,us1.Acceso,us1.Imagen 
        FROM dbo.Usuarios_seguridad us1 
        WHERE us1.Clave = @minClave
        UNION ALL
        SELECT top 100 percent us2.Padre,us2.Clave,us2.Variable,us2.Modulo,us2.Contenido,us2.Acceso,us2.Imagen 
        FROM dbo.Usuarios_seguridad us2 
        INNER JOIN UsuariosAccesos AS us3 ON us3.Clave = us2.Padre  
        WHERE us2.Clave <> @minClave 
    )
 
    SELECT TOP 100 PERCENT ia.Padre,ia.Clave,ia.Variable,ia.Modulo,ia.Contenido,ia.Acceso,ia.Imagen 
    FROM UsuariosAccesos ia
    ORDER BY padre, clave
END
GO
 
La clausula with debe contener un miembro delimitador, en este caso el formado por la  primera sentencia Sql que hace referencia al valor mínimo (Primer nodo) y el segundo miembro recursivo que hace referencia a la misma tabla definida el la clausula With.

El procedimiento almacenado calcula el valor mínimo del nodo con la clave mas baja, posteriormente va leyendo cada nodo relacionado de forma recursiva ya que en el inner join se relaciona con el conjunto de datos definido en la clausula WiTH, finalmente devuelve el conjunto de datos en un orden determinado, el resultado obtenido es el siguiente:

image

La consulta retorna los datos de forma similar a la estructura de arbol que posteriormente se carga en el tree.

image

Para cargar los datos en el control, podiamos haberlo hecho sin recurrir a la recursividad en Sql Server y hacerlo directamente con el lenguaje de programación en el cliente, pero hay veces que puede ser mas interesante recurrir al servidor en lugar de hacerlo en el cliente, por ejemplo para buscar un dato determinado aprovechando las ventajas de las busquedas en el servidor y devolver su nodo, borrar todos los nodos relacionados o simplemente por descargar la tarea del lado del cliente.

Si quereis mas información sobre la clausula WITH que permite realizar este tipo de consultas podeis encontrala en http://msdn.microsoft.com/en-us/library/ms175972.aspx (Ingles) o http://technet.microsoft.com/es-es/library/ms175972(SQL.90).aspx (Español).

por Juan Irigoyen | 4 comment(s)
Archivado en:
Calidad de código
20/5/2009 22:24

La calidad de software engloba muchos y diferentes aspectos sobre el desarrollo de aplicaciones, que pasan desde la elección de una buena arquitectura, hasta utilización de diferentes herramientas, la aplicación de diferentes técnicas y metodologías de trabajo. Creo que todavía hoy en día, existe mucha gente reticente a apostar por la calidad de código, debido a que piensan que su coste es mayor que su beneficio.

Cuando empecé a trabajar en equipo, surgieron una serie de problemas de difícil solución, en seguida me di cuenta de que los programadores escribimos código de forma muy diferente que realiza las mismas cosas, generalmente algunos, los más experimentados solían redactar un código mas legible, mejor documentado, necesitaban menos líneas para llegar a la misma solución, ya que sus conocimientos eran mayores, esto originaba muchos problemas cuando tenian que modificar o entender el código de los demás y es aquí cuando empecé a interesarme por las reglas de estilo, fxcop y otras herramientas que de alguna forma nos permitían establecer reglas para que todos pudiéramos por decirlo del alguna forma “entendernos mejor”. Por otra parte en la depuración de las aplicaciones observe que era mucho menos costoso detectar y corregir un error en una fase temprana que hacerlo posteriormente.

Para poder entender mejor el trabajo de los otros programadores comenzamos a aplicar algunas de estas reglas, desde normas de estilo, documentación, desarrollo de pruebas unitarias, aplicación de patrones de diseño, normativas de base de datos y un largo etc. Esto empezó a facilitarnos la compresión y la modificación de programas, en poco tiempo empezamos a tener una visión muy diferente del proyecto, nos aporto más claridad y conocimiento del trabajo de los demás y nos ayudo a detectar gran parte de errores en una fase temprana del desarrollo.

Algunos de los beneficios más importantes que observo son los siguientes:

- La aplicación de patrones de diseño suponen la solución más adecuada para resolver un problema determinado. Esta ha sido elaborada y seleccionada en base al entendimiento y posibles soluciones propuestas y analizadas por mucha gente.

- La adopción de herramientas como fxcop, stylecop, resharper, coderush, refactor y otras, permiten minimizar algunos errores en la fase de desarrollo además de obligar a cumplir ciertas reglas de calidad y estilo, que de no utilizar, provocan si el desarrollador no es un experto, a cometer errores de difícil detección como fugas de memoria, aprovechamiento óptimo de los recursos, localización de código no utilizado, y un largo etc. Por otra parte si todos las adoptan nos habituamos a escribir código de una manera similar, con lo que nos será más fácil comprender el trabajo de los demás. De la información de los errores que nos proporcionan aprendemos a programar mejor, liberando y utilizando recursos adecuadamente, con lo que nuestro conocimiento aumenta. Algunas de estas herramientas cuentan con utilidades para ayudarnos a escribir el código y refactorizar de una forma mucho más rápida.

- El uso de profiles nos permite detectar cuellos de botella y otros problemas que de otra forma serian prácticamente imposible de conocer.

- La utilización de pruebas unitarias y otras técnicas de testeo, nos permiten detectar errores en una fase temprana, si no lo hacemos a tiempo a veces puede implicar que tengamos que modificar más de un módulo relacionado con este, con lo que el coste se incrementa aún más. Como dice la frase, “más vale prevenir que curar”.La ventaja de contar con pruebas unitarias de un módulo que no hemos desarrollado nosotros nos permite entender mejor el comportamiento del programa. La aplicación es más fácil de modificar ya que si alguien altera el programa, por ejemplo cambiando el nombre de un campo de un procedimiento almacenado o alterando alguna función como el cálculo de totales de una factura, detectaríamos el error mucho antes de ponerlo en producción evitando mayores consecuencias.

- Se disminuye la dependencia del equipo de desarrollo: Si el día mañana alguno de los desarrolladores no está o la empresa de desarrollo cierra, será mucho más fácil encontrar a alguien que entienda el código que cumple unas determinadas reglas. Si cada miembro del equipo escribe software de forma diferente esto se hace practicamente imposible. Si otra persona o empresa externa cumple nuestros requisitos de calidad esto permite que pueda comprender y extender la aplicación más fácilmente.

La calidad de código no es opcional, de no aplicarla el coste de nuestros proyectos con seguridad será mayor.

Pero no todo es de color de rosa, utilizar estas herramientas requiere tiempo, formación y sobre todo constancia. Realizar pruebas unitarias además de ser costoso requiere mucha disciplina y un alto nivel de desarrollo, no solamente debemos preocuparnos de tener la máxima cobertura en nuestro código, si no que debemos intentar probar todos los extremos, valores nulos y otros factores que de no realizarse disminuyen los beneficios de estas. De igual forma aprender a utilizar profiles y otras herramientas llevan mucho tiempo en formación y desde luego tienen su coste. No debemos obsesionarnos con realizar pruebas unitarias y cumplir con el 85 % de cobertura en todo nuestro proyecto o cumplir a raja tabla todas las reglas que propone fxcop, resharper, coderush, utilizar reglas de estilo, realizar pruebas de carga, utilizar mock objects para crear independencia con nuestro entorno de datos, utilizar profiles para analizar hasta la más mínima señal de que algo va mal, etc, debemos comenzar poco a poco implantando alguna y habituarnos a utilizarla. Si haceís esto y dedicais un poco de tiempo en aprender a sacarles partido, os puedo asegurar que la mayoría se harán indispensables en vuestro trabajo.

Recuerdo que la primera vez que pusimos en marcha fxcopy en uno de los proyectos aparecieron miles de warnings, os aseguro que fue un autentico coñazo eliminarlos, ya que lo aplicamos en una fase media del desarrollo, nos costó bastante tiempo poner la aplicación en orden, pero aprendimos un motón de cosas sobre programación, algunas que nunca hubiéramos conocido si no llega a ser por este tipo de herramientas. Ahora no podemos vivir sin él y cuando vemos una aplicación que no lo utiliza en seguida nos damos cuenta de los errores que se cometen.

Las ventajas de desarrollar código de calidad son innumerables, se facilita la detección precoz de errores y nos permite anticiparnos y corregirlos antes de poner el sistema en producción evitando tener que rehacer gran parte de las aplicaciones. Estas herramientas nacen con el objetivo de permitirnos mejorar en nuestros desarrollos, no quiere decir que nuestra aplicación vaya a estar libre de fallos, pero si que será mejor, que aprovechara mejor los recursos y por supuesto, que tendrá menos errores, tendremos mayor seguridad a la hora de modificar un programa y reglas de trabajo en equipo que de otra forma serian muy difíciles de controla, se facilita la escritura de código y la detección visual de errores en tiempo de diseño, ahorrando mucho tiempo a la hora de programar y depurar la aplicación.

El esfuerzo que debemos realizar para desarrollar código de calidad es grande, pero marcara la diferencia y en poco tiempo nos permitirá recuperar la inversión con creces, así que animaros, merecerá la pena.

Acelera Visual Studio con Discos Solidos (SSD) y Tarjetas de Memoria
13/4/2009 12:00

Después de leer varios artículos sobre los últimos modelos de discos SSD, y con el fin de acelerar mi trabajo con Visual Studio decidí adquirir un disco SSD modelo OCZ Core Series V2 SATA II 2.5" SSD con 120 Gb,  las comparativas con los últimos modelos presentados por Intel X25, decían que incluso iban por delante en cuanto a rendimiento, su coste bastante inferior, de unos 340 € frente a los 650 € de un Intel.

 

Core_v2_back_b

La primera impresión cuando lo tienes en las manos es lo poco que pesa, parece un trozo de plástico. Después de clonar el equipo e instalar el disco duro, el rendimiento no parece mejorar, es mas en algunas operaciones incluso parece más lento, consultando en los foros del fabricante, leo que hay que hacer varios ajustes relativos al cache, el servicio de indexado, desfragmentación y otros. Para los interesados dejo los ajustes aquí http://www.ocztechnologyforum.com/forum/showthread.php?t=47212, que supongo haya que realizar en todos los discos SSD. Me pregunto si algunos serán correctos, no lo tengo muy claro.

Lo curioso es que después de hacerlo las búsquedas de archivos son espectaculares, sin embargo el rendimiento general aparentemente sigue siendo muy bajo, los tiempos de compilación con Visual Studio son similares a la utilización de un disco SATA de 7200 rpm, incluso en algunos casos más altos, los test de disco me decían que el rendimiento en lecturas secuenciales era espectacular, en cambio en lecturas aleatorias dejaba mucho que desear, la gran ventaja de la utilización de este disco es que la batería del portátil a pasado a durar más del doble, de dos horas a casi 5, sigo haciendo cambios en la configuración a través de regedit, pues el fabricante ni siquiera ofrece un programa de configuración, el disco tiene una conexión USB para actualizar el firmware, pero este brilla por su ausencia, lo curioso es que antes de comprarlo estuve leyendo en varios post, que los resultados obtenidos con este tipo de discos pasaban por un aumento de rendimiento en torno a un 30 % frente a un disco SATA Normal, en resumen toda una decepción, espero que con alguna actualización y soporte de Windows 7 para discos SSD el rendimiento pueda mejorar, pero no lo tengo nada claro.

Quizás, para trabajar con herramientas de diseño grafico como autocad que maneja archivos grandes el rendimiento mejore, pero en mi caso con Visual Studio me temo que con la cantidad de archivos que tiene la solución y el tamaño de estos que normalmente no supera 20 Kb no sea así. Lo cierto es que estoy bastante decepcionado con este disco, esperaba al menos cierta mejoria en el rendimiento tal y como se comentaba en los artículos.

Por otra parte acabo de renovar mi antiguo PC, un AMD con doble núcleo de los primeros que salieron al mercado, 4 Gb de Ram y un disco serial ata de 250 Gb, adquirí un equipo DELL Optiplex 960 con un procesador Intel Quad Core, 8 Gb de Ram, Vista 64 y un disco SSD de 64 Gb de la marca Samsung.

samsung_ssd_001

Como sabéis Visual Studio no permite realizar cambios en tiempo de ejecución cuando estas depurando en 64 bits, no entiendo porque ni despues del Sp1 han incoporado esta característica que es verdaderamente importante. Como trataba de potenciar el rendimiento decidi renunciar a esta opción.

Con esta configuración los resultados son espectaculares, se reduce el tiempo de compilación en un 70 %, el equipo abre outlook en decimas de segundo, realmente espectacular, el disco utilizado tiene la mitad de capacidad que el primero, pero en rendimiento nada que ver, impresionante, hay que tener en cuenta de que el procesador tambien hace su trabajo en el proceso de compilación los cuatro procesadores no bajan del 60 % de rendimiento, el sistema operativo es de 64 bits, el uso de memoria no sobrepasa los 4 gygas. Resharper y Devexpress van como un tiro. Es increíble que en un equipo que ronda los 1200 €, el rendimiento haya mejorado tanto, la verdad merece la pena la inversión.

Aprovechando este post, he realizado otra prueba utilizando una tarjeta de memoria de 4 Gb, similar a esta http://www.gigabyte.com.tw/Products/Storage/Products_Overview.aspx?ProductID=2180 Desconozco la marca de la tarjeta que tengo ya que la consiguió un compañero a través de unos proveedores directamente en china, la de la foto es de la marca Gygabyte y es practicamente identica a la mia exceptuando la bateria que es una pila normal recargable de 1,5 V, En España todavía no he visto ningún sitio donde se comercializa.

desktop_productimage_i-ram_1.3_big 

Esta tarjeta te crea un disco virtual de memoria, esta sustentanda por una pequeña batería de litio que se recarga a través del slot PCI, para evitar perder los datos cuando apagamos el equipo, aquí también los resultados son espectaculares, después de dejar el proyecto en el disco de memoria que tiene una capacidad de 4 Gygas, suficiente para almacenar varios proyectos, y redirigir los archivos temporales a un directorio del propio disco, las pruebas son verdaderamente asombrosas, el rendimiento en la compilación es similar al logrado con el nuevo equipo con disco duro SSD. No os puedo poner el precio de esta tarjeta, pero según he leído es cara.

Otra posible solución de bajo coste para acelerar Visual Studio pasa por utilizar memorias Flash como las que se usan en las cámaras réflex digitales de alto rendimiento, abra que ver las especificaciones de lectura(escritura, esta es una de las mas rápidas actualmente..

g_00014498 

Se pueden utilizar como un disco mas en un portatil o se pueden conectar a traves de un interface SATA como el de la foto a cualquier PC, no he realizado las pruebas con este tipo de dispositivos, una memoria de 4 Gb similar a la de la foto no costara mas de 70 €, la de la foto de 8 Gb esta sobre los 110 € y el un interface para pc sobre los 20 €.

adsacf_detail

El ahorro de costes que puede suponer trabajar con este tipo de dispositivos puede ser espectacular, imaginar un equipo de 8 personas que compilen una media de 10 veces al día y el proceso tome unos 4 minutos, supone que podemos ahorrarnos 4 horas diarias solo en la compilación, aunque el dispositivo solo mejorase un 30 % el rendimiento, ya merece la pena realizar la inversión.

Otra solución muy interesante y gratuita para los que dispongais de suficiente memoria, al menos 3 Gygas, puede ser la utilización de este programa gratuito, https://www.cenatek.com llamado RamDiskVe, el programa crea un disco virtual utilizando la memoria ram del equipo, las pruebas que he realizado han logrado mejorar el proceso mas de un 30 %, aunque el rendimiento al guardar el contenido del todo el disco antes de apagar el equipo no es muy bueno y tiene algun problema, de hecho la versión para Windows Vista es beta, pero puede ser una buena alternativa que no nos cuesta nada probar.

En resumen, cuidado al comprar un disco SSD, no todos son iguales… los discos de memoria pueden ser una buena alternativa y si teneís memoria suficiente probar RamDiskVe.

Os dejo un video sobre el samsung SSD, tarda un poco, pero merece la pena. http://www.youtube.com/watch?v=pJMGAdpCLVg

Espero que el post os resulte útil.

Diseñando controles. Atributo DesignerSerializationVisibility.
10/4/2009 19:57

En el siguiente ejemplo hemos encapsulado un texbox dentro de un UserControl y añadido la propiedad MaxLenght para poder modificar la propiedad de control encapsulado.

Public class UserControl1 : UserControl
{
     public UserControl1()
     {
         InitializeComponent();
     }
 
     public int MaxLenght
     {
         get { return textBox1.MaxLength; }
         set
         {
             textBox1.MaxLength = value;
         }
     }
    
     private void InitializeComponent();
     {
         this.textBox1 = new System.Windows.Forms.TextBox();
         this.SuspendLayout();
         // 
         // textBox1
         // 
         this.textBox1.Location = new System.Drawing.Point(3, 3);
         this.textBox1.Name = "textBox1";
         this.textBox1.Size = new System.Drawing.Size(100, 20);
         this.textBox1.TabIndex = 0;
         // 
         // UserControl1
         // 
         this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
         this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
         this.Controls.Add(this.textBox1);
         this.Name = "UserControl1";
         this.Size = new System.Drawing.Size(108, 27);
         this.ResumeLayout(false);
         this.PerformLayout();
 
     }
 
     private System.Windows.Forms.TextBox textBox1;
}

Si arrastramos el control al formulario, observamos que en el código del InitialiceComponent del form aparece la siguiente linea:

this.userControl11.MaxLenght = 32767;

El generador de código ha añadido la propiedad con el valor por defecto en el InitializeComponent del formulario.

A partir de aqui solo se podra alterar el valor de la propiedad dentro del propio formulario, alterando manualmente su valor, esto obligaría a recorrer todos los formularios donde se usa el control.

El verdadero problema es que hagamos lo que hagamos en nuestro control el valor de la linea del InitializeComponent no cambiará ya que esta se introduce solo la primera vez que arrastramos el control al formulario. Con lo que el valor del Maxlengt en el formulario siempre sera 32767.

Si lo que buscamos es poder establecer a todos los controles una propiedad publica y un valor inicial, deberemos decirle a la propiedad que no se agrege a los contenedores donde se utilize el control. Esto se consigue decorando la propiedad con el atributo DesignerSerializationVisibility.

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int MaxLenght
{
    get { return textBox1.MaxLength; }
    set
    {
        textBox1.MaxLength = value;
    }
}

 

El atributo utilizado tiene tres valores posibles:

- Hidden. El generador de código no produce código para el objeto

- Visible. El generador de código produce código para el objeto

- Content. El generador de código produce código para el contenido del objeto más que para el objeto en sí.

De esta forma la linea del InitializeComponent no se introducira en el formulario, si alteramos el valor de la propiedad en el control, su valor se utilizará en todos los contenedores donde le utilicemos excepto en aquellos en que explicitamente cambiemos su valor.

Si establecemos la propiedad sin atributos debemos tener en cuenta que por cada propiedad se añadira al menos una linea en todos los sitios donde utilizemos el control, esto además de penalizar el rendimiento, porque el valor ha de ser cargado cada vez que abrimos el formulario, elimina la posibilidad de realizar cambios en el control y propagarlos a todos los sitios donde se utilize.

En el caso de una propiedad formada por un array inicializado con valores, el problema es mucho mayor, ya que podemos encontrarnos en nuestro formularios casos como este:

private void InitializeComponent();
{
 
       this.userControl13.Array = new string[] {
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "10",
        "11",
        "12",
        "13",
        "14",
        "15",
        "16",
        "17",
        "18",
        "19",
        "20",
        "21",
        "22",
        "23",
        "24",
        "25",
        "26",
        "27",
        "28",
        "29",
        "30",
        "31",
        "32",
        "33",
        "34",
        "35",
        "36",
        "37",
        "38",
        "39",
        "40",
        "41",
        "42",
        "43",
        "44",
        "45",
        "46",
        "47",
        "48",
        "49",
        
};
 
this.userControl13.Location = new System.Drawing.Point(30, 80);
this.userControl13.Name = "userControl13";
this.userControl13.Size = new System.Drawing.Size(108, 27);
this.userControl13.TabIndex = 2;

Es muy importante entender como funciona el generador de código de visual studio para decorar las propiedades de controles y formularios que vayan a ser reutilizados de forma adecuada evitando sobrecargar sus contenedores y aprovechar las ventajas de la herencia.

Más artículos Página siguiente >