Mostrando las entradas con la etiqueta programming. Mostrar todas las entradas
Mostrando las entradas con la etiqueta programming. Mostrar todas las entradas

viernes, 3 de febrero de 2017

Patrón Observador




Hemos vuelto, esta vez escribo sobre el patrón observador (the observer pattern), este patrón es muy simple y se usa cundo se require que alguien se entere de que algo ha sucedido dentro de otro ámbito, de allí su nombre, veremos un ejemplo sencillo:

Lo primero que se requiere es una interface Observer de quien saldrán las implementaciones que serán los Observadores:

public interface Observer {
    void update();

}

Luego tendremos otra interface Observable que es la que va a implementar nuestra objeto que necesitamos que notifique sus cambios de estado:

public interface Observable {
    public void addObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notifyObservers();

}

Ahora las implementaciones, primero veamos la implementación de Observable:

import java.util.ArrayList;
import java.util.List;

public class Invoice implements Observable {

    
    private String serialNumber;
    
    private String status;
    
    public Invoice(final String serialNumber) {
        this.serialNumber = serialNumber;
        this.status = "new";
    }
    
    public String getSerialNumber() {
        return serialNumber;
    }
    
    public String getStatus() {
        return status;
    }
    
    private List<Observer> observers = new ArrayList<Observer>();
    
    public void markAsPaid() {
        notifyObservers();
    }
    
    public void addObserver(final Observer observer) {
        this.observers.add(observer);
    }

    public void removeObserver(final Observer observer) {
        this.observers.remove(observer);
    }

    public void notifyObservers() {
        for(Observer observer : this.observers) {
            observer.update();
        }
    }


}

Por último las implementaciones de la interfaz Observer:

public class InvoiceStorer implements Observer {

    private Invoice invoice;
    
    public InvoiceStorer(final Invoice invoice) {
        this.invoice = invoice;
        this.invoice.addObserver(this);
    }
    
    public void update() {
        System.out.println("Guardando cambio de estado de la factura: " 
                + this.invoice.getSerialNumber() 
                + " a " + this.invoice.getStatus());
    }
    
    public String getInvoiceSerialNumber() {
        return invoice.getSerialNumber();
    }

}

public class InvoiceStatusChangeNotifyer implements Observer {

    private Invoice invoice;
    
    public InvoiceStatusChangeNotifyer(final Invoice invoice) {
        this.invoice = invoice;
        this.invoice.addObserver(this);
    }
    
    public void update() {
        System.out.println("Notificar pago de factura: " + invoice.getSerialNumber());
    }
    
    public String getInvoiceSerialNumber() {
        return invoice.getSerialNumber();
    }

}

Tenemos un test para probar la funcionalidad hecha:

import java.util.UUID;

import org.junit.Assert;
import org.junit.Test;

public class InvoiceTest {
    
    @Test
    public void markAsPaid(){
        String serialNumber = UUID.randomUUID().toString();
        Invoice invoice = new Invoice(serialNumber);
        InvoiceStorer storer = new InvoiceStorer(invoice);
        InvoiceStatusChangeNotifyer notifyer = new InvoiceStatusChangeNotifyer(invoice);
        invoice.markAsPaid();
        Assert.assertEquals(serialNumber, storer.getInvoiceSerialNumber());
        Assert.assertEquals(serialNumber, notifyer.getInvoiceSerialNumber());
    }

}
La salida del test es:

Guardando cambio de estado de la factura: db1a5606-2aad-475c-b4af-bf59f03975d4 a new

Notificar pago de factura: db1a5606-2aad-475c-b4af-bf59f03975d4

Ahora si vamos a ver lo que sucedió.

Lo primero es que los Observers al inicializarse se "registran" haciendo la llamada al método addObserver de la clase Invoice, este método llena una lista de observadores a la que al momento de que se actualiza su estado (método markAsPaid) les notifica del cambio hecho.

Cuando los observadores son notificados hacen uso de la instancia de su observable para hacer su trabajo, por ejemplo el InvoiceStorer se encargará de guardar el cambio de estado en la base de datos, mientras que el InvoiceStatusChangeNotifyer se encargará de enviar una notificación por correo electrónico informando del pago de la factura.

Como vemos, esto se pudo haber hecho en sólo el método de markAsPaid pero usando el patrón observador se puede hacer una mejor separación de responsabilidades.

martes, 18 de octubre de 2016

Que cosas hacen de Scrum?


Este post ya tiene rato en la congeladora, así que espero recordar bien lo que quería transmitir con él en ese momento de mi vida.

Hace unos meses alguien me hizo esta pregunta, ¿Qué hacen de Scrum?, la cuál me llamó mucho la atención ya que esta es una pregunta que normalmente hace alguien que no conoce de metodologías ágiles de desarrollo de software, mucho menos de Scrum, normalmente estas personas sólo han oído hablar, han leído del tema o los han "obligado" a la mala a "usarlo", por eso es que a ellos les hace sentido esa pregunta.

A parte de esto lo que yo leo en esta pregunta es desinterés y rechazo sobre el framework en sí ya que aunque se ha tenido el contacto no se ha tenido las ganas de de verdad conocerla y poder ver mas allá de su "uso".

Pero bueno, en ese momento puse mi cara de what? la sangre me hirvió y me dieron ganas de platicarle lo que realmente significa y que no es algo que se "usa", sino algo que se interioriza y se vive hasta el punto de convertirse en uno de tus principios de vida (ya se que suena muy mamón, pero de verdad que así es) pero pude contenerme y lo que me salvó fueron las siguientes preguntas de esta persona, las cuales me ayudaron a desafanarme del tema muy rápidamente, ¿sólo hacen junta diaria y ya verdad? y ¿también hacen sprints no? a las cuales mis respuestan fueron "heee (dudando) aaa si, solo eso hacemos", ya se que estuvo mal, pero en ese momento no quería entrar en discusiones ni detalles, solo me quería desafanar.

Gente, scrum no se usa, es un modo de ver el mundo, ágil en general lo es, si recordamos uno de los principios ágiles que dice:
"At regular intervals, the team reflects on how 
to become more effective, then tunes and adjusts 
its behavior accordingly"
Nos habla sobre lo que en scrum conocemos como retrospectivas, esto en lo personal me ha ayudado mucho a mí en vida de portero, cada vez que acaba un partido paso por mi mente una y otra vez los goles que me metieron y así visualizar que es lo que hice mal y que pude haber hecho en ese momento que me hubiera ayudado a que el balón no terminara en las redes. Parece algo simple, pero así es, y este es sólo un ejemplo de como es que yo "uso" scrum en mi vida.

Ahora, ven como es que esto se vuelve parte de tus principios, en este caso, la reflexión y la mejora continua.

A mis lectores, en verdad les recomiendo que lean, escuchen, vean, se involucren y entiendan lo que scrum y ágil en general les puede dejar en sus vidas, por la red rondan muchos sitios donde no sólo hablan de ágil en desarrollo de software, sino en la vida cotidiana por lo que aún si no te dedicas a la profesión de los 0's y 1's estaría muy bueno que le des una pasada, al menos para que no se te ocurra preguntar ¿Que cosas hacen de Scrum?.

Un abrazo a todos.

lunes, 5 de septiembre de 2016

Reduce regresando un objeto


La semana pasada escribí acerca de algunas funciones útiles en javascript, una de ellas es mas interesante de lo que parece, ésta es la función reduce, en ese post comentamos que lo usamos cuando tenemos que generar un sumarizado de un arreglo, en ese momento hicimos el conteo (sumarizado) de cachorros y de adultos, en sí esta forma es útil, pero a veces lo que queremos no es un sumarizado numérico, sino crear un objeto y que él sea el sumarizado.

Reduce nos sirve también en este caso de uso ya que la función también puede regresar el sumarizado como un objeto, no solo como un entero.

Otra cosa que mencioné es que no me había tocado usar alguna de estas funciones, pero ya en esta semana que pasó me tocó usar reduce, el caso de uso fue el siguiente:

Tengo un arreglo de bancos con los bines de tarjetas de crédito, en este caso lo que necesitaba es un arreglo de los bancos que tengo en la lista, por lo que usé la función reduce para "reducir" (sumarizar) el arreglo de bines de bancos en un arreglo de bancos, el código es como sigue:

var bines = [{"bank":"banco1","bin":"111111"},
     {"bank":"banco1","bin":"122222"},
           {"bank":"banco1","bin":"133333"},
     {"bank":"banco1","bin":"144444"},
          {"bank":"banco2","bin":"211111"},
     {"bank":"banco2","bin":"222222"},
     {"bank":"banco2","bin":"233333"},
     {"bank":"banco3","bin":"311111"},
     {"bank":"banco3","bin":"322222"}];

var reduced_banks = bines.reduce(function(banks, bin) {
isAlreadyAdded = banks.find(function(bank) {
return bank == bin.bank;
})
if(!isAlreadyAdded)
banks.push(bin.bank);
return banks;
}, []);
console.log(reduced_banks);

lo que sale a la consola es:


[ 'banco1', 'banco2', 'banco3' ]

Esto es, el listado de bancos.

Ahora, explicando un poco lo que sucede, tenemos un arreglo de bines en el que se repiten los bancos y lo que queremos es sólo el arreglo de bancos, lo que hacemos es usar la función reduce mandándole una función que recibe el objeto contenedor del sumarizado (banks) y el elemento actual de la lista original (bin), enviándole también a la función reduce un arreglo vacío como último parámetro ([]) que es el valor inicial de banks, luego reduce aplica a cada elemento del arreglo bines la función que le enviamos como primer parámetro donde lo que hacemos es buscar en el arreglo de bancos (banks)
si ya existe el banco del elemento en el que estamos de bines y si no ha sido agregado antes se agrega al arreglo banks (objeto simarizador). Como ven, también find es aplicado sobre un arreglo, en este caso banks y lo que hace es iterar sobre cada elemento del arreglo y a cada elemento le aplica la función  que le mandamos como parámetro y que regresa true si el arreglo ya contiene banco del elemento actual de bines.

Espero que este ejemplo sea didáctico en el uso de reduce y find, en este ejemplo el objeto sumarizador es un arreglo, pero bien puede ser cualquier otro tipo de objeto.

viernes, 26 de agosto de 2016

Algunas funciones útiles en javascript

Esto de cambiar de trabajo es muy interesante, la verdad es que uno está acostumbrado a cierto ritmo y al cambiar de trabajo tu día cambia mucho desde tomar otra ruta para llegar a la oficina, levantarte en un horario distinto hasta conocer gente distinta, reencontrarte con los antiguos camaradas, regresar a programar activamente y bueno pues como en todo encontrar problemas distintos a los ya habituales, un ritmo de trabajo distinto, un negocio distinto y cosas nuevas por aprender.

Dentro de estos cambios me ha tocado entender AWS, lo que ofrece y como manejar lo que tiene (en mi primer semana instalé dos veces en producción), algo de spring que ya tenía un poco empolvado y lo que más me ha costado, reencontrarme con los html, javascript y css, esos fueron mis amigos en mi primer trabajo hace mas o menos 10 años y desde entonces no me había tocado trabajar activamente en el front end de aplicaciones web de esta manera pues en Tralix me la pasé más con GWT, un poco de echo2 y muy poco de struts.

Y como parte de mi aprendizaje he estado viendo algunas cosas en javascrip que me llamaron la atención, en particular las funciones find, filter, map y reduce (que aún no he ocupado pero que ya son parte de mi toolbox) y de esas funciones es de lo que quiero hablar en este post. Comencemos con el arreglo definido de la siguiente manera:

mascotas = [
{
'nombre'  : 'max',
'especie' : 'perro',
'raza'    : 'dálmata',
'edad'    : '3',
'sexo'    : 'macho'
},
{
'nombre'  : 'yoshina',
'especie' : 'perro',
'raza'    : 'dálmata',
'edad'    : '5',
'sexo'    : 'hembra'
},
{
'nombre'  : 'luneta',
'especie' : 'perro',
'raza'    : 'dálmata',
'edad'    : '4',
'sexo'    : 'hembra'
},
{
'nombre'  : 'simba',
'especie' : 'perro',
'raza'    : 'dálmata',
'edad'    : '1',
'sexo'    : 'macho'
}
]

Find

La función find nos sirve para encontrar un elemento en un arreglo, por ejemplo si queremos encontrar a max dentro del arreglo lo que tenemos que hacer es:

max = mascotas.find(function(mascota) {
return mascota.nombre == 'max'
})
console.log(max)

y lo que nos va a imprimir en la consola es a max.

Filter

La función filter la usamos para obtener un sub arreglo del arreglo original, por ejemplo si queremos encontrar a todos nuestros perros machos lo que tenemos que hacer es:

machos = mascotas.filter(function(mascota) {
return mascota.sexo == 'macho'
})
console.log(machos)

en este caso nos imprimirá en la consola un sub arreglo conteniendo a max y a simba.

Map

La función map se usa cuando queremos transformar un arreglo en otro, esta es una función muy útil cuando se trabaja en un cliente de servicios REST ya que normalmente lo que el servicio nos trae son cosas generales y tal vez nosotros no queremos operar sobre todos los datos, sino sobre sólo algunos, espero esto no sea confuso, pero bueno, para que quede mas claro vamos a transformar nuestro arreglo de mascotas en un arreglo de edades de la siguiente forma:

edades = mascotas.map(function(mascota) {
return mascota.edad
})
console.log(edades)

Lo que nos imprime en la consola es el arreglo de las cuatro edades de nuestros perros (transformamos un arreglo de mascotas a un arreglo de edades).

Reduce

La función reduce normalmente la ocupamos cuando queremos generar un "sumarizado" o un resultado "agregativo" (jeje no supe como decirlo) sobre un arreglo, para que sea mas claro veamos el ejemplo:

cachorros = mascotas.reduce(function(total, mascota) {
if (mascota.edad <= 1)
return total +1
else 
return total
}, 0)
console.log(cachorros)

la salida a la consola que obtenemos es la cantidad de cachorros que hay en nuestro arreglo (los que son menores o igual a 1 año de edad), y la forma en que opera es que va iterando el arreglo, para cada elemento checa la edad de la mascota y si es un cachorro suma 1 al total, por cierto ese 0 "cero" extraño que se ve al final de la llamada a la función reduce es el valor inicial del total.

Lo bonito de esto es que muchas de estas funciones existen dentro de prácticamente todos los lenguajes funcionales y nos ayudan no solo en la programación del front end en javascript.

Otra cosa a hacer notar es que todas estas funciones reciben como uno de sus parámetros una función, esto las hace muy poderosas y reusables ya que por ejemplo si quieres obtener a los adultos (en el ejemplo del reduce) lo único que tienes que hacer es cambiar a función que recibe el reduce como parámetro, lo que se hace es sacar la función a por ejemplo:

cachorros = function(total, mascota) {
if (mascota.edad <= 1)
return total +1
else 
return total
}

y tener otra función:

adultos = function(total, mascota) {
if (mascota.edad > 1)
return total +1
else 
return total


y pasar uno u otra al reduce:

numero_cachorros = mascotas.reduce(cachorros(total, mascota), 0)

o

numero_adultos = mascotas.reduce(adultos(total, mascota), 0)

Con esto se ilustra una de las bondades de la programación funcional, el poder enviar funciones como parámetros.

Este post nos sirve como capítulo introductorio a la programación funcional, de la que estaremos hablando poco a poco.