archivo

Archivos Mensuales: abril 2010

Supongamos el siguiente caso: te dicen que puedes conseguir un cliente que te asegure al año 1.000.000€ de ingresos para tu organización si consigues sacar adelante un proyecto tecnológicamente difícil, con usuarios complicados y con un plazo de entrega prácticamente inalcanzable.

Por otro lado te dicen que puedes conseguir un cliente que asegura ingresos de 100.000€ para tu organización si consigues sacar adelante un proyecto tecnológicamente simple, con unos plazos holgados, pero que tiene un gran tamaño y es bastante monótono y repetitivo.

¿En cuál crees que tendrías más posibilidades de tener éxito?

¿Por qué si por ejemplo un programador es capaz de hacer el trabajo de tres programadores y le gusta su trabajo hay que convertirlo en analista para que gane más dinero?, ¿por qué no se valora su productividad en lugar cambiarle su perfil profesional?. Alguno dirá, pues porque de analista funcional puedo facturar por él X y de programador 0.6*X. Pese a que esto pueda parecer razonable sólo lo es si medimos los trabajos por horas en lugar de por servicios. Puede que haya algunos encargos que sean simples bolsas de horas, pero habrá alguno (muchos) que serán servicios y ahí lo realmente importante y lo que esperan los clientes es que el trabajo se haga y bien, lo haga un técnico o diez.

Concebir esta forma de organizar al personal, como hemos visto, es rompedora respecto a cómo se suelen estructurar las empresas, pero por el simple hecho de ser diferente no quiere decir que se esté cogiendo un camino equivocado, ya que no creo que sea erróneo aprovechar cada empleado en aquellas tareas donde puede resultar más productivo.

La productividad también está ligada a las aspiraciones y satisfacción del trabajador, por lo que además de que pueda resultar muy productivo en una determinada tarea, hay que evaluar si realizar la misma le llena o quiere evolucionar hacia otro tipo de trabajo. Volvamos al ejemplo del programador, supongamos que se trata de un técnico con una gran habilidad y experiencia en la realización de este tipo de tareas y que siente satisfacción en la realización de las mismas, pero que desea asumir otro tipo de responsabilidades, en este caso soy partidario de que en el momento que se pueda y si es posible se le permita evolucionar tal y como lo está pidiendo, pero que también se le intente enfocar su carrera profesional a donde puede resultar más productivo, es decir, si ese técnico puede resultar un buen analista o un buen gestor, pues resulta interesante incorporarlo a ese itinerario, sin embargo si lo suyo es la realización de tareas eminentemente técnicas, lo mismo hay que incorporarlo al Departamento de I+D o Arquitectura.

Otro ejemplo que puede ilustrar todo esto lo tenemos en el fútbol, supongamos que cuando Casillas negoció su primer contrato importante con el Real Madrid le comentasen: “si quieres ganar más dinero, tienes que jugar de delantero”, ¿no es absurdo?, pues esto es extensible a otras actividades. Lo lógico es aprovechar a Casillas en la posición donde más puede rendir, que es de portero.

Hace poco leí en un libro algo que llevo analizando desde entonces. Venía a decir que en el ámbito profesional cada cual tenía unas habilidades y que eran esas fortalezas las que había que seguir potenciando, en lugar de intentar mejorar en otros aspectos para los cuales no teníamos habilidades especiales. De esta manera, podríamos reforzar aquellos ámbitos en los que de alguna manera marcamos la diferencia, para de esta forma marcarla todavía más, en lugar de intentar evolucionar en otros aspectos donde no se destaca y que como mucho nos situaría en la media de los demás. Este planteamiento está muy orientado a que es mejor ser un gran especialista en algo que ser normal en muchos aspectos. Esto puede parecer discutible o no, pero merece una reflexión. En los dos artículos de esta serie, más que centrarnos en las personas propiamiente dichas, nos vamos a centrar en la perspectiva de esa persona en su trabajo, donde surge la discusión de si es mejor que las personas sigan una carrera profesional convencional o es más práctico aprovechar cada recurso en aquellas áreas donde están más capacitados.

Esta última forma de ver las cosas, difiere en cierto sentido de cómo evoluciona la carrera profesional en muchas empresas u organizaciones, donde las estructuras verticales indican el sentido hacia el cual se dirige la trayectoria de un individuo en la misma, sobre todo si quiere sentir algo más de peso en la cartera.

Supongamos que una persona tiene una habilidad especial para programar, que le permite ser tremendamente productivo y que además se siente realizado con esas tareas, ¿por qué no enfocar su carrera profesional hacia la realización de ese tipo de tareas?, ¿por qué ponerlo a realizar tareas de análisis de sistemas de información o gestión de proyectos, cuándo en eso es una persona más del montón o por debajo de la media?. Lo mismo se podría decir al revés, es decir, si una persona tiene una habilidad especial para tratar con clientes, con usuarios, para obtener requisitos, para negociar un contrato, para solventar problemas de gestión, ¿por qué hacerle pasar por una serie de etapas donde si bien puede obtener un aprendizaje que le puede ser de utilidad no es tan productivo como lo es realizando otras tareas?.

Pese a que pueda parecer de sentido común utilizar cada recurso en aquellos ámbitos donde puede ser más productivo, la realidad es que la propia deriva del funcionamiento de una organización hace que no sea así y se produzcan mejoras en las condiciones económicas de un empleado a cambio de realizar otro tipo de tareas donde no se pueda aprovechar su potencial o simplemente no se les dé bien.

Productos y servicios, son dos de las posibles principales fuentes de ingresos de las empresas de desarrollo de software. De hecho hay organizaciones centradas en productos, otras en servicios y otras donde conviven productos y servicios ya sean como elementos de negocio diferentes o bien conviviendo, es decir, se ofrecen productos y junto a ellos servicios o se ofrecen servicios y junto a ellos productos.

Desde mi punto de vista, una empresa dedicada al negocio del software, debe buscar siempre la consolidación de productos ya sea para comerciarlos directamente (con o sin servicios asociados) o para utilizarlos en sus procesos internos y mejorar aspecto tales como la productividad.

Los productos tienen la ventaja de que ya están desarrollados, son mejorables, eso es cierto, pero los costes de esos mantenimientos son relativamente bajos en relación a los ingresos que se pueden obtener de los mismos, a eso hay que sumarle que además los riesgos son mucho menores que la realización de la mayoría de los servicios, en resumen, se pueden tener altos beneficios con un índice de riesgo bajo.

Existen muchas estrategias posibles para obtener productos, que pueden ir desde el I+D, la adquisición de los mismos a terceras empresas, la utilización de software libre (en este caso el negocio estaría alrededor de la personalización de estos productos y/o la prestación de servicios de soporte), hasta el aprovechamiento de los conocimientos y desarrollos realizados en servicios para consolidar nuevos productos (digamos que en este caso el I+D estaría subvencionado por el posible cliente).

Dedicar parte de los recursos de una organización a obtener y comercializar nuevos productos, debe ser una línea estratégica de la misma, es cierto que personal con talento o con visión de negocio es capaz de desarrollar nuevos productos, pero el simple hecho de tenerlos no quiere decir que tengan un retorno económico, para ello se requiere crear una cierta estructura alrededor de los mismos o bien utilizar la misma estructura de la organización para sustentarlos, es decir, necesitan darse a conocer, por lo que tienen que entrar dentro de los procesos comerciales y de marketing de la organización, necesitan una estrategia, por lo que tienen que ser tenidos en consideración por los ejecutivos de la organización, responsables técnicos y responsables de negocio y necesitan equipos de trabajo alrededor de ellos para seguir progresando en su desarrollo ya sea como productos individuales y/o creando un ecosistema de productos alrededor de ellos.

Por tanto, tener en consideración los productos como una parte más del negocio de una organización, debe considerarse un objetivo estratégico (no quiero decir con esto que deba ser estratégico para una organización orientarse a productos, ya que lo mismo con los servicios les va muy bien o su estrategia de negocio va por otros derroteros) y por tanto darle al mismo el protagonismo que se merece y establecer objetivos parciales de obtención de productos y extracción de rendimiento económico de los mismos, es decir, una planificación y unos hitos a perseguir por los mismos.

La complejidad ciclomática es una métrica a tener en cuenta para evaluar la mantenibilidad, comprensión, testeabilidad y probabilidad de errores de una determinada aplicación.

Este término fue propuesto por Thomas J. McCabe en 1976 y tiene como una de sus características principales su independencia respecto a los lenguajes de programación (por lo menos, de los más convencionales), por lo que teóricamente podrían ser comparables aplicaciones realizadas con tecnologías distintas en base a su complejidad ciclomática. Digo teóricamente, porque además de la algorítmica las características propias del lenguaje de programación pueden influir en que sean más sencillas o no su inteligibilidad, mantenibilidad, etc… No obstante y en cualquier caso, resulta una aproximación muy a tener en cuenta de esos factores.

¿Qué mide la complejidad ciclomática? Pues el número de posibles caminos lógicos que tiene una aplicación. ¿Quiénes crean esos posibles caminos lógicos? Los métodos, las sentencias selectivas (if, case), sentencias iterativas (while, for), lanzamiento y tratamiento de excepciones (throw, catch), devolución de resultados de un método cuando no es lá última línea del mismo (return), operadores lógicos en guardas, etc…

Cuanto más caminos lógicos tenga una aplicación, una clase o un método más complejo resulta y por tanto, requiere un mayor esfuerzo desde el punto de vista de las pruebas unitarias (el número de pruebas unitarias para recorrer todo el código crece linealmente con la complejidad ciclomática (además de cumplirse eso, se verifica que: 1) la complejidad ciclomática es menor o igual que el número de casos de pruebas que se requiere para hacer cobertura de todo el código de la aplicación (téngase en cuenta que los else no suman complejidad ciclomática), 2) la complejidad ciclomática es mayor o igual que el número de casos de prueba que se requieren para verificar que realmente se “abren” los distintos caminos físicos)).

Por tanto, una baja cobertura de una aplicación viene a decir que existe una gran cantidad de código que no se ha verificado (utilizando esta estrategia), que se recorra, por lo que probablemente si no se ha recurrido a pruebas intensivas de la aplicación, muy probablemente se traduzca en errores evitables que se detectan posteriormente, incluso en producción).

También se requiere un mayor esfuerzo para la mantenibilidad y comprensión del código (¿cuántas veces nos hemos perdido en un mar de sentencias if anidadas?) y por todo lo anterior se incrementan las posibilidades de que existan errores, porque ¿cuántas veces nos hemos encontrado con que un problema en un método era provocado porque no se metía por la guarda correspondiente de una condicional o porque no entraba en un determinado bucle?, por lo que simplemente la mera experiencia nos indica que debe existir una relación entre la complejidad ciclomática y el número de errores de una aplicación.

Como la complejidad ciclomática es el resultado de los diferentes caminos lógicos que puede tener una aplicación es lógico que esta crezca conforme más extensa (en líneas de código) es una aplicación y por regla general una aplicación con muchas funcionalidades, grande, etc…, es más compleja, requiere mayor codificación y tendrá como consecuencia una mayor complejidad ciclomática (de esta manera existirá prácticamente una relación entre una clasificación de las aplicaciones por líneas de código y una clasificación de las aplicaciones por complejidad ciclomática, es importante señalar que no tienen por qué conservar el mismo orden aunque sí más o menos estarán por el mismo entorno, es decir, la segunda aplicación con más líneas de código, puede ser la cuarta en complejidad ciclomática o la quinta aplicación con más código, la segunda en complejidad. Por tanto este tipo de complejidad es inherente a las aplicaciones y existe por el simple hecho de la existencia de las mismas y por tanto, aplicaciones con envergadura se traducen en aplicaciones complejas de mantener y eso es consecuencia de su complejidad ciclomática intrínseca.

Independientemente de que una codificación eficiente puede eliminar caminos lógicos innecesarios, existe un límite y es el que da la propia dinámica de funcionamiento de un sistema de información que provoca que se codifique su comportamiento en algoritmos que como se han comentado anteriormente pueden ser complejos. Cuando se aproxima a este límite, lo más que se puede hacer es utilizar la complejidad ciclomática para determinar si determinados métodos o clases son demasiado complejas y requerirían ser analizadas de cara a dividirlas en otras más simples, mejorando así la mantenibilidad de las mismas.

Existen algunas clasificaciones basadas en rangos de complejidad ciclomática que determinan cuando es recomendable hacer la simplificación de determinadas clases y métodos y también hay casos de éxito de la aplicación de los mismos en algunas compañías.

En muchas ocasiones a simple vista se puede determinar si un método o una clase tienen una complejidad ciclomática alta, no obstante, esta tarea puede ser agotadora si la aplicación a analizar es muy grande, por ese motivo, lo mejor es delegar esa función en analizadores estáticos de código, como es el caso de Sonar, que permite obtener métricas de la complejidad ciclomática tanto a nivel de aplicación, como de clases y de métodos y utilizando su implementación de funcionalidades de drill down ir de datos más generales a información más de detalle.

Como todas las métricas de ingeniería del software, no hay que tomarse los resultados de la complejidad ciclomática al pie de la letra, sino saber interpretar qué es lo que están diciendo y tomar medidas para reducir el impacto de dicha complejidad en la aplicación (mayor cobertura de pruebas unitarias) y para tomar decisiones de revisión de la codificación en métodos y clases complejos y su posible simplificación en otros más sencillos.

Otra aplicación del principio de Pareto lo tenemos en la Revelación de Sturgeon, derivado de una cita del autor de Ciencia Ficción americano Theodore Sturgeon que viene a decir: “Nada es absolutamente de esa forma”. A partir de ahí se generó la Revelación de Sturgeon cuyo enunciado es: “El noventa por ciento de la Ciencia Ficción es basura, bueno entonces, el noventa por ciento de todo es basura”.

Así de golpe la Revelación de Sturgeon puede parecer muy fuerte, porque de cumplirse vendría a afirmar por ejemplo que el 90% de los canales de la TDT son basura, que el 90% de la programación de televisión es basura, que el 90% de la política es basura o que el 90% de este blog es basura, este…, mejor no seguir dando ejemplos.

Este guiño que nos da la Revelación de Sturgeon como podemos apreciar no es más que una extensión más del Principio de Pareto y si bien podría considerarse como una curiosidad más, no está de más reflexionar un poco con ella teniendo en cuenta como afrontamos determinadas cosas, como también conviene reflexionar de vez en cuando teniendo en cuenta el Principio de Pareto.

El principio de Cargill también conocido como regla del noventa-noventa, se puede considerar como una aplicación de principio de Pareto y viene a expresar básicamente que es imposible el cumplimiento de la planificación de un proyecto o por lo menos las previsiones económicas y de esfuerzo del mismo ya que enuncia (y no hay ningún tipo de error al poner los porcentajes) que “el primer 90% del código ocupa el 90% del tiempo de desarrollo. El 10% restante del código ocupa el otro 90% de tiempo de desarrollo”.

Digo que no es ningún error porque el hecho de que el tiempo de desarrollo no sume 100% está hecho a posta. Este principio viene a indicar que poner a totalmente a punto una determinada aplicación llegado a un determinado grado de avance en el proyecto es treméndamente costoso y una de las principales causas de que no se cumplan las planificaciones en todos los sentidos (tiempo, esfuerzo, etc…).

Como en el caso del principio de Pareto, aqui la clave es saber cuándo se llega a ese 90% “mágico”, ya que a partir de ese momento el proyecto se pone muy cuesta arriba. También, como sucede con el principio de Pareto la habilidad, experiencia y metodología (además de as circunstancias del proyecto) de los responsables y del equipo de proyecto tienen mucho que ver en las posibles desviaciones que ocurran en el mismo.