lunes, febrero 13, 2017

Cohesión



La cohesión (en programación) se refiere a que tan bien están relacionados entre sí los elementos de un módulo. En el desarrollo orientado a objetos podría decirse que es el grado de relación que existe entre los métodos y variables de una clase. 

Conocer la cohesión te puede ayudar a saber si la clase cumple o no con el principio de responsabilidad única, el cual dice que una clase solo debe tener una razón para cambiar. A veces no se ve a simple vista si el diseño cumple con este principio. Midiendo la cohesion podría ayudarte a distinguir si realmente los métodos hacen cosas relacionadas entre sí.

He visto que hay más de una forma de medir la cohesión de una clase, hay herramientas que pueden auditar el código y decirte como está la cohesión en el proyecto. No he tenido oportunidad de jugar con esas herramientas, la verdad es que esta métrica no la aplico seguido; pero una forma sencilla de medirla es creando un diagrama donde a cada operación de la clase la representas con un rectángulo y cada variable como un circulo (o rectángulo con bordes redondeados). Después conectas los elementos relacionados con una línea. Una vez que se hacen todas la conexiones agrupas los elementos que tienen relación entre sí.

Si solo te sale un grupo entonces hay una alta cohesión y la clase tiene una sola responsabilidad. Si salen varios grupos entonces tiene una baja cohesión, significa que la clase tiene más de una responsabilidad  y quizás sea buena idea dividirla en otras clases, según los grupos resultantes en el diagrama.

Esto va a depender de lo que buscas con la clase, hay ocasiones en que la clase solo la quieres para tener datos relacionados entre sí, como una clase de tipo dirección sin operaciones, solo propiedades para cada parte del dato. Ahí tienes una baja cohesión; pero quizás quieras dejarlo todo en una sola clase. Esto dependerá de tu diseño, la métrica solo te da información, a ti te toca decidir que hacer con ella.

Haz un ejemplo, supón que estás trabajando en una aplicación que generará una factura electrónica, entonces creas una clase Factura con las siguientes operaciones y variables (omitiendo cosas porque esto es solo un ejemplo):

Ya que tienes las operaciones y variables dibuja unas flechas con las relaciones y reacomodas los elementos para que se vean mejor las relaciones:
Viendo las relaciones puedes identificar 4 grupos, eso te dice que la clase Factura tiene baja cohesión y que puede dividirse en varias clases. Puedes ver, también, que la clase tiene varias responsabilidades.

Separando las responsabilidades de la clase factura y buscando una alta cohesión puedes quedar con un diseño de 4 clases donde antes tenias solo una. Cada una con una única responsabilidad y "una sola razón para cambiar". 
Al final el objetivo es que el código sea fácil de entender y de mantener por ti o por alguien más. La meta no es lograr una alta cohesión, la meta es lograr un mejor diseño. Si después de separar en muchas clases, algo te dice que hubiera sido mejor dejar todo en una sola, no dudes mucho en hacer el cambio.  





jueves, febrero 02, 2017

Todo comienza con la escritura

Estaba escuchando el podcast de seanwes, un episodio donde comentaba (como muchas otras veces) que todo comienza con la escritura. Ya había escuchado esa opinión de Sean, de hecho él tiene un curso y toda la cosa sobre el tema. Cuando escuchaba esa frase, pensaba que eso aplicaba solamente para el content marketing; pero pensando un poco más me di cuenta que también puede aplicarse al desarrollo de software.

"Todo comienza con la escritura". Al pensar como aplica esa frase al desarrollo de software, recordé que como programador lo que me gusta es escribir código. No me gusta escribir palabras sobre lo que va a hacer mi programa, no me gusta realmente escribir documentación; pero... 

También recuerdo que en los proyectos donde he podido avanzar más rápido y sin estrés es cuando me entregan los requerimientos por escrito y bien explicados. Cuando la persona que describe el problema se tomó la molestia de escribir claramente el objetivo del proyecto. Me ha tocado estar en proyectos donde no hablo directamente con el cliente, donde mi trabajo es solo implementar una solución propuesta por el arquitecto, en esas ocasiones ha sido fácil llegar al resultado cuando el diseño está bien documentado. Cuando no tengo que estar en las juntas donde se habla de como sería bueno que funcionaran las cosas en lugar de definirlas por escrito.



Parte de la motivación diaria que me ayuda para no distraerme es tener tareas bien definidas, por eso creo que es bueno definir tareas antes de ponerse a programar... con esto me doy cuenta que realmente todo empieza con la escritura, también en el desarrollo de software. Se inicia con la definición de la idea, del objetivo y con la definición de tareas. Si tenemos el habito de escribir nuestras ideas, no nos dará flojera definir por escrito lo que vamos a realizar. De ese modo cuando tengamos definido lo que haremos podemos abrir el editor y solo preocuparnos por el código, seguir el flujo sin detenernos por falta de información.

Es claro que el escenario ideal no es muy común, por lo general no hay tiempo para definir todo a detalle e incluso cuando lo hay no tiene mucho sentido ya que seguramente los detalles de requerimientos cambiarán. Pero no por eso debemos dejar de definir el proyecto con escritura antes de iniciar, las especificaciones pueden cambiar y el habito de escribir nos va a ayudar a no postergar la actualización de la definición. Como todo, entre más practiquemos definir los proyectos con palabras más sencillo se nos hará. Será fácil que llegue una persona nueva al equipo y se ponga al corriente con lo que es el proyecto. 

miércoles, enero 18, 2017

Aprender o morir

Las cosas no son las mismas desde que aprendí a programar, los conceptos básicos son los mismos; pero las bibliotecas, plataformas, herramientas e incluso los lenguajes han cambiado. Aun así se espera que seas experto en poco tiempo, constantemente tenemos que estar aprendiendo para poder usar lo que tenemos disponible para sacar el proyecto adelante. Incluso dentro de la misma plataforma y lenguaje las cosas cambian. En el caso de JavaScript es fácil ver que en cuanto te distraes un poco las cosas ya cambiaron y lo que usan los cool kids ahora no es lo que tú conoces, en lo que aprendes lo que usan ellos ya cambiaron a otra cosa. Pero no debemos molestarnos por eso, es parte del trabajo.

Si no te gusta aprender constantemente, quizás el desarrollo de software no es para ti. Asumo que en todas las carreras es importante mantenerse al día, conocer las tendencias, los últimos adelantos. Pero en el desarrollo de software en particular, la velocidad con lo que van y vienen tecnologías es alta. Con internet y el OpenSource hay más opciones. Ya no basta comprar un libro y conocer el IDE actual mientras sale la nueva versión.

Como profesionales del desarrollo de software es nuestra responsabilidad conocer las nuevas bibliotecas, marcos de aplicaciones, lenguajes, plataformas y aprenderlas en caso de que sirvan para la solución del problema. Si no sabes, está bien decirlo, nadie sabe todo; pero eso no te justifica para no hacer tu trabajo. No digas: "es que eso no me gusta" cuando en realidad le sacas la vuelta porque no te has dado el tiempo de aprenderlo. Por lo menos debemos tratar de saber qué es lo que no sabemos para poder investigarlo cuando veamos la necesidad.

Aprender es parte del desarrollo de software (y del programador). Si no estás aprendiendo algo nuevo, lo estás haciendo mal.

miércoles, enero 11, 2017

Define las tareas antes de empezar

Es divertido iniciar proyectos e ir agregando funcionalidad que se nos va ocurriendo. Intentar usar nuevas tecnologías, nuevas formas de resolver problemas. Equivocarnos, aprender y volver a empezar.  Esto lo podemos realizar en un proyecto personal, en un super happy dev house o cualquier otro día.

Pero cuando se trata de entregar un proyecto con presupuesto fijo a tiempo, vale la pena definir desde un principio las tareas por realizar. Pensar qué es lo que queremos lograr y definir los pasos necesarios para llegar a esa meta. Esto no quiere decir que no podemos ajustar el plan después, el plan cambia. Para eso hacemos las iteraciones en el desarrollo. Revisamos como vamos y decidimos qué sigue.

Ha habido ocasiones que por sentir que tenemos el tiempo encima iniciamos el desarrollo del proyecto sin tener el backlog definido completo. Esto con la idea de que en cada iteración podemos irlo modelando, agregando elementos y definiendo el trabajo necesario. Para algunos proyectos ha funcionado más o menos; pero me he dado cuenta que durante el desarrollo del proyecto sentimos que vamos un poco sin rumbo. No sabemos cuánto nos falta o que porcentaje llevamos avanzado.

En cambio, cuando nos tomamos el tiempo de definir los objetivos y tareas necesarias a realizar. Aun cuando parece que no tenemos tiempo que perder y que debemos simplemente ponernos a programar en lugar de estar definiendo tarjetitas en un programa para administrar proyectos. Incluso cuando el proyecto ya se pasó del tiempo de entrega, vale la pena detenerse a pensar y definir eso que vamos a realizar. Con esa información podemos "saber" cuánto tiempo más necesitamos para completar el proyecto. Aunque nos fallen los estimados podemos revisar donde estuvo el error y mejorar el próximo proyecto. Sin tareas definidas y solo codificar es difícil medir el progreso e identificar áreas de oportunidad.

Tener el trabajo definido ayudará también a trabajar más rápido. Se evitan los tiempos muertos que surgen cuando al programar pensamos: "Ya terminé esta tarea... ¿ahora qué sigue?". Si ya tenemos un backlog de cosas por hacer bien definido podemos seguir programando en lugar de detenernos a pensar. Como ya no tenemos que pensar en detalles no técnicos podemos concentrarnos en lo que nos gusta. Disfrutar el viaje programando con nuestra dosis de motivación diaria.

viernes, enero 06, 2017

Si no sabes, no mientas

Hace tiempo necesitábamos sacar un proyecto que sería una prueba de concepto, algo rápido para probar una idea. La meta era sacar el proyecto en 2 semanas, el cliente solo quería saber si ese sería el mejor camino para resolver el problema. Le pedí a un programador que me ayudará con cierta tarea y al mismo tiempo le explique la importancia de tener algo listo en el menor tiempo posible. Al explicarle lo que debía de hacer le pregunté si ya lo había hecho antes, si sabía usar la herramienta. Porque si no, yo podría explicarle sin problema en una hora como hacerlo. De ese modo él iba poder seguir desarrollando. Me contestó que ya lo conocía y que no habría problema.

Al otro día revisé el repo y no estaba lo que había pedido. Le pregunté sobre el commit y me comentó que se le había pasado subirlo; pero que lo haría en ese día. Sin embargo al otro día seguía sin ver los cambios. No me gusta estar preguntando cada rato el clásico "cómo vas"; pero si no se ve avance en el proyecto no queda de otra más que preguntar. Me dijo que en un momento se lo aventaba... después de un rato me pidió ayuda porque no sabía como hacer lo que le había pedido. Esto fue casi tres días después de cuando le asigné la tarea y le pregunté si sabía.


No me hubiera molestado, para nada, que no supiera como realizar algo, porque pude haberle explicado y contemplar el tiempo necesario para aprender; pero como me dijo que sí sabía, no había planeado esos 2 días y ahora con dos días menos debía planear el tiempo que le llevaría aprender aquello que quizás pensó que podría googlear y sacar sin que me diera cuenta que no sabía.

Si necesito algo nuevo ¿Confiaré en que esa persona dará una solución? No. Ahora sé que no puedo confiar en que hará el trabajo, aunque diga que lo sabe hacer. No había necesidad de mentir, ni de tratar de hacer creer a los demás que sabía lo que no sabe. No está mal no saber, lo que sí está mal es mentir. Si no queremos decir "no sé", lo que debemos hacer es tratar de estar preparados para lo que se pueda necesitar, aprender lo nuevo lleva su tiempo y debemos estar en constante capacitación para mantenernos al día y ser útil cuando se necesite usar algo nuevo.

No debes tener miedo a decir que no sabes hacer algo o que no haz usado cierta herramienta. Nadie sabe todo. Lo más importante es la actitud, las ganas de aprender y tener sentido común. Si crees que perderás reputación por decir que no sabes algo, de nada sirve mentir, al final se va a notar que no sabes y va a salir peor. No solo serás la persona que no sabe, también serás alguien en quien no se puede confiar. Aprender algo nuevo es fácil, recuperar la confianza de los demás no tanto.

miércoles, diciembre 28, 2016

Pleonasmos booleanos


A veces es bueno escribir más código del necesario para que sea fácil de leer. Para que la persona que le de mantenimiento pueda entender de forma clara y rápida lo que hace el código. Esa persona en el futuro puedes ser tú mismo. Hay otras veces que el código redúndate no ayuda, al contrario es ruido que no dejar ver lo que realmente está pasando. Puede esconder bugs difícil de ver a simple vista.

Al escribir código debemos tomar en cuenta que no solo escribimos para la maquina. A la computadora no el importa como escribamos las cosas, para ella es lo mismo el nombre de las variables, el estilo de programación, el lenguaje, paradigma, etc. El código fuente que escribimos debemos pensar que es para las personas que van a leerlo. Escribimos para personas, no para maquinas. Por lo tanto debemos de ser claros con lo que tratamos de expresar en el código. Tampoco es una novela a la que le debemos dar suspenso o drama. Deben ser una serie de instrucciones concretas sin palabras de más.

Los pleonasmos en el código son esas palabras que no es necesario escribir, que están de más. He visto que pasa con los booleanos.

Tomemos por ejemplo algo en JavasScript: supongamos que tenemos un formulario en una página web y necesitamos que el usuario verifique una casilla antes de continuar (¿suena raro eso en español? el usuario necesitar hacer check en un checkbox).

var approveCheckbox = document.GetElementById("approve");
var continueButton = document.GetElementById("continue");

if (approveCheckbox.checked == true)
  continueButton.disabled = false;
else
  continueButton.disabled = true;

El fragmento de código tiene pleonasmos, palabras de más. En una condición donde esperas un valor booleano, verificar la igualdad a true siempre está de más. Ese es el trabajo de la sentencia condicional (el if). Por lo tanto siempre que veamos == true en un if lo podemos quitar y el código hace lo mismo.

var approveCheckbox = document.GetElementById("approve");
var continueButton = document.GetElementById("continue");

if (approveCheckbox.checked)
  continueButton.disabled = false;
else
  continueButton.disabled = true;


Otra cosa que podemos notar es que el código en el then y en else ambos son asignaciones. Cuando tenemos una asignación en ambos casos y solo cambia según la condición podemos usar el operador ternario "?". Esto es un cambio opcional que a veces ayuda a reducir el ruido en el código. Es importante no abusar de esto.

var approveCheckbox = document.GetElementById("approve");
var continueButton = document.GetElementById("continue");

continueButton.disabled =
    approveCheckbox.checked ? false : true;


Ahora es fácil ver que cuando tenemos una asignación a un booleano que depende de otro booleano (condición) podemos simplemente asignar la condición a la variable

var approveCheckbox = document.GetElementById("approve");var continueButton = document.GetElementById("continue");

continueButton.disabled = !approveCheckbox.checked;


Tenemos menos código y es más fácil comprenderlo, darse cuenta que: la propiedad disabled del botón depende de la propiedad checked del checkbox.

Entonces en resumen, lo que podemos hacer para reducir algunos de los pleonasmos en el código son:
  1. Piensa que escribir "== true" es como escribir "subir para arriba". Simplemente bórralo, no es necesario.
  2. Si asignas un valor en el then y otro en el else puedes usar el operador ternario, con moderación.
  3. Si lo que asignas es un booleano que depende de la condición, asigna directamente la condición a la variable. Esto también aplica si comparas valores, algo como: var enable = list.lenght > 0;
Hay otros ejemplos de redundancias en el código o pleonasmos, estos son algunos comunes y "fáciles" de evitar.



jueves, julio 21, 2016

No hagamos repositorios para el acceso a datos

Este artículo está pensado sobre todo para el desarrollo usando el .NET Framework. Quizás aplique para los demás también, ya que casi cada Framework tiene su ORM.

Hace ya varios años que leí la opinión de Ayende Rahien acerca de que el patrón repository era el nuevo singleton. Tiempo después Jimmy Bogard también escribió sobre alternativas.

A mi entender el patrón repository consiste en abstraer el acceso a datos para que el resto del código no tenga que lidiar con los detalles del acceso a datos (conexiones, consultas, SQL, etc) al momento de acceder a colecciones de datos.

Con  el creciente uso de ORMs el patrón repository ya no es necesario. Ahora podemos usar algo como Entity Framework y dejar que se encargue de esos detalles para los que construíamos un repositorio. Entity Framework (o cualquier ORM) hacen eso y más sin que tengamos que escribir tanto código de "plomería". Escribo este post porque aun veo a programadores que intentan usar el patrón repositorio aún y cuando están usando un ORM.


No veo la utilidad de abstraer la abstracción del ORM (como EF) bajo el patrón repository. No es necesario, es querer apegarse a un patrón de diseño solo porque antes se usaba. Sí, se usaba porque era necesario; pero ya no lo es. La meta no es usar patrones, la meta es tener software funcionando que sea fácil de modificar.

Escribí un poco sobre esto cuando traté el tema de la arquitectura en capas, aunque el artículo no se trataba precisamente del patrón repositorio.