sábado, 28 de mayo de 2016

Don't Repeat Yourself Principle o DRY (primera parte)

Esta vez la entrada es acerca del principio  DRY o no te repitas  a ti mismo, este principio es muy conocido, tal vez uno de los principios de los que mas se habla en el desarrollo de software pero sobre todo en el contexto del código, aunque sus aplicaciones son muchas más, de estas aplicaciones es que hablaremos en el post de esta semana.

En el código

Es el contexto mas común en el que se aplica es este principio, y de lo que se trata es de que no se tenga código duplicado, el hecho de tener código duplicado es un problema grave en el desarrollo de software ya que es muy difícil tener identificado este código en todos los lugares donde se repite y en caso de que por ejemplo se tenga algún bug en esas líneas se tiene que replicar la corrección en todos los lugares necesarios lo cual es algo difícil de hacer sobre todo si no se sabe donde se tiene repetido el código.
Normalmente lo que se hace para solucionar esto es poner el código duplicado en un método y hacer la llamada a él en los lugares donde se se tenían los bloques duplicados. Otra estrategia es dejar en uno de los dos lugares donde se tiene el código duplicado y heredar una clase de la otra y así ya las dos usaran el mismo método vis herencia, pero ojo, esta estrategia la mayoría de las veces no es la mejor ya que normalmente se rompen oros principios como "Composition over inheritance" o preferir composición sobre la herencia y "Liskov Substitution" o substitución de Liskov, los cuales esperemos abordar en entradas siguientes.
En cuanto a la detección, ya hay herramientas de análisis estático de código que son de mucha ayuda al momento de detectar cuando se rompe este principio.

En el contexto

Este tipo de "código duplicado" es un poco mas difícil de percibir y se trata de que aunque los bloques de código por sí mismos no son iguales, si tienen el mismo objetivo, con este tipo de "código duplicado" se tiene que tener mas cuidado ya que normalmente los analizadores de código estáticos no los detectan por lo que quedan más al feeling del desarrollador.
Las soluciones son normalmente las mismas que en el caso anterior.

En los comentarios

Este caso se da mucho en los desarrolladores jóvenes ya que normalmente se les enseña que tienen que "documentar" su código y que esto es una buena práctica, el hecho es que la mayoría de las veces cuando hacen esto están violando este principio ya que te estás "repitiendo a ti mismo" en código y en comentarios, lo cual no tiene caso.
Esto parece muy trivial y uno podría llegar a pensar que que payaso soy pero cual es el problema de esto, el problema es que el software está siempre en constante evolución, lo que implica es que el código cambia tan constantemente (o tal vez mas constantemente) como las veces que uno se cambia los calzones, pero cual es el problema... el problema es que normalmente no cambiamos los comentarios, por lo que el comentario se vuelve obsoleto y si uno documentó bien chingón el código con muchos detalles pues ya valió pues ahora el comentario no es fiel a lo que hace el código y esto puede llegar a causar bugs muy graves ya que quien esa ese código (api) se pede basar en la documentación para decidir su uso o no y seguramente esperará un comportamiento muy distinto al que el código al final de 10 cambios de calzones hace.
Como solucionarlo, pues documentando con comentarios lo menos posible el código y haciendo que él por si mismo revele su intención desde el paquete, nombre de clase y nombre de método. Aguas no digo que no se pongan comentarios, solo que si se ponen o se actualicen o sean algo que realmente valga la pena, por ejemplo si tiene un código que usa una estrategia de minimax para solucionar un problema pero este algoritmo es muy complejo pues vale la pena primero que el código por si solo revele su intención y tal vez documentar un poco acerca de este algoritmo.


viernes, 20 de mayo de 2016

Principios en el desarrollo de software

Los principios en desarrollo de software son ciertas características de diseño de objetos que permiten que el código sea mas expresivo y por ende mas mantenible, hay varios principios, los más conocidos son los principios SOLID, DRY y KISS, en una serie de blogs entraremos mas en detalle en cada uno de ellos, por lo pronto y de forma muy general doy una breve descripción.

SOLID acrónimo de Single Responsability (responsabilidad única), Open-Close (abierto a extensión y cerrado a modificación),  Liskov Substitution (substitución de Liskov), Interface Segregation (segregación de interfaces) y Dependency inversion (inversión de dependencias) estos son principios que aplican de forma directa en el diseño de clases para programación orientada a objetos, como comenté, mas adelante en algún post revisaremos cada uno de estos principios.

DRY acrónimo de Don't Repeat Yourself (No te repitas a ti mismo), este principio es uno de los más publicitados en el medio y su aplicación va desde una clase hasta un sistema completo, pasando por versionamiento de la base de datos y documentación.

KISS acrónimo de Keep It Simple Stupid (mantenlo simple, estúpido) es un principio también muy conocido pero que es muy difícil de aplicar ya que por naturaleza (no le encuentro otra razón) los desarrolladores somos muy perfeccionistas, pero este principio nos dice que hay que mantener las cosas lo más simple posibles y esto es desde el código, hasta el propio producto igual, pasando por la documentación y el proceso de desarrollo de software.

Estos principios son muy usados y mencionados del desarrollo usando metodologías ágiles (de las que escribiremos en algún post posterior) y es que es muy normal que en este tipo de metodologías dada su naturaleza propicien que los desarrolladores se apeguen a este tipo de principios casi de a fuerzas pero de una forma un poco sutil.

Además de estos principios se podrían mencionar también otras características del software que un buen desarrollo debe de cumplir como el hecho de que todo código productivo debe de estar respaldado por un test o prueba unitaria automatizada y ya hablando de los tests también mencionar que estos tests no deben de ser "low class citizens", es decir, estos tests son igual (o tal vez hasta mas) de importantes que el código productivo, otra característica de un buen código es que debe de ser un código limpio siguiendo ciertos lineamientos encaminados mas que nada a que sea entendible y por lo tanto mantenible.

Bueno, pues esperen próximamente posts relacionados a todo esta madre sin sentido que les acabo de decir.

Saludos.

domingo, 15 de mayo de 2016

Patrones

Originalmente en este post iba a hablar de forma muy general de patrones, principios y herramientas, pero con forme empecé a hablar acerca del primero de ellos me di cuenta que es mejor separarlos, por lo que esta vez hablaremos sólo de patrones desde un punto de vista general, no hablaremos de un patrón en específico si no mas bien sobre que es y por que es importante, pero bueno pues a darle que es mole de olla.

Patrones, seguramente hemos oído mucho del patrón mvc (que creo es que es el único que se menciona en las universidades de México) o mvvm o singleton, pero que cosa es eso y por que son patrones? pues empecemos definiendo lo que es un patrón, también conocidos como patrones de diseño, según wikipedia "Los patrones de diseño son la base para la búsqueda de soluciones a problemas comunes en el desarrollo de software y otros ámbitos referentes al diseño de interacción o interfaces.
Un patrón de diseño resulta ser una solución a un problema de diseño. Para que una solución sea considerada un patrón debe poseer ciertas características. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reutilizable, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias" tomando esta definición como base un patrón es algo que te ayuda a solucionar un problema y que de alguna forma es algo genérico, por lo que para poder aplicar un patrón hay que tener un problema de diseño que se quiere solucionar y acá es a donde muchos de los desarrolladores jóvenes no les hace mucho sentido esto de los patrones, ya que las primeras veces que uno empieza a tirar código es muy difícil que identifique estos problemas de diseño (aguas, no confundir con los problemas de negocio a solucionar) ya que en su experiencia aún no se ha topado con ellos, a veces, me atrevo a decir que no solo las primeras veces que uno tira código, los primeros sistemas en que se ve involucrado o hasta en los primeros años de "profesional" (en algún otro post hablaremos sobre esta palabra) es algo difícil de identificar estos problemas de diseño, ya conforme uno se va haciendo mas huevudito en esto del desarrollo de software y empieza a saber lo que en verdad es desarrollar software con calidad es cuando le empieza a caer el veinte de lo que son los patrones y por que son importantes; pero bueno, volvamos a la definición, otra parte de ella que llama la atención es que dice que debe de ser reutilizable, es decir debe de ser de alguna forma genérica en cuanto a la solución de un problema e diseño en específico por lo que la primera vez que uno usa un patrón para resolver un problema la siguiente vez que se encuentra con un problema similar ya tiene una herramienta más para solucionarlo y debe de poder aplicar el mismo patrón con éxito.

Pues bien eso es lo que es un patrón, y ya sabemos lo primero es identificar el problema que se tiene que solucionar, como siempre hay muchas formas de solucionar un problema pero siempre algunas de ellas son mejores que otras, pero esto también depende de la situación específica en la que se esté, ahora que es lo que sigue, pues empezar a llenar nuestra caja de herramientas aprendiendo algunos patrones y éstos los empezaremos a aprender en el transcurso de esta serie de posts (intercalados con otros temas de interés en el desarrollo de software), como primer patrón ya comentamos acerca de el patrón decorador y una situación muy específica en la que se usa.

Los patrones son importantes por que ayudan a solucionar de una forma "estándar" un problema y que puede ser aplicado en muchas ocaciones dando generalmente un software con mejor diseño, por lo que será mas desacoplado, testeable y mantenible.


sábado, 7 de mayo de 2016

Patrón decorator para validar

Cuantas veces hemos oido de el principio de responsabilidad única (Single responsability) de los principios SOLID, en el que dice que una clase debe de tener una y sólo una responsabilidad, eso dice la teoría, pero ya en la práctica es muy dificil de cumplir ese principio y una de las razones de ello es derivado de las validaciones ya que uno dice que cierta clase debe de hacer cierta acción, pero a su vez para poder hacer esa acción es necesario validar algunas cosas, por ejemplo que un atributo no sea null, pero entonces lo que pasa es que esa clase ya no tiene una sola responsabilidad, sino que aparte de hacer su chamba también tiene que validar algunos valores, en este caso que algo no sea null. En este tipo de escenarios es en donde entra en juego una de las variantes del patrón decorador, con el que lo que hacemos es que la clase base sólo hace su chamba y nada más que eso, y las validaciones pues las creamos como una decoración de la clase base y de esta forma tenemos dos clases donde cada una de ellas tiene una responsabilidad única, una hacer el "negocio" principal y la otra el de validar pero pues veamos algo de código.

veamos la clase, por ejemplo Report

public class Report {
    public byte[] getBytes(File report) {
        if(report != null) {
            if (report.exists()) {
                return getBytesFromFile(report);
            } else {
                throw new FotoEmpleadoInvalida("The report doesn't exists");
            }
        } else {
            throw new IllegalArgumentException("Unknown report");
        }
    }

    private byte[] getBytesFromFile(File report) {
        return new byte[0];
    }
}

en esta clase se tiene el método getBytes con el que se obtiene un arreglo de bytes que contiene el reporte listo para ser descargado, como vemos, se hacen ciertas validaciones antes de que se genere y descargue el arreglo de bytes, parece todo bien no? pues entonces de lo que hablamos antes, Single responsability, en este caso esta clase hace validaciones y la conversión y obtención del arreglo de bytes del reporte, pues bien, acá es donde podemos aplicar el patrón decorador para separar las validaciones de lo demás quedando las clases de la siguiente forma:

public interface Report {

    public byte[] getBytes(File report);
}

public class NormalReport implements Report {

    @Override    public byte[] getBytes(File report) {
        return getBytesFromFile(report);
    }

    private byte[] getBytesFromFile(File report) {
        return new byte[0];
    }
}

public class ReportWithFileExistsValidarion implements Report {

    private final Report report;

    public ReportWithFileExistsValidarion(Report report) {
        this.report = report;
    }

    @Override    public byte[] getBytes(File file) {
        if (file.exists()) {
            return this.report.getBytes(file);
        } else {
            throw new FotoEmpleadoInvalida("The report doesn't exists");
        }
    }
}

public class ReportWithNullValidation implements Report {

    private final Report report;

    public ReportWithNullValidation(Report report) {
        this.report = report;
    }

    @Override    public byte[] getBytes(File file) {
        if (file != null) {
            return this.report.getBytes(file);
        } else {
            throw new IllegalArgumentException("Unknown report");
        }
    }
}

y la forma en que se usan estas clases es:

public class Main {
    public static final void main(String... args) {
        Report report = new ReportWithNullValidation(
                new ReportWithFileExistsValidarion(
                        new NormalReport()));
        
        byte[] reportInBytes = report.getBytes(new File("report.csv"));
    }
}

como se ve, se crea una interfaz que define que método debe de existir, y de allí se definen 3 implementaciones de esa interfaz, en donde una de ellas es la que hace el "negocio" de obtener y transformar el reporte y esa es su única responsabilidad, mientras que las otras dos implementaciones se dedican exclusivamente a hacer la validación que le corresponde a cada una, pero estas dos implementaciones a diferencia de la primera reciben en su constructor un Report, con lo que se puede ir haciendo una cadena de validaciones hasta llegar al "negocio" y así poder ejecutar la ación esperada.

A esto que sucede acá es a lo que se llama "decoración" ya que se tiene un "negocio" que se quiere hacer y que está encapsulada en una clase específica y luego esa clase se "decora" con otra que se dedica a hacer la validación de existencia del archivo y luego esa clase se "decora" con  la que se encarga de hacer la validación de que le parámetro no sea nulo, así aplicando este patrón se logra que cada una de las clases tenga una responsabilidad única.

Pues bien, chingón, ya se tiene todo bien separado y demás, pero ahora ¿cuál es la ventaja de tener las clases así? pues bien aunque al parecer es más código, esto nos da la ventaja de que las clases sólo cambian por una única razón por lo que posibles errores y cambios son mas localizados y si se quiere se pueden agregar mas validaciones con más decoraciones de ser necesario, por ejemplo si ahora nos dicen que sólo los reportes con extensión .txt son soportados basta con hacer el nuevo decorador y unirlo a la cadena de llamadas o si se encuentra un bug en como obtener el arregla de bytes del archivo pues se sabe específicamente en que clase se debe de hacer el cambio. Otra gran ventaja es la testeabilidad ya que al depender de una interfaz solamente, en las clases de tests se pueden crear mocks y pasarlos como parámetros y así poder testear cada parte por separado.