lunes, 14 de marzo de 2016

Enums: Campos de arreglo

Usando arreglos en campos del enum. En este ejemplo utilizado para agragar los lenguajes soportados por una tienda.

public enum StoreCode {
 
    BR(Language.pt_BR, Subdomain.BR, Language.pt_BR, Language.en),
    US(Language.en_US, Subdomain.WWW, Language.en_US)
    // ....
    ;

    private final Language defaultLanguage;
    private final Language [] supportedLanguages;    
    private final Subdomain subdomain;
    
    StoreCode(Language defaultLanguage, Subdomain subdomain, Language ... supportedLanguages) {
        this.defaultLanguage = defaultLanguage;        
        this.subdomain = subdomain;
        this.supportedLanguages = supportedLanguages;
    }

    public Language getDefaultLanguage() {
        return defaultLanguage;
    }

    public Subdomain getSubdomain() {
        return subdomain;
    }

    public Language[] getSupportedLanguages() {
        return supportedLanguages;
    }
}

viernes, 12 de febrero de 2016

Enums: Buscando valores de manera invertida

Un tip interesante para simplificar la búsqueda en un enum por alguna de sus propiedades. En este ejemplo tenemos un enum para tiendas de países. Una de sus propiedades es el subdominio. Si queremos tener un método para retornar el valor de la tienda usando como entrada el subdominio, podemos preparar un mapa de manera estática donde la llave es el subdominio.

public enum CountryStore {

    AD(Language.en, Measures.METRIC, Subdomain.AND),
    AE(Language.en, Measures.METRIC, Subdomain.AE),
    AF(Language.en, Measures.METRIC, Subdomain.AF),
    ...

    private final Language defaultLanguage;
    private final Measures defaultMeasure;
    private final Subdomain subdomain;    

    CountryStore(Language defaultLanguage, Measures defaultMeasure, Subdomain subdomain) {
        this.defaultLanguage = defaultLanguage;
        this.defaultMeasure = defaultMeasure;
        this.subdomain = subdomain;
    }

    private final static Map<String, StoreCode> subdomainMap;

    static {
        // Reverse lookup preparation for subdomains.        
        Map<String, CountryStore> smap = new HashMap<String, CountryStore>();
        
        for(CountryStore store: CountryStore.values()) {
            smap.put(store.getSubdomain().name().toLowerCase(), store);
        }
        subdomainMap = Collections.unmodifiableMap(smap);
    }

    public static CountryStore fromSubdomain(String subdomain) {
        return subdomain == null ?  null :  subdomainMap.get(subdomain.toLowerCase());
    }

}


viernes, 18 de septiembre de 2015

Programación Reactiva: Reactive Extensions Library o RX (comenzado a aprender esta cosa de Reactive)



Encontré un buen video explicando la programación reactiva en el sabor de la librería Reactive Extensions hecho por Jafar Husain (Líder técnico en Netflix) . Aquí un pequeño resumen de los principales conceptos que extraje.

Event Reacting
El término reactivo se puede asociar por analogía con alguien tirando un montón de bolas hacia uno al mismo tiempo. Tienes que reaccionar rápidamente para tratar de atraparlas todas. Uno no tiene control sobre cuándo quiere que las pelotas sean lanzadas, sólo hay que estar preparado para la captura de ellas.

Para empezar a entender Rx (Reactive Extensions), necesitamos tener en mente dos patrones fundamentales de diseño en consideración: Iterador y Observador.

En Java tenemos la interfaz Iterable, que es una interfaz que cualquier tipo de colección puede implementar para permitir a los consumidores de esa colección obtener objetos uno a la vez. Así es como en Java podemos utilizar el operador foreach para recorrer una colección. Debido a que la interfaz proporciona un específico Iterator para el tipo de datos que estamos consumiendo en la colección.

Tres cosas pueden pasar cuando usamos un iterador:
  1. Obtener el siguiente item
  2. No hay más items para consumir (fin del flujo  de datos)
  3. Un error sucedió (en Java mediante el uso de excepciones)
El patrón Obervador es otro famoso patrón de diseño donde subscriptores se subscriben a ciertos temas para poder ser notificados cuando un cambio ocurre. Si analizamos este patrón encontramos que es muy similar al patrón Iterador en el sentido que existe un productor y un consumidor; la principal diferencia es que en el Observador el productor está en control de cuando enviar los datos, mientras que en el Iterador el consumidor es el que está en control. El es el que decide cuando tomar los datos del productor.

Iteratot Observer Fusion
Pero hay dos aspectos principales "ausentes" del patrón Observador que si están presentes en el patrón Iterador:
  • Una manera de indicar que no hay más datos
  • Una manera de indicar que un error acaba de suceder
En el Observador uno solamente puede subscribir un callback para recibir datos, pero no puede registrar callbacks para el evento donde se indica que no hay más datos siendo encolados en el stream (evento de completado), o para indicar que un error sucedió. RX trata básicamente de unificar el "acueducto" del Observador con el "acueducto" del Iterador produciendo un nuevo tipo llamado el Observable, el cual proporciona la misma semántica de ambos patrones.

Hay un montón de operaciones interesantes que se pueden realizar sobre los iterables. En SQL existen un gran número de operaciones que se pueden hacer sobre conjunto de datos: filtrar, seleccionar, ordenar, etc. Que tal si todas esas mismas operaciones que podemos ejecutar sobre datos alojados en una tabla, pudiéramos también hacerlo sobre eventos (datos que llegan). Eso no es una fantasía con RX. Es posible escribir sentencias al estilo SQL sobre eventos. La diferencia es que la consulta es evaluada conforme llegan los datos. Uno puede evaluar datos en tiempo real.

Cada vez más el código se esta volviendo orientado a eventos. Tenemos un montón de llamadas asincrónicas en el lado del cliente (JS), y del lado del servidor (Node.JS). Esto agrega mucha complejidad en la aplicación que intenta manejar todos estos callbacks. RX provee el nuevo tipo de datos Observable para establecer una manera poderosa de modelar eventos. Al completar las semánticas faltantes (fin de flujo de datos y error), ahora uno puede aplicar operaciones familiares que hacemos sobre colecciones como map, filter, reduce, merge, zip, etc. Todas estas cosas podemos hacerlas sobre flujo de datos también.

Imaginemos la nueva Java 8 Stream API sobre datos que llegan dinámicamente por eventos lanzados hacia uno. Muchas cosas pueden mejorar en la aplicación como enviar datos al consumidor mucho más rápido, por citar solo un ejemplo.

Aún necesito aprender mucho más de este nuevo paradigma, pero al menos pienso que este video cubre los conceptos fundamentales que necesitamos tener de antemano antes de arrojarnos a jugar con RX en el código.

miércoles, 24 de junio de 2015

¿Es esto arquitectura?


Interesante artículo de Gregor Hohpe que nos enseña por analogía lo que una documentación de una arquitectura de Software debería contener. Muy resumidamente, una descripción de arquitectura de Software debería mostrar decisiones no triviales u obvias hechas en un sistema. Por ejemplo, describir que en el sistema hay una separación de capa de presentación (Front-End) con la capa de datos (Back-End), es lo mismo que decir que en una casa tenemos puertas que tocan el piso para que la gente pueda caminar por ellas.

Quizás determinar que es trivial y qué no lo es puede despertar sospechas de que estamos en terreno de lo subjetivo, pero creo que a como maduramos como desarrolladores de software, y vamos obteniendo experiencia observando patrones recurrentes en los diseños de sistemas en los que participamos, se va volviendo un poco más claro cuando algo es digno de ser documentado. Esto se nota también en el plano del código de programación cuando intentamos que el mismo sea auto-descriptivo y solo comentamos lo que no parece obvio de entender.