sábado, 26 de junio de 2021

A 20 años de la creación del manifiesto ágil


En febrero del 2001, varios programadores algo ya hartos de la forma de desarrollar sistemas tradicional y queriendo mejorar por un lado calidad del software y los sistemas y por el otro (y sobretodo) reivindicar el valor de la figura de programador crearon los que se conoció como manifiesto ágil.



Las metodologías de desarrollo de software nacido de la adopción de otras metodologías, pertenecientes a industrias y mercados que llevaba vigentes muchos antes que la creación de sistemas. A pesar de eso el desarrollo del software y su alcance ha aumentado de forma más rápida que cualquier otra industria. Realmente se podría decir que las necesidades del desarrollo de software, han crecido más que la capacidad de adaptarse de los desarrolladores para hacer software.

Originalmente (o más bien en la década setenta), cuando se vio que el desarrollo del software iba a ser imprescindible en el futuro (de una forma u otra) se comenzaron a usar varias metodologías y procesos para la construcción de este. Hay que considerar, que tanto el desarrollo del software, así como el mismo hardware eran recursos muy caros, y frecuentemente de difícil acceso.

Antecedentes clásicos relacionados con la programación



  • Creación de FORTAN en 1954, con un enfoque matemático y científico practico.

  • Creación de COBOL en 1960, con un enfoque hacia los negocios y una clara intención de vender las ventajas de programación a las empresas. Fue un lenguaje usado en los bancos de forma casi exclusiva hasta principios de los 2000.

  • Creación de BASIC en 1964, creado con intención de hacer más humana y accesible los conceptos de programación. Fue extremadamente popular en los 80, donde prácticamente cada ordenador personal tenia instalo una versión de BASIC

  • Gestación de la programación estructurada, durante toda la década de los 70: Una nueva visión de la forma de programar que abogaba (entre otras cosas) por la eliminación de programación goto.

  • Creación de Pascal en 1969: El lenguaje de programación que mejor implemento la programación estructurada, y uno de los más limpios y claros existentes. Tuvo varias evoluciones y actualmente es raro verlo implementado de forma empresarial.

  • Creación de C en 1970, A fecha de hoy una de los lenguajes más importantes, y inspiración de multitud de lenguajes actuales.

  • Creación de Unix en 1970: Uno de los sistemas operativos mas importantes y igualmente fuente de inspiración para multitud de sistemas operativos.

  • Creación de C++ en 1983: Extensión del lenguaje C, con multitud de nuevas características, además del uso de programación orientada a objetos, extendiese su uso bastante en los 80 y sobre todo en los 90, se en la base de multitud de sistemas y desarrollos.

  • Creación de SQL en 1986, Estándar para realizar consultas a las bases de datos, independiente del motor de esta y de los sistemas de la consulta. Se extendió su uso masivamente en los 90. El hecho de proporcionar una abstracción entre los datos y los programas, fue un hito importante, en una nueva concepción de cómo debieran estructurarse los sistemas.


Las necesidades y lenguajes iban evolucionando en los 70, 80 y 90. También debemos entender que realizar software era complicado, muchas veces debiendo aprender sobre la marcha e intentando adaptar métodos y formas propias de otras ramas, que no tenían por qué funcionar en el desarrollo de software.

Antecedentes que ocurrieron en los años 90



  • Implantación de Windows: Si bien Windows se gesto creo en los 80, su versión Windows 95 fue una atentica revolución, tanto en nivel mediático como en la amplitud de los hogares que tuvieron este sistema instalado en sus computadoras.

  • Regreso de Steve Jobs a Apple: Después de su despido en los 80, Steve Jobs regreso en 1997 a una Apple, que había perdido completamente su brillo y empuje inicial. Después de ciertas alianzas (algunas algo muy sorpresivas como con Microsoft) y de cambiar la visión y su enfoque comercial, tuvieron (y tienen) un gran impacto en la computación domestica, celular y la industria del entretenimiento de las dos siguientes décadas.

  • Programación Extrema (XP): Creada a finales de los 90, y predecesora inmediata de las metodologías agiles. Implica (entre otras cosas) la simplificad del código, la comunicación efectiva entre los codificadores y el cliente y de la importancia de las pruebas unitarias

  • Java: Java es un lenguaje/arquitectura creada en el 1996. En los 90 era muy popular el uso de C, C++ (y ASM), para la generación de programas y sistemas embebidos, pero tenía varios problemas y es que cada sistema operativo y dispositivo tenían su propias librerías, tamaños de números (y punteros), gestores de memoria y de hardware, lo que hacía que un programa escrito en C (o C++), fuera incompatible con otro. El nacimiento de Java prometía que un programa sería compatible con multitud de dispositivos, fue creado de cero con una inspiración clara de de C++, pero quitando todo lo que hacía difícil y propenso a fallar, con la intención de simplificar el desarrollo de software. En las siguientes décadas fue un lenguaje muy importante en el desarrollo WEB, en la renovación de los sistemas empresariales (principalmente en el sector bancario), y de diversas formas en los dispositivos móviles, igualmente (y a aunque no fueron los primeros en hacerlo), en el uso de componentes desplegables e instalables fácilmente desde internet. Popularizo a que fuera un lenguaje en que siempre encuentras una herramienta (o frameworks) para resolver casi cualquier problema.

  • Visual Basic: Microsoft tiene una relación muy estrecha con BASIC, fue uno de los primeros programas que vendió y ha incluido durante años versiones de Basic en sus sistemas operativos (GWBASIC, QBASIC, QuickBASIC). Visual Basic Clásico estuvo disponible desde el 92 hasta el 98, donde fue adoptado por muchas empresas para la creación de software, como puntos positivos presento un IDE muy sencillo de manejar, una serie de componente gráficos ampliable y fáciles de implementar, y sobretodo un esquema de acceso a base de datos unificado llamado ADO, común para cualquier motor de base de datos.

  • Efecto 2000: Originalmente y al ser la memoria un recurso limitado se usaban solo dos dígitos para representar el año de las fechas, por ejemplo 80, era 1980, esta circunstancia provocaría que los sistemas asumieran que él año 2000, era erróneamente el años 1900, provocando problemas en el manejo de las fecha, los plazos y el tiempo. Así se crearon muchos sistemas y lenguajes de programación. Entre estos lenguajes estaba COBOL, que era además el más usado en los sistemas bancarios (donde las fechas son realmente muy importantes), si bien se parcharon con más o menos dificultad los sistemas (al final el tan anunciado efecto no fue para tanto), Provoco como efecto colateral que hubiera una migración hacia otras tecnologías y sistemas, además de otras visión de cómo como debiera consumirse el software y las aplicaciones siendo más móvil, mas des localizado, interconectado y sobretodo mas usando entre la población general, convirtiéndose a fecha actual, en algo imprescindible en sus vidas

  • Internet y la WWW: Aproximadamente en el 92 se crea la WWW y unos años después se crea comienza a difundir domestica internet a través de un boom de proveedores comerciales. Inicialmente el contenido era tremendamente estático, pero años después el contenido fue evolucionado hacia algo más dinámico e interactivo, conocido como la Web 2.0, en la que el usuario es el centro de la información, creándose contenido por y para él.

  • Linux y el auge del Open Source: El concepto del código abierto se creó en los 80, con la finalidad de tener acceso al código fuente y tener el derecho de modificarlo y distribuirlo libremente, el movimiento tuvo un auge real (y comercial) por la creación del Linux (que es un kernel y no un sistema operativo como tal), por Linus Torval en el 91. A finales de los 90 y a principio de los 2000, la combinación de Linux y GNU se hizo extremadamente popular para los servidores y para una nueva visión de la informática basada en la nube. En la década pasada (los 2010), empresas que clásicamente se habían opuesto al software libre, como Microsoft entraron de lleno en este modelo y visión de desarrollo.

  • Patrones de software: Los patrones de software son “formulas” conocidas, prácticas y probadas en los que un programa (un código fuente) funciona de forma exitosa. Son “recetas” que si las seguimos tendremos éxito en la solución de un problema especifico. En el 90 se publica el libro Gang of Four (GoF), y a partir de los mediados de los 2000 se populariza el uso de patrones (quizás de una forma exagerada en algunos casos).

Creación del manifiesto ágil


Los preámbulos anteriores nos dan a entender que en un futuro próximo la informática y los sistemas, se iban a convertir en una de las partes centrales de nuestra vida (personal y laboral), prácticamente la totalidad de los negocios y empresas a lo largo del mundo esta gestionados por un sistemas software, y ¡qué decir de la cantidad de dispositivos móviles que existen por persona!

La situación era que a finales de los 90, y con pensamientos y técnicas obsoletas de desarrollo de software era imposible llegar cumplir las necesidades presentes y futuras del mercado. Es más, la falta de compresión de la labor exacta del programador y la importancia e impacto de su trabajo (además de un exceso de profesionales técnicos que se dio debido al efecto de la burbuja .com y su futura explosión) hizo que se crearan sentimiento de desasociacion, falta de pertenencia (a la empresa y sus objetivos) por parte del informático, y un sentimiento de frustración por parte del empresario y gestor del negocio que no obtenía lo que quería.

El 12 de febrero de 2001, diecisiete programadores (algunos muy importantes a futuro), se reunieron con la intención de mejorar la visión del desarrollo de software. En cierto sentido están hartos de las metodologías pesadas, llenas de documentación, burocracia y protocolos que limitaban el tiempo y el impacto de lo que mejor sabían hacer, crear software.

Lo que crearon es conocido como el manifiesto ágil, que tiene las siguientes premisas básicas.

  • Individuos e interacciones sobre procesos y herramientas

  • Software funcionando sobre documentación extensiva

  • Colaboración con el cliente sobre negociación contractual

  • Respuesta ante el cambio sobre seguir un plan


A lo que se refiere el manifiesto es que si bien los elementos de la derecha son importantes, los elementos de la izquierda deben estar por encima.

Individuos e interacciones sobre procesos y herramientas


Si hay algo que odie mas en el desarrollo de software es la burocracia, a veces olvidamos que los proceso fueren creados para facilitar el trabajo, para ser un reflejo del las tareas y sus pasos para resolver problemas, y sin embargo parece que el trabajo fue creado para “cumplir” el proceso.

Decía Sun Tzu, en el arte de la guerra, que nadie espera una orden para apagar un fuego. Las necesidad se imponen sobre los procesos y los individuos resuelven necesidades.

A veces hasta el más mínimo cambio o mejora se ve “ahogada” entre una montaña inmensa de procesos burocráticos, correos, documentos, validaciones y “visto Buenos”, que hace que francamente sea más costosos resolverla, que dejarlo pasar.

La iniciativa individual y colectiva se ve detenida por procesos que se interponen por ser “procesos”, más que por ser necesarios.

Muchas veces el proceso crea un cerco de “responsabilidad” que nos hace indiferentes a las “responsabilidad” y necesidades de nuestros compañeros, creemos que nuestro trabajo es seguir unos procesos específicos y asignados a nosotros, y no comprendemos que nuestro trabajo solo tiene sentido al integrarse con el trabajo de nuestros compañeros.

Recuerdo un proyecto cuando ejercería de programador en que el líder de proyecto, proporcionaba los requisitos del sistema, el sistema en si debía conectarse con otro sistema que esta construyendo otro equipo (con su propio líder de proyecto) , la comunicación entre equipos era prácticamente inexistente, todo se tenía que hacer a trajes del líder del proyecto y mediante documentos formales, después de muchas horas extra, trabajar sin tener claro el objetivo y muchos cambios de definición, el resultado al momento de las pruebas, fue que nada encajaba con nada y había que rehacer mucha partes tanto desde el lado del código fuente, como desde el lado del diseño. Todo esto se podría haber evitado dan prioridad (y reconociendo) a los integrantes de cada equipo y fomentando la comunicación entre ellos en lugar de seguir a raja tabla los procesos.

Software funcionando sobre documentación extensiva


Uno de los motivos que ms me ha tocado vivir y por los que un software no sale de la forma deseada o en el tiempo requerido, es querer definirlo y documentarlo completamente antes de construirlo.

En las metodólogas pesadas el orden donde ocurren las cosas es muy claro, primero el análisis, después el diseño y posteriormente la construcción y la pruebas.

También una de las frases que más se repiten en el desarrollo de software es “No hagas nada, sin tener claro todo lo que vas a hacer”. La verdad es que casi nunca podemos tener claro al 100% lo que vamos a hacer.

Posiblemente lo anterior funcione en otro tipo de proyectos de ingeniera, pero no en desarrollo de software.

Lo cierto que es que un problema no se entiende nunca completamente hasta que está resuelto.

Por norma general un cliente siente que tiene una necesidad (una carencia que necesita ser resulta), pero es muy raro que sepa cómo resolverla, e incluso que sepa de forma precisa que necesita. El desarrollador por otro lado desconoce la naturaleza del negocio del problema que necesita resolver.

La programación ágil, apuesta por comenzar a programar cuando antes, buscando hacer entregas que puedan estar productivas cada pocas semanas, cada entrega se acerca más a la solución final, y no permitirte no tener que avanzar mucho antes de darnos cuenta que vamos en mal camino, porque créenme no hay nada peor que estar meses en un proyecto y al momento de entregarlo ver que no le sirve al cliente, y que el trabajo de un equipo fue en vano, no generando satisfacción en ninguno de los implicados.

Colaboración con el cliente sobre negociación contractual


Una vez tuve que trabajar con una empresa que se contrato para desarrollar un producto web (es decir en este caso nosotros éramos el cliente). La relación con la empresa fue complicada, porque ellos a la vez contrataron a unos programadores externos (de otra empresa) para resolver el problema, con lo que había una seria de escalones burocráticos y contractuales entre nosotros y los que realmente hacían la pagina web.

Una de las discusiones que mas me saco de quicio, fue cuando les pedí que limitara la entrada de un cuadro de texto, para que fuera acorde con el tamaño del campo relacionado en la base de la base de datos, la empresa quería cobrarnos un precio adicional por que eso no está especificado en la definición, yo alegaba que no era necesario que se lo especificamos por que era un requisito no funcional que debería haberse detectado por ellos y no por nosotros. Total al final fue más fácil pagarles, y nunca volver a trabajar con ellos.

El caso es que el trato no fue beneficios para ninguna de las partes, ni para nosotros que no obtuvimos el producto que necesitamos, ni para la empresa desarrolladora ya que no volvimos a colaborar con ellos.

La programación ágil propone un acercamiento constante con el cliente, se asume que no se comprende al cliente a través de definiciones, sino de prototipos funcionales, se colabora con el cliente para poder crear un software que sea satisfactorio.

Evidentemente en este punto surgen dudas sobre cuál es el límite de aceptación de lo que si hay que programar, y lo que no, sobre todo por motivos de recursos.

Y aquí hay tener claro que estamos resolviendo una necesidad en concreto, todo lo que nos acerque a esa resolución es positivo, lo que nos aleje es negativo. Por ejemplo se deben evitar y postergar en la medida de los posible, soluciones que parecen mágicas, para casos extraordinarios y inverosímiles que rara vez pasan, y centrarnos en los que pasa la mayoría de las veces. Esto se relación con el principio de paleto, que resumiendo es que el 80% de la funcionalidad de un sistema, es suplicada por el 20% por cierto del código de dicho sistema.

Cuando un cliente ve su software funcionando se olvida rápidamente de idea, casos de uso y caminos extraños para su sistema que no llevan a ninguna parte. Cuando está definiendo todo completamente al principio del proyecto, se pierde en callejones que no llevan a nada, y que en la práctica requieren un enorme esfuerzo de desarrollo y recursos, para el beneficio real que producen.

Respuesta ante el cambio sobre seguir un plan


El cambio esta inherentemente ligado al desarrollo del software, sobre todo al desarrollo de software empresarial. La velocidad con la cambian los mercados y los consumidores hacen que el software deba adaptarse rápidamente para por tener valor.

Pero en el desarrollo de un sistema especifico, hay que entender que cuando más se avanza en la construcción de un sistemas, mas se comprende las necesidades y eso lleva a cambios, y adecuaciones, cuando mejor sea la arquitectura de un sistemas, mas fácil es esto. Esto es siempre así, se realicen se realice en un escenario ágil o no.

Como vemos todos los puntos están relacionados entre sí, el disminuir el análisis inicial y generar entregas continuas que generen valor, no solo nos ayuda a resolver más rápido el problema y a comprenderlo menor, sino además a descartar las ideas iniciales que pudiera tener el cliente, y que realmente no solucionarían su problema. Aunque parezca una contracción las entregas incrementales y un acercamiento al problema por partes minimiza los cambios que hay que realizar en el proyecto. En una metodología pesada los cambios serian solicitados al final, cuando la fecha de entrega esta sobre nosotros, y las modificaciones a realizar pueden tener mayor impacto.

Perspectiva a 20 años del manifiesto



Es estas dos décadas, la tecnología no ha dejado de evolucionar y de ser adoptada masivamente, tenemos la implementación casi total de internet, la web 2.0, las redes sociales, la conexión las 24 horas y la demanda en línea de servicios, entre otras cosas.

Las metodólogas agiles han sido ideales para conseguir esta unión entre tecnología y sociedad.

Han surgido nuevos enfoques de desarrollo de software, y herramientas maravillosas, que nos permiten comunicarnos más fácilmente, y de diversas formas.

Pero también existieron puntos negativos, si bien el manifiesto apareció como una reivindicación de la figura del programador y su importancia dentro del desarrollo de software, poco a poco se uso la palabra ágil para definir tareas de gestión y administración de diversa índole (y en muchos conceptos), quedando la palabra “hueca” en sus significado, casi convirtiéndose en una idea genérica, abstracta y vende humos, más que en una cosa real y practica.

Hay considerar siempre al programador, su experiencia, y su potencial, como le elemento central y principal del desarrollo de software ágil, y la clave del éxito para crear software de calidad.




Si te ha gustado la entrada, ¡Compártela! ;-)

sábado, 13 de marzo de 2021

Regla Nº20 No depender del llamador, ni de la implementación (evitar acoplamientos)

Frecuéntenme, en nuestra vida personal y laboral, cambiamos nuestro comportamiento y actitud según con quien estemos hablando con la finalidad de poder conseguir y resolver las necesidades o circunstancias que se nos plantean. No es lo mismo (o no diera) que un doctor este dando una clase sobre alguna enfermedad que le este comunicando dicha enfermedad a un paciente, ni tampoco es igual como hablamos con nuestros padres o hijos a como hablamos con nuestros compañeros de trabajo. Por otro lado tampoco recibimos la información de la misma forma de personas que apreciamos y conocemos que de desconocidos, “modulamos” nuestro comportamiento según con quien estemos hablamos.

Ese punto de vista, tan normal en interacciones humanas, supone un problema a la hora de implementar software.

Una clase no debe cambiar su comportamiento según quien la consume, igualmente el consumidor de una clase no debiera saber cómo esta implementada internamente dicha clase, para poder consumirla de forma adecuada.

Estos días he tenido que dar mantenimiento a un sistema, un sistema que es consumido por otros, bastante viejo, ¡pero no tanto como para los problemas que me he encontrado!


Había que agregar un nuevo comportamiento, hasta ahí todo normal, como ya hemos hablado en varias circunstancias (Regla N°1: Va a cambiar), el software se modifica contantemente para adaptarse a negocio cambiante. ¡El problema es que básicamente toda la lógica de negocio estaba en una misma función, con multitud de if anidados  y ramificaciones! (Regla N°18: evita el código espagueti). No solo era difícil de entender, si no extremadamente delicado de modificar, cada vez que se moviera algo, podría afectar de cualquier forma a los consumidores, para colmo el sistema reacciona de forma diferente si lo llama un sistema o si lo llama otro, es decir la clases tiene que reconocer que quien le está llamando, para saber cómo debe comportarse.

 Lo anterior resume un gran problema de acoplamiento y falta de cohesión, lo que está ligado directamente a la dificulta de mantenimiento del software (lo que a su vez es ligado a costos económicos, tiempo, y muy posibles desastres productivos)

Acoplamiento


El acoplamiento entre dos clases es una medida que indica cuanto depende una clase de otra, específicamente cuando depende de su implementación interna. Cuando mas acoplamiento, peor es nuestro código, cuando mas desacoplado este, mas fácil de mantener.

Idealmente una clase solo se debiera relacionar con otras a través de la definición de los métodos, el cómo hagan esos métodos sus funciones con cosas que nos deben preocupar. Lo anterior se ve claramente cuando podemos sustituir la referencia de una clase, por la referencia a una interface, y cambiar la clase que lo implementan sin mucho (o ningún) impacto.

Si podemos cambiar una clase consumida por otra, sin realizar cambios en el consumidor, hemos conseguido un nivel aceptable de desacoplamiento.

Con respecto a no depender de la “implementación interna de una clase”, se dan varios escenarios que demuestran un alto acoplamiento:

  • Cuando la clase consumidora debe almacenar información que no le sirve de nada, salvo para consumir otra clase. Aquí es donde se ve un defecto de diseño, puesto que debiera ser la clase consumida la que debe contener sus propios datos, sin forzar a los consumidores a hacerlo.

  • Las clases se comunican de forma estrafalaria y poco comprensible, por ejemplo se usan cadenas de texto, para comunicar cosas que claramente no lo son, como números, fechas u objetos. El ejemplo de la fecha es muy común, se pasa una fecha en formato texto, pero hay muchas formas de expresar una fecha por texto, no es lo mismo el 1 de Febrero (01/02/2021), que el 2 de Enero  (02/01/2021), pero según el formato de la fecha podría ser una u otra. La única forma correcta de pasar una fecha es mediante un objeto de tipo fecha.

  • Los métodos de una clase deben llamarse en un orden determinado para que funcionen, si no dan resultados inesperados, cada métodos debe hacer algo en concreto, y debe hacerlo independiente en el orden en lo que se les llama, si no puede hacerlo por algún motivo, debe lanzar una excepción (es mejor no hacer algo que hacerlo mal).

    Una situación reciente que me acaba de pasar, tenía que usar un control grafico de terceros, un datagrid para mostrar tabla en pantalla (en una aplicación de escritorio). Una vez mostrada la información en pantalla había que cambiar el valor de una celda en particular, pero por algún motivo extraño, la celda tenía que estar visible, si no ignoraba la instrucción para cambiar el valor (sin producir ningún fallo), así que la solución fue posicional visualmente el componente en la fila requerida y cambiar el valor, y después volver a la fila que estaba el usuario actualmente (que pudiera ser otra), pero esta daba otro problema como un parpadeo innecesario en el programa, eso se solucionaba desactivando el control antes de realizar la operación. Al final el programa consumidor, se lleno de instrucciones que hay que ejecutar antes (y después) de cambiar el valor de una celda, y no se comprende muy bien porque es así, y desde luego si se cambia el componente todo ese código esta de mas.

  • La clase consumida cambia su comportamiento según quien lo está consumiendo, ese es el acoplamiento más rocambolesco de todos. Es decir si la clase A, y B consumen la clase C,  la C cambia su funcionalidad según quien la este llamando.

    Para comenzar, de por si suena muy extraño. Una clase debe tener una misión sea cual sea, debe ser clara y concisa y realizarla de la misma forma independientemente de quien le este llamando.

    Que modifique su comportamiento según el llamador, suena a que la clase no tiene un diseño bueno orientado a objetos, donde se usa una serie de estructuras condicionales gigantescas, en lugar de usar herencia y polimorfismo.

    Cuando se modifica la clase consumida, se puede afectar a la clase consumidora obligándola también a  ser modificada, si hay más de un sistema que consuma dicha clase, habrá que cambiar todos y cada uno de ellos con un consumo en tiempo y recursos. Si además los sistema a modificar son consumidos por otros sistemas, pueden desencadenas una cadenas de modificaciones enorme y costosa.

    Es posible, no obstante, que debamos modificar el acceso a la funcionalidad en cuestión de permisos, es decir dichas componente tendrá acceso a alguna funcionalidad y otra no. Un ejemplo muy típico de esto es cuando las aplicaciones se logean con facebook y nos muestra un mensaje que nos dice a que tendrá acceso la pagina web donde nos logeamos, puede ser al perfil público y a nuestro correo, otra quieren acceder a nuestra lista de contactos y otra incluso a publicar en nuestro nombre. Pudiera parecer que se está creando un acoplamiento en el que facebook devuelve información según la aplicación que se lo pida pero no cierto. Hay una capa de seguridad adicional que se encarga de generar un “token” con ciertos permisos hacia facebook y la aplicación web consumidora usara este token, pero en ningún caso facebook lo hará por que la pagina web que lo consume sea una o la otra, sino porque se solicito unos permisos y se trabaja con la autorización previa de con dichos permisos.

  • Una medida del acoplamiento de una clase es la cantidad de clases adicionales que consume. Puede ser que parezca que no dependa de la implementación interna de cada uno de los componentes que consume pero cuando una clase consume muchas clases, comienza a perder su identidad y a depender de elementos externos para realizar su tarea,  lo que al final repercute en un alto acoplamiento. En una aplicación empresarial se supone que una clase solo debe consumir las clases que estén en un nivel más por debajo que el suyo con lo que sería bastante raro que consumiera muchas clases.


Cohesión


La cohesión posiblemente sea unos de los conceptos que son más difíciles de explicar y comprender acertadamente de la ingeniera de software.

A veces se explica simplemente como que todo lo que pertenezca a mismo ámbito o tenga que ver entre sí debe estar junto. Así agrupamos los métodos en clases, las clases en namespace (o paquetes), los namespace en componentes y los componentes en sistemas.

Pero lo anterior es solo organización, agrupar las cosas según su semejanza y naturaleza, para que sea más sencillo encontrarlas y usarlas pero no define el nivel de cohesión como tal.

  • Una clase se debe componer de datos, representados por atributos (o propiedades) y por funcionalidad que usa esos datos. ¿Qué tantos atributos debe usar cada función o métodos?, en principio debiera usar todos, ya que los atributos es lo que representa el estado del objeto y cada función debiera cambiarlo (por que debiera hacer algo con el objeto), en la medida que use mas métodos y mas atributos de la clase, la misma clase esta mas cohesionada.

  • Si en una clase, una  colección de métodos usa unos atributos y otra colección de métodos usan otros atributos diferentes entonces la clase no tiene cohesión y realmente son dos clases que se han convertido en una sola, debiéndose separar. Si esto lo tenemos varias veces, lo que tenemos es lo que se llama una “clase gorda”, una clase con muchas cosas dentro sin nada que ver entre sí y que posiblemente solo sea una colección de métodos, que no son parte de una objeto con identidad. Posiblemente las  clase tenga más de un motivo para cambiar y dichos motivos no tengan nada que ver entre sí (lo que hace que no se cumpla el principio de “responsabilidad única”).

  • De igual manera si una clase consume en exceso a otra clase, y sobretodo usa sus atributos (a atreves de sus propiedades o métodos) de forma constante pareciendo que no tiene ningún sentido una clase sin la otra, estaríamos en un caso de “clase famélica”, y posiblemente debiera ser una sola.

  • Lo anterior vuelve a pasar con los namespaces (o paquetes). Estos deben componerse de clases que se consumen o se relacionan entre sí (por medio de mecanismos de (herencia, agregación, composición, colección u otros). También debe evitar incluir clases que no se usan de ningún modo. Esto hacen que las clases sea cohesionadas y tengan un objetivo, fácilmente identificable.

  • Los namespaces se agrupan en componentes. Los componentes igualmente tiene un objetivo común y identificable, pero es una agrupación “física”, en forma de elemento reusable como una librería, un jar de java o un servicio.

  • Los sistemas son agrupaciones de uno o más componentes que interactúan entre sí para resolver una serie de problemas de negocio a través de flujos e interacciones con el usuario.


La cohesión nos ayuda a que los problemas que tenemos que resolver sean pequeños, conexos y fácilmente escalables.

Relación entre cohesión y acoplamiento


Cohesión y acoplamiento son dos valores tan relacionados que siempre se van a encontrar juntos.
  • Si aumenta la cohesión disminuye el acoplamiento.

    Si tenemos juntos los elementos que si deben estar juntos, el acoplamiento debiera disminuir porque la organización de los mimos elementos nos lleva a consumir solo los que necesitamos, con cierto control y estructura.

  • Si disminuye la cohesión aumente el acoplamiento.

    Lo contrario de “tener todo en un lugar”, es “tenerlo todo junto”. Si tenemos todas las clases a la mano, es normal que comencemos a usar clases simplemente porque están accesibles, mezclando cosas que poco o nada tiene que ver, y eso aumentaría el acoplamiento

  • Si disminuye el acoplamiento aumenta la cohesión.

    Si diseñamos nuestro código disminuyendo la cantidad de clases que consumimos, no dependemos de su implementación interna y nos comunicamos a través de interfaces, quiere decir que tenemos un nivel de organización y agrupación lo suficientemente algo.

  • Si aumenta el acoplamiento disminuye la cohesión.

    Si nuestra clase comienza a consumir clases de diversa índole y sin ningún control ni estructura, es forzosamente necesaria tenerlas accesibles y tenerlas accesibles le fuerza a que tenerlas lo mas “cerca” posible, disminuyendo considerablemente la cohesión.




Si te ha gustado la entrada, ¡Compártela! ;-)

Reglas de la Ingeniería de software (índice): https://desdelashorasextras.blogspot.com/2019/12/reglas-de-la-ingenieria-de-software_15.html

sábado, 28 de noviembre de 2020

Modelos de trabajo para un desarrollador de software

Este articulo trata sobre las distintas formas y modelos de trabajo que como desarrolladores de software podemos desempeñar. Está escrito desde un punto de vista personal, repasando y exponiendo modelos de trabajo en los que de una forma u otra me he visto involucrado. Hay que considerar que dependiendo de cada país estos modelos pudieran cambiar e incluso ser más laxos o rígidos que otros en el cumplimiento de normas y leyes.


Existen formas explicar que es el trabajo, podemos considerar que es la labor y tareas que realizamos con la intención de recibir una remuneración económica.

Existe la falsa creencia que debemos ganar de forma proporcional por los conocimientos que tenemos, así que si nos hemos esforzado mucho y hemos estudiado deberíamos ganar mucho dinero, y si bien eso suena lógico y hasta justo, no es cómo funciona el mercado laboral. Los conocimientos y los estudios que tengamos, son solo una herramienta que vamos a usar en nuestra profesión, pero lo cierto es que en el mercado se nos pagara por lo que “hagamos”, no porque lo “sabemos”. Se cumplirían varias reglas:

  • Si existe mucha gente que sepa hacer lo mismo que nosotros (independientemente si para saber hacer eso mismo hemos “estudiado” mucho), cobraremos poco.

  • Si existe poca gente que sepa pueda lo mismo que nosotros, cobraremos mucho.

  • Si existe poco gente que pueda hacer lo mismo que nosotros, y lo que podemos hacer no es de interés para otras personas, puede que tengamos un hobby interesante.

Lo anterior es una simplificación de la ley de la oferta y de la demanda, aplicada a nuestra profesión.

Pero al margen de esa regla tenemos varios problemas adicionales que influyen con respecto a los sueldos que cobramos en nuestra profesión:

  • Nuestro trabajo llevaba décadas en alza, es decir la demanda de informáticos siempre ha crecido, particularmente esta creció de forma más rápida en los 90 y a principio de los 2000, donde además hubo una crisis llamada burbuja puntocom (además de otras crisis inmobiliarias debido a especuladores que puso varias veces en jaque a la economía mundial). Todo esto hizo que en la actualidad haya muchos informáticos y desarrolladores de software.

  • A pensar del anterior, los sistemas que desarrollamos no son siempre valorados como se debiera, debido a varios motivos; uno de ellos es que parece que hay una reticencia a que un usuario comprenda exactamente qué es lo que hacemos. Muchas profesiones con las que interactuamos como adultos se comprende “intuitivamente” (aun de forma superficial), comprendemos que hace que hacer un contable, un médico o un abogado, pero a frecuentemente (para una persona que no se dedica a los sistemas informativos) comprender que hacemos realmente los desarrolladores de software. Por otro lado la creación de sistemas generalmente crea un valor indirecto, es decir se crea un sistema para que sostenga un negocio, el cual es que el genera el valor directo (el dinero en sí). Por eso es difícil relacionar el costo de un sistema, con los beneficios económicos que produce.

  • Por otro lado la programadores somos personas realmente muy entusiastas con nuestra profesiones. Disfrutamos programar, lo cual es bueno en un sentido, pero malo en otro, ya que no alcanzan a valorar por si mismos el costo de su trabajo, ya que este suele ser gratificante.

  • Por último, y de forma más trágica, parece que nuestra profesión es la única en la que experiencia y madurez no significan mayores posibilidades de conseguir un trabajo. Nuestro trabajo, esta asociado con el cambio, la evolución, y de cierta forma con la juventud. Muchas empresas descartan contratar a gente a partir de cierta edad. Esto puede ser por varios motivos, pero el exceso de informativo graduados, la renovación tecnología constantes, y que en general es más barato contratar a una persona sin experiencia excesiva, hacen que las contrataciones sean muy desfavorables para la gente madura, con ya amplia trayectoria en el mercado laboral.

Hay que tener en cuenta los dos escenarios (la ley de la oferta y la demanda y las particularidades de nuestra profesión), para conseguir un salario digno y justo, y que podamos garantizarnos un ingreso fijo y constante en nuestro futuro.

Consultorías de software


Las consultorías son empresas expertas en el desarrollo de software que ofrecen su accesoria a otras empresas (de otros rublos), para la implementación adecuada de sistemas en sus negocios.

Esa “asesoría” puede tener muchas facetas, desde lo que es realmente una “asesoría”, incluyendo la venta y personalización de sistemas “prefabricados”, que se adapten a las necesidades del cliente hasta la creación de sistemas a medidas.

También es posible que el modelo de consultaría se acabe pareciendo mas a un modelo de “outsourcing”.

Los empleados trabajan para la consultaría y no para el cliente, toman los requisitos, los analizan y se presenta una proyecto que acaba implementando.

Una de las ventajas de la consultoría, es que son proyectos (en principio limitados), con un principio y un fin, y generalmente tiene cierta independencia en cuanto al desarrollo de este (siempre que cumpla con lo estipulado en plazos y recursos). Se puede decir que los codificadores cambiar de proyecto y el trabajo no se vuelve rutinario, hace que estén siempre estén “despiertos”, y buscando formas interesantes de resolver los problemas.

Otra de las ventajas es que al ser la consultoría un negocio dedicado a la creación de sistemas, los jefes y empleados, hablan un lenguaje semejante y que ambos entienden, lo que suele ser un alivio en muchas formas.

En cuanto al sueldo y el tipo de contrato, no suele hacer restricciones en este aspecto, es decir podría darse de cualquier forma, desde empleados fijos a empleados temporales (por proyecto), pero si suele haber un límite en lo que respecta al sueldo de los programadores (para que los productos que vendan suelan ser rentables).

Outsourcing o subcontratación de recursos humanos



La subcontratación, es el proceso en él que una empresa delega la resolución de un problema o una necesidad a una segunda empresa. Digamos que le “comprar” el trabajo.

La subcontratación tiene muchas facetas, y suele cambiar según la legislación del país, llegando a ser en algunos casos muy controversial.

Una empresa requiere un software, o alguna otra necesidad relacionada con el desarrollo de software, pero no quiere contratar nuevos recursos (con recursos nos referimos a específicamente a codificadores), porque eso requiere adquirir una seria de responsabilidades hacia ellos, como realizar un contrato temporal (para dar paso según la legislación a uno definitivo), a pagar vacaciones, enfermedades, impuestos y prestación social de diversa forma.

Lo anterior hace que no resulte atractivo a la empresa contratar recursos, ahí es donde entra el outsourcing, que contrata a la gente, y la pone a trabajar para la empresa, pero absorbiendo todas las responsabilidades con respeto al empleado (que formalmente pertenece al outsourcing).

Aquí es donde reside uno de los problemas principales en el outsourcing, y es que tiene que compensar para ambas partes, es decir la empresa subcontrata los recursos, porque el coste que le supone es menor que la contratación directa, el outsourcing ofrece sus servicio y asume la responsabilidad con los empleados, porque también le compensa económicamente, ¿Cómo es posible que compense a los dos, cuando en ambos lados, hay un costo económico?, impactando en el salario del programador. El outsourcing cobra a la empresa un costo que es atractivo para ambas partes, y de ese costo debe sacar su ganancia y pagar al codificador.

El outsourcing suele ser atractivo para recién egresados, o personas que están buscando su primer trabajo, ya que las empresas de esta índole suelen siempre buscar recursos para ofrecer a las empresas (y no son muy exigentes en cuanto a los requisitos o la experiencia) y los nuevos ingenieros buscan una oportunidad para obtener experiencia en el mercado laboral y comenzar una carrera.

Antes aceptar un trabajo en una empresa outsourcing revisa bien si te conviene a corto, mediano y largo plazo, y haz una estrategia que sea atractiva a tus intereses.

Se puede ubicar el tema de outsourcing en dos ramas principalmente.

Outsourcing para proyectos concretos


La empresa tiene la necesidad de desarrollar un proyecto de software muy concreto, con lo que contacta una empresa de outsourcing (que en este escenario trabaja más como una consultoría), y pone a disposición de su cliente los recursos necesarios para poder realizar su sistema.

El cliente puede intervenir en el desarrollo en menor o mayor medida. El outsourcing puede usar empleados fijos para que gestionen el proyecto (normalmente son los mas veteranos), y contratar otros exclusivamente para el proyecto.

En estos momentos y debido a que es un proyecto cerrado, generalmente tiene un cotos fijo, y en base de ese costo puede permitirse pagar más a las personas que contrata temporalmente pero es posible que su contrato finalice con la finalización del proyecto.

Outsourcing de recursos humanos


Aquí es cuando la empresa no necesita un desarrollo de software en particular, ni la asesoría en cuanto a tecnologías y sistemas. Lo que necesita la empresa son programadores que saque el trabajo según su control y especificaciones.

Básicamente son empleados mas, que trabajaba con la empresa, generalmente in situ, para sacar sus requerimos en la forma que esta lo necesite, pero siendo su empleador el outsourcing, la cual como comentamos tiene todas las obligaciones.

En este caso el sueldo del programador tienen que a ser menor, debido a que hay un intermediario entre el que pone el dinero (la empresa) y la que lo gestiona (el outsourcing).

El empleo puede ser temporal debido a que la empresa podría no requerir a los recursos en cualquier tiempo, aunque la verdad es que no suele ser así. Las necesidades de sistemas de las empresas no van a disminuir, sino mas bien a aumentar, con lo que el trabajo se acaba convirtiendo en una suerte de fijo, en el que el programador esta asignado a la empresa sin fecha de finalización. Es fijo en la práctica, pero no de forma contractual, con lo hay que considerar las posibilidades que esto lleva, una de ella es que la empresa decida cambiar de proveedor de outsourcing (porque le convenga mas, o sea más barata), en dicho caso el puesto sigue existiendo, pero es puede que se reemplace al programador por otro de la nueva empresa.

Otros de los problemas es la faltan de identificación, y la sensación de no pertenencia del programador con respecto a la empresa y viceversa. En muchos casos la empresa de outsourcing se dedica a encontrar recursos para otras empresas, y una vez que los tiene localizados, los manda a trabajar directamente en sus asignaciones con el cliente, aquí se da un problema en el que el programador no siente pertenecer a la empresa del cliente (donde realmente trabaja), ni a la empresa de outsourcing donde apenas pasa tiempo (y muchas veces no es conocido).

Empleado de una empresa cuyo giro no sean los sistemas



Hay que considerar que todas las empresas tienen necesidades en cuanto a software, pueden comprar software o paquetes pre construidos, pero llegara un momento en el que si empresa quiere impactar en el mercado, necesitara software personalizado a sus necesidades específicas.

Generalmente cuando la empresa llega a la conclusión que necesita un equipo de desarrollo in situ, ha pasado ya por varias fases:
  • Comprar software establecido en el mercado, que se acerque a las necesidades de su negocio.

  • De alguna manera contratar o pagar a un tercero para que gestione o personalice el software anterior, para que se ajuste a sus necesidades reales.

  • Darse cuenta que requieren un sistema más personalizado. Necesitamos que el sistema se adapte a su negocio, y no que el negocio se adapte a los que pueda hacer el sistema.

  • Contratar a alguna consultoría para que cree software específico para su negocio (cuyo propietario real es la empresa).

Cuando la empresa se da cuenta que requiere algo más cercano a sus necesidades y que le preste atención en el momento que lo necesitan, se plantea tener un equipo propio de desarrollo.

En proceso de tener un equipo propio de desarrollo también pasa por varias fases:

  • Creación de un equipo de soporte de infraestructura (tal como redes, impresoras, etc.).

  • El equipo de infraestructura da soporte al software y sistemas adquiridos

  • Se crea un subequipo de desarrollo de software, pero la mismas personas que dan soporte a la infraestructura, es la genera el software, es decir los roles están “mezclados” y son intercambiables.

  • Se crea una división real entre el equipo de soporte y el de desarrollo de software.

  • El equipo de desarrollo de software se organiza en una estructura que contenga los roles clásicos tales como líderes de proyecto, codificadores, analistas, testers…

Hay que ser consciente que no todas las empresas llevan a la última fase (o alguna de las anteriores), los dueños de la empresa no quieren obtener un equipo de desarrollo maduro, lo que quieren es vender su producto. También es cierto que los responsables del negocio no son expertos en sistemas, con lo que a veces es difícil convencerlos de las ventajas de tener un nivel de madurez en el equipo de desarrollo.

Debido a que la mejora en procesos, metodologías y tecnologías no tiene una ganancia directa en la empresa, los propietarios del negocio, no suele querer hacer cambios y mejoras (que serian evidentes para una empresa tecnológica), y podemos caer en una obsolescencia tecnología que estanque el negocio.

Es necesario saber “vender”, la ganancia de la evolución tecnológica continua en la empresa, y tener estrategias para hacer que la empresa (que insisto no está interesada en cambios tecnológicos), los pueda adquirir de la mejor manera y de la forma más sana, de no ser así, las tensiones entre los equipos de desarrollo (que conocen las necesidades de los sistemas) y las de los dueños o trabajadores (que conocen las necesidades de negocio), irán en aumento, haciendo difícil que ambas partes puedan cumplir con sus responsabilidades.

Otro problema es que el propietario de la empresa paga sueldos (nominas), y no paga directamente por software, por que se corre el riesgo que no valore correctamente lo que cuesta hacer software, y se subestime su precio real.

Freelance o autónomo


Es el trabajador que se establece por su cuenta, el vende su trabajo directamente a un cliente, y recibe su cobro.

Las ventajas de esta forma de trabajo son evidentes, libertad en cuento sus decisiones y gestión de su tiempo y recursos, con el añadido de que cualquier esfuerzo adicional que se haga para tu trabajo, es realmente para él.

  • Las desventajas son muy variadas:

  • El autónomo tiene que localizar a su cliente, a la vez que resuelve las necesidades de los clientes actuales.

  • El autónomo tiene que enfrentarse a circunstancias que no tienen que ver directamente con su trabajo, como son responsabilidades financieras y legales, que podrían no ser su fuerte, y a veces no tener tiempo para atenderlas.

  • La más evidente, su ingreso económico depende de su trabajo, si se enferma, o no consigue clientes, no recibirá ingresos, lo cual puede colocarle en una situación dedicada.

Es posible (y muy probable) que el autónomo compagine su trabajo como independiente, con otro trabajo como empleado de algún tipo, de forma que tenga un ingreso fijo, mientras que intenta emprender proyectos propios. Esta es la forma más segura de poder comenzar pero requiere muchas disciplinas, es difícil “quedar bien” con dos jefes (aunque uno de ellos seas tú mismo).

Debido a las complejidades anteriores, varios autónomos se suelen asociar para poder llevar acabo todas las tareas de forma más sencilla, puede que uno se encargue de los asuntos del negocio y otro de los asuntos tecnológico, o dividirse el trabajo entre todos. Esta quizás es la mejor forma, que permite equilibrar las funciones y responsabilidades de cada uno y demás tener el apoyo de un compañero. Por otro lado hay que tener en cuenta que las circunstancia pueden volverse tensas, y generar conflictos facialmente en este tipo de equipos, por eso hay que buscar hacer proyectos con compañeros profesionales y responsable y comportarse así al mismo tiempo. Sin duda habrá contratiempos, pero hay que saber lidiar con ellos, y poder sacar los proyectos adelante.

Empresa propia



Es cuando el desarrollador de software tiene una estructura formal de negocio, con un nombre comercial y empleados que depende de él.

El empresario adquiere unas responsabilidades superiores a las que ha tenido hasta ahora, por que no solo tiene compromisos con sus clientes, sino que además tiene compromisos con sus empleados.

Los productos que pueden vender a un cliente son varios, desde un paquete software prefabricado, a la personalización de alguno, software a la media, o entrar en un esquema de outsourcing donde rente recursos.

Hay que considerar que se puede ser responsable legalmente de los incumplimientos que tengas, ya no solo a nivel personal, si no a nivel empresa. Por ejemplo debemos pagar nominas, y cumplir con los requisitos de ley, aunque nuestro ingreso pueda ser variable.

El ingreso puede, y seguramente, sea variable, esto es por que dependemos del número de contratos que téngannos con otras empresas, así como los proyectos que tengamos en marca. También muchas empresas pueden posponer el pago, ya sea por políticas propia de la empresa, por contrato o por conveniencia. Así que es necesario que se aprendan y se usen herramientas de crédito (lo cual puede llegar a ser otro problema en el futuro).




Si te ha gustado la entrada, ¡Compártela! ;-)

sábado, 22 de agosto de 2020

Regla N°19 de la Ingeniería de Software: Enfoque en el mantenimiento y la escalabilidad antes que en la optimización

Primero haga que funcione, después hágalo rápido. Esto es cierto incluso si se está seguro de que una trozo de código es realmente importante y se sabe que será un cuello de botella es el sistema. No lo haga. Primero, consiga que el sistema tenga un diseño lo más simple posible. Entonces, si no es suficientemente rápido, optimícelo. Casi siempre descubrirá que «su» cuello de botella no es elproblema. Guarde su tiempo para lo verdaderamente importante. Bruce Eckel, Thinking in C++

Recuerdo un desarrollo donde el responsable (que no era codificador) quería optimizar al máximo la velocidad de una aplicación, era una obsesión para él. Así que se entro en una restructuración del código tras otra, con tal de obtener un poco mas de velocidad. Al final el resultado fue que se gano aproximadamente unas pocas horas de procesamiento por cada año de operación, lo que en un escenario real, viene a ser nada, por otro lado se obtuvo un código fuente completamente incomprensible y extremadamente difícil de modificar. Cuando llegaron los inevitables cambios, cada cosa que se movía era un problema nuevo, cada pequeño cambio un desastre inesperado, incluso al final el sistema comenzó a ser extremadamente lento. Al final el sistema se descarto, porque era inusable e inmantenible.

Dos términos que definen la calidad del software son la escalabilidad y la mantenibilidad, a veces son usados para referirnos al mismo aspecto del software, a que pueda “cambiar” con facilidad, y sin problemas.

  • La mantenibilidad son las modificaciones que hacemos a un sistema para que siga funcionando con el propósito para el cual fue diseñado (para resolver la necesidad de el negocio para que fue creado)
  • La escalabilidad es la facilidad con la que podemos agregar nueva funcionalidad a un software para que se adapte a las nuevas necesidades de un mercado y para que nuestro negocio no se quede estancando y obsoleto.

Hay que considerar dos cosas, y más en estos precisos momentos:

  • Todos los negocios al competir entre ellos evolucionan, cambian constantemente para adaptarse a las necesidades de sus clientes (o crear necesidades nuevas).
  • Todos estos negocios se sustentan, de una forma u otra en software que los hacen posibles.

Si el software no es capaz de adaptarse para sostener los continuos cambios de un negocio, va a fallar como sistemas y posiblemente falle el negocio siendo reemplazado por una empresa que si pueda suplir las necesidades del consumidor.

En nuestra vida profesional, vamos a estar más tiempo manteniendo software que creando software de cero. La idea de que se crea un software y nunca se va a tocar, porque “funciona bien a la primera”, es una falacia.

Aquí es donde es fundamental, que el software sea mantenible, si invertimos poco, arquitectónicamente hablando, en la construcción del software, invertiremos mucho en su mantenimiento, y viceversa. Consideran que si vamos a pasar más tiempo mantenimiento un sistema que creando, parece lógico, que debemos optar por abaratar el costo en el mantenimiento.

Volviendo al tema de la velocidad de los sistemas. La preocupación por la velocidad del software, es una “piedra en el zapato”, que a acompañado al desarrollo del software desde sus inicios. El hardware era extremadamente lento (y caro), y había que hacer software rápido, aunque sea sacrificando su propia mantenibilidad (con lo que también hacíamos software caro). Esta idea del de la necesidad de software rápido se incrusto como un paradigma inmutable en la mente de los programadores, aunque ni siquiera tuvieran que haber vivido la lentitud de un hardware tan extremo como en sus inicios.

Así parece que de forma sistemática, cada vez que ser creaba un lenguaje de programación más abstracto con el hardware, se le criticaba de forma inevitable por su lentitud. “C es más lento que ASM”, “C++ es más lento que C”, “Java es más lento que C++”, y así seguirá en un futuro, seguramente.

Las optimizaciones por obtener velocidad, pueden llegar a ser muy confusas, y a veces muy ligadas a situaciones extremadamente particulares (tanto para el software, como para el negocio). Y aquí hay que poner en una balanza varias cosas.

  • ¿Realmente mi software es lento?
  • ¿Realmente necesito que mi software sea más rápido?
  • ¿Cuál es el costo de optimizar el software? O ¿Qué voy a sacrificar para obtener más velocidad?
  • ¿Cuál es el beneficio de la optimizar el software, es real?

Aquí es donde hace sentido, la observación de Bruce Eckel, “Primero haz que funcione, después hágalo rápido”. Asegúrate siempre de programar un software bien construido, que puedas modificar fácilmente.

Un software lento, bien construido, siempre podrás modificarlo para que sea más rápido. Un software rápido mal construido, no vas a poder modificarlo.




Si te ha gustado la entrada, ¡Compártela! ;-)

Reglas de la Ingeniería de software (índice): https://desdelashorasextras.blogspot.com/2019/12/reglas-de-la-ingenieria-de-software_15.html

martes, 16 de junio de 2020

Seguridad y factores de autentificación. Casos de Fraude y Vulnerabilidades.

¿Por qué cada vez es más complicado seleccionar un password y hay cada vez más medidas y controles de seguridad?

Esto es porque dependemos más de “almacenar” y organizar nuestra vida en medios digitales, y estos datos privados adquiere un cierto valor para usarse de forma maliciosa de diversos formas, como por ejemplo robarnos el dinero que tenemos en nuestras cuentas bancarias.

Los formas tradicionales de protección se hacen obsoletos muy rápido, y las formas de obtener nuestros datos, se vuelve cada vez mas ingeniosas, y se alejan de un clásico ataque de película de hacker, en la que se usan puertas traseras o complicados códigos. La mayoría de los ataques se bajan en ingeniería social aprovechándose de la inocencia e ingenuidad (a veces de la avaricia), de los usuarios.

Vamos a analizar las formas de proteger nuestros sistemas y algunos ataques clásicos que los vulneran.


Diferencia entre privado y secreto


Ante de nada hagamos una diferencia entre que es privado y que es secreto:

  • Privado: Es un dato que solo debemos compartir con personas autorizadas, cuanto menos personas sepan este datos, más seguro es. Generalmente son datos que sirven identificarnos y se complementan con un dato secreto.

  • Secreto: Son datos que solo nosotros debemos conocer, no debemos proporcionarlos a nadie, y en el momento de usarlos debemos ser nosotros mismos los que los usemos a través de un sistema, sin ninguna iteración humana adicional.


Factores de autentificación


Los factores de autentificación son “categorías” que clasifican formas que tiene un usuario de autentificarse dentro de un sistema.

En la actualidad se debe combinar más de un factor de autentificación (más de una forma de autentificación) para garantizar la seguridad de un sistema.

Factor cero de autentificación. Algo que se sabe en común


La autentificación se basa en algo el que usuario (o cliente), y la institución (o empresa) conocen. Este dato debe ser privado, pero en muchos casos se acaba convirtiendo en un elemento público, algunos datos son:

  • Número de cuenta, cliente: Deben ser privados pero generalmente no es así, ya que es el elemento con el cual generalmente nos identifican en un primer nivel y hay que compartir.

  • Números de tarjeta: Debieran ser secretos, pero el simple de usarlas lo expone continuamente.

    Una forma muy sencilla de obtener este dato por parte de empleados maliciosos es la siguiente:

    Al momento de pagar, con papel de carbón o algún tipo de superficie que se marque con la presión, graban estos números simplemente apretando la tarjea con la superficie (recordemos que estos números tienen relieve), es algo muy rápido y pasa desapercibido porque puede estar oculto debajo de la terminal (o incluso en el pantalón) posteriormente con la excusa (o el gesto) de revisar la firma aprenden de memoria el CVE. De esta forma ya tienen el número de tarjeta, la fecha y el CVE, con lo que pueden realizar comprar por internet. Esto es muy común en comercios muy congestionados, donde la prisa se junta con el movimiento del empleado como gasolineras que no son de autoservicio.

    ¿Qué se recomienda en esto casos?:

    • Tapar el CVE, con un poco de papel, o cinta, de forma que sea imposible, revisar este número.

    • Nunca pagar con debito, si no con crédito. Es mucho más fácil ganar una reclamación cuando estas pagan con crédito (ya que le dinero nunca es tuyo y el banco se puede negar a pagar a un negocio fraudulento), que pagar con debito (donde si es tu dinero, y cuando lo pierdes, es más difícil reclamarlo).

    • No activar la compra por internet con tarjetas físicas, sino con tarjetas digitales, que ofrezcan medidas de seguridad como un CVE cambiante, y otras medidas de personalización.

    • Nunca pagar por teléfono (en un llamada telefónica) con la tarjeta.

    • Y sobre todo, nunca, nunca, perder de vista tu tarjeta, por ningún motivo, incluso, si el empleado se tarda mucho en cobrar, hay que pedir que se devuelva la tarjeta. Es común que en un escenario de fraude, el empleado haga que no entra la tarjeta y tiene que llamar a alguien o hacer una operación especial, para liberar el cobro, aprovechando para tomar los datos de la tarjeta.


  • Usuarios: Un usuario que identifica al cliente. Aunque este dato generalmente no se tiene que compartir a una persona (porque es privado y se usa generalmente dentro de sistemas), suele ser conocido por la institución (en decir en ninguna forma esta encriptado de forma no reversible) ya que es un elemento de referencia y seguimiento para distintas actividades.

  • Email o teléfono: Se usan frecuentemente y cada vez más como medios de autentificación, debido a que son fáciles de recordar, pero son extremadamente públicos, con lo cual son el primer punto de entrada para un hackeo.


El problema de este factor de autentificación es que a pesar de sus distintos niveles de privacidad, es necesario que tanto la institución, como el usuario, intercambien de forma clara el “dato”, que ambos conocen para garantizar que el otro también lo conoce, pero al hacerlo comprometemos el datos en si, por que no sabemos si realmente la persona o contraparte con lo que estamos hablando es la intuición, el cliente o solo alguien que quiere obtener dicho dato (para efectos maliciosos).

Factor uno de autentificación. Algo que solo el cliente sabe.


Generalmente aquí estamos hablando de los password, pines y demás.

  • PIN (o NIP) numérico: Es un valor numérico de cuatro o más números, que se usa para acceder a un servicio, como por ejemplo, el pago con una tarjeta.

    No ofrece en si mucha seguridad, debido a que con cuatro números, tenemos solo mil combinaciones posibles (no que no es mucho), la seguridad viene en si en que después de un numero de intentos determinado, el dispositivo o la tarjeta se bloquea (en algunos casos puede borrarse la información), lo cual es realmente lo que proporciona la seguridad.

  • Password: Es una palabra secreta que combina, letras, numero y símbolos, al igual que el pin, no se debe compartir bajo ningún concepto con otra persona.

    Tanto el password como el PIN, se guardan (o se debiera) “encriptados” en los sistemas de seguridad, con una encriptación que se llama “de una sola vía” (conocido comúnmente como hash). Esto quiere decir que no se puede llevar al valor original (el password), desencriptando el valor guardado, porque es imposible, con lo que ni la institución sabe cuál es el password que estamos usando.

    Una anécdota que me paso hace unos años con respecto a los password. Estaba con una líder de proyecto, y necesita acceder a su laptop para obtener un dato, pero ella tenía las manos ocupadas, así medio en broma le comente “voy a entrar con tu password”, y por chiripa y en medio de la broma use el nombre de su hija (ella acaba de madre recientemente), y por sorpresa la computadora de desbloqueo.

    La situación anterior, nos hace ver que sin restricción alguna, seleccionamos podemos seleccionar password que son débiles, relacionado por algún detalle de nuestra vida o contraseñas demasiado comunes que están en diccionarios para hackear contraseñas.

    Cuanta más entropía (menos orden y menos lógica) tenga un password más seguro es, con lo que se establecen una seria de restricciones a su creación, generalmente son las siguientes (cuando más se cumpla, más seguro es el password):

    • Una longitud mínima.

    • Un uso mínimo de mayúsculas y minúsculas.

    • Un uso mínimo de símbolos.

    • Un uso mínimo de números.

    • No permitir caracteres (o números) igual en secuencia, como ldquo;aaa”, o “1111”.

    • No permitir caracteres consecutivos de forma ascendente o descendente, como “1234”, “abcd” o “dcbd”.

    • No permitir palabras que se encuentren seguidas en el teclado como “qwerty”.


Una vez me preguntaron si hacer públicas esas reglas no hace que un ataque sea “más guiado” y por tanto hacer que sea más posible hackear un password. La respuesta es no, es mas hacer pública estas reglas y obligar a que sea cumplida por los usuarios (o clientes), son realmente un elemento disuasorio para los hackers, por que básicamente saben que con los medios actuales esas contraseñas son prácticamente inhackeables (aunque pueden obtenerlas mediante ingeniería social).

Factor tres de Autentificación. Algo que el cliente tiene


El usuario de autentifica con algo que solo él puede poseer, generalmente un elemento físico que se asocian a una identidad y nos permiten el acceso a una acción, característica o servicio. Algunos son:

  • Tarjetas: Las típicas tarjeas que nos permite el acceso a zonas restringidas, o para realizar pagos con ellas.

    Las tarjetas como elemento único de validación son extremadamente inseguras, deben usarse siempre junto con otro elemento.

    En México, por ejemplo, era común en la década pasada que para pagar con tarjeta solo fuera necesario presentar la tarjeta, realizar el pago con el punto de venta y firmar el voucher, en teoría el empleado debiera validad la firma y la identidad con otra autentificación, pero a pesar de ser obligatorio, era a voluntad del empleado y comúnmente nunca se hacía.

    Solo fue hasta hace poco que se comenzó a pedir el NIP de la tarjeta al realizar el pago (pero no para todas las tarjetas, ni bancos), de esta forma ya no queda a la voluntad del empleado el validar la identidad del cliente, sino que además es el cliente el que debe acreditarla, y se si equivoca varias veces, puede bloquear su tarjeta. Esta es una medida de protección fundamental para que la tarjeta no sea solo el medio de identificación posible para hacer un pago.

    Pero nada sirve totalmente, una vez mas es más sencillo realizar fraudes mediante ingeniera social, que mediante complicados y herramientas tecnológicas, como ejemplo los siguientes escenarios:

    Muchos Bancos no tiene personalizadas sus tarjetas de debito (no entiendo el motivo), con que no es fácil ubicar si una tarjeta es tuya entre dos tarjetas iguales del mismo banco, en base a eso, uno de los posibles fraudes es el siguiente:

    Una persona parece consternada cerca de un cajero (esta es el timador uno), cuando otra (este el cliente real), va a usar dicho cajero, el timador se acerca y le dice “oiga no se olvide frotar su tarjeta”, cuando el cliente se muestre perplejo, el timador insiste que debe frotar la tarjeta por qué no funciona el cajero, haciendo que se sienta cada vez mas confundido. Cuando sienta que haya bajado la guardia, le toma la tarjeta rápidamente, y le enseña con gento amable como debe frotarla y se la devuelva rápidamente, pero en el intervalo, le cambia la tarjeta por otra, al final se despide y le desea suerte, todo ocurre tan rápido que la única sensación que tiene el cliente, es que el sujeto es un poco raro y confiado.

    Cuando el cliente vaya a usar su tarjeta y le pida el NIP, es donde se acerca el timador dos, para ver disimuladamente que números está marcando. De esta manera los timadores ya tiene por separado el NIP y la tarjeta, y el cliente está confundido sin saber que ha pasado. Dándoles tiempo a los sujetos de usar las tarjetas en un negocio para compra televisiones o algún elemento de valor, que ya tendrá un tercer timado, en la fila de la caja de un comercio cercano. Todo esto puede pasar en menos de diez minutos.

    Otro timo que se puso de moda hace unos años, esta vez más sofisticado:

    Un timador, con una base de datos de teléfonos y personas (que se puede comprar ilegalmente), se hace pasar por teleoperador de un banco con muchos clientes (lo que aumenta la posibilidad de encontrar un inocente cliente).

    Llama a una víctima de sus lista, y le indica que su banco le realizo un cargo incorrecto (el teleoperador no sabe si el cliente tiene cuenta en un banco, solo es suerte y estadística).

    Le dice “por su seguridad, voy a decirle los 8 primeros números de su tarjeta)”, y aquí reside el engaño, los 8 primeros números de una tarjeta, solo indican a que banco pertenece la tarjeta, y el tipo de producto que es, esto quiere decir, que son iguales para todos los clientes.

    El cliente al ver que le han dado algunos números de su tarjeta (que no aportan realmente nada), le proporciona al timador todos los datos de su tarjeta, lleno de confianza, al pensar que habla con su banco y no con un timador. Al final, el resultado, es que de una forma u otra, el cliente se queda sin su dinero, al haber dado sus datos privados al timador.

  • Tag (Etiqueta RFID) o incluso una matrícula: Los coches pueden tener elementos como tag, que permiten la salida y entrada de vehículos (a veces incluso con reconocimiento óptico de matriculas).

    Uno de los problemas de usar un tag (o la matricula) asociado a un vehículo, es que generalmente esta pegados al mismo vehículo, con lo que se puede decir que están unidos el medio de autentificación y la acción a realizar. Esto quiere decir que por ejemplo si alguien roba tu vehículo en un estacionamiento, podrá salir con el sin más problemas (por ese falta algo más que impida esta circunstancia como un guardia o cámaras de seguridad).

  • Un teléfono: Se garantiza que la operación que se desea hacer es desde un teléfono especifico, generalmente esto se consigue de una forma parecida a la siguiente:

    1. Se genera un identificador único con datos del teléfono.
    2. Se generan claves criptografías (generalmente asimétricas).
    3. Se encriptan estos datos, usando algo mecanismo de protección como un password.

  • Un token o generador de números: Son dispositivos que genera números y se usan en cada operación, por ejemplo, si estoy haciendo una operación bancaria se pedirá un número generado por este dispositivo, y si no es el número correcto, la operación no se realizaran.

    Los dispositivos pueden ser físicos, como un aparato dedicado exclusivamente a esa función, o una aplicación instalada en un teléfono.

    Estos dispositivos, de la siguiente forma:

    1. Existe un servidor y dispositivo, ambos aislados uno de otro, sin comunicación alguna.
    2. El servidor y dispositivo, comparte una misma llave de una determinada longitud llamada semilla.
    3. Ambos generan números basándose, en la semilla (que comparten), y algún elemento independiente de ellos, como la fecha y hora exacta, esto genera un numero, como el servidor y el dispositivo generan comparte la llave, debiera poder generar el mismo número, en el mismo momento (sin tener que estar conectado).

    De esta forma el servidor sabe en cada momento que numero debe generar el dispositivo y solicitárselo al usuarios para garantizar que tiene el dispositivo consigo.

    Uno de los problemas es que el servidor (que está en la empresa que proporciona el servicio, como un banco) sabe cuáles son las semillas que generan el token, es decir es capaz de duplicar dichos números, con lo que en teoría es información que se comparte, y no es algo que tenga exclusivamente el cliente. En otras palabras quien tenga dichas semillas, se pudiera hacer pasar por el cliente.

    Otro de los problemas del token, es que el número sirve para autorizar casi cualquier cosa, con lo que podemos ser engañados, para proporcionar nuestro número actual de token, y realizar operaciones fraudulentas.


Factor tres de Autentificación. Algo que el cliente es


Algo único que está ligado a la persona física del cliente, de forma inequívoca, algo que “el cliente es”, de forma inequívoca e irrepetible, como:

  • Firmas manuscrita: es la clásica firma que hacemos de nuestro puño y letra como prueba de nuestra identidad. Es usual en contratos, y documentos impresos. Aunque se supone que es algo que solo nosotros podemos duplicar exactamente igual, generalmente puede ser copiada y no ofrece mucha seguridad (tal es el caso que en la realización de contratos generalmente hace falta una figura notarial que le de valor, y personas que funjan como testigos).

  • Elementos biométricos: Son elementos que pertenecen a nuestro cuerpo, y que pueden ser validados por un sistema informático, como

  • Huellas: Son los surcos únicos que poseemos en la llama de los dedos.

  • Rostro: Nuestra cara como identificación, el problema es que frecuentemente nuestra cara cambia, con lo que es necesario renovar la autentificación.

  • Iris del ojo: Al igual que las huellas se supone que son elementos únicos en cada uno de nosotros.

El cambio hacia los biométricos ha sido bastante arduo, por no siempre ha dado los resultados requeridos. Unos de los aspectos importantes de los biométricos (y por lo cual han sido hackeados mas de una vez), es que deben garantizar que la persona que está ofreciendo la muestra biométrica está viva y presente, por ejemplo en el caso de las caras es necesario garantizar que realmente estamos leyendo una cara, y no la foto de un sujeto, en el caso del iris, se deben observar movimientos involuntarios del ojo, para garantizarlo.

A veces el uso de biométricos puede ser frustrante, por ejemplo, Es común tener lectores de huella en los teléfonos móviles, estos lectores solemos entrenarlos con nuestra propias huellas y tener un porcentaje de éxito muy elevado, pero lectores empresariales (a veces de poco costo), que se usan másicamente en las empresas para identificar clientes, suelen dar multitud de quebraderos de cabeza.

Autentificación multifactorial


Como hemos visto cualquier solución de autentificación individual, es hackeable en cierto punto, casi siempre usando ingenio más que habilidades tecnológicas.

He aquí el por qué generalmente se usa más de una de forma de autentificación (lo que se conoce por autentificación multifactorial). Por si una es rota, quede la protección de la otra.

De misma forma las técnicas de fraude, avanzan más y de forma muy rápida, con lo que los sistemas se van mas forzados a endurecer sus mecanismos de seguridad, a expensas de la comodidad del usuario.

El principal enemigo del usuario, es su misma ingenuidad, es más fácil que el usuario proporcione sus datos de autentificación mediante engaños, que en si sea hackeado por sofisticados métodos informáticos.



Si te ha gustado la entrada, ¡Compártela! ;-)