Canales en Go

Los canales son la característica que Go nos facilita para comunicar entre sí goroutines y poder sincronizar su ejecución.
var c chan string = make(chan string)
El tipo canal se representa con la palabra chan y, a continuación, el tipo de los datos que viajaran a través de dicho canal. En el ejemplo de arriba he declarado la variable c, que contendrá un canal para transferir datos de tipo string. En la misma línea de código he usado make para crear dicho canal que, como puedes observar, se asigna a la variable c.

Para enviar o recibir datos por el canal has de usar el signo <- justo delante o detrás del canal de la manera que sigue.
c <- "Enviando por el canal"
var mensaje := <- c
Esta operación es síncrona, por tanto, el emisor esperará hasta que el receptor está preparado para recibir el envio. Si usas un canal con buffer, la operación será asíncrona, y por tanto, éste bloqueo sólo tendrá lugar cuando el buffer esté lleno.
c := make(chan int, 1)

Go testing

Go incluye un programa llamado go test que te será de gran utilidad para poner a prueba funciones de tu código. Esto es realmente útil para asegurarte de que todo funciona como debería hacerlo después de añadir características o de realizar cambios importantes en tu desarrollo. Para poder fabricar un ejemplo con el uso de go test, supongamos que has escrito un archivo llamado math.go, y que dicho archivo contiene una función que sirve para calcular el promedio de un conjunto de números:

package math

func Average(numbers []float64) float64 {
  total := float64(0)
  for _, x := range numbers {
  total += x
}
return total / float64(len(numbers))

Para preparar pruebas para esta función, sólo tienes que escribir un archivo con el mismo nombre que el archivo que contiene la función a probar, pero en lugar de finalizar en .go lo hará en _test.go. El compilador de Go ignora los archivos que finalizan de este modo cuando usas go install o go build. Como queremos fabricar pruebas para la función Average, en nuestro nuevo archivo vamos a crear una función llamada TestAverage. La función probadora debe empezar con la palabra Test para que go test la ejecute. Te muestro el código que habría en math_test.go y te sigo explicando...

package math

import "testing"

func TestAverage(t *testing.T) {
  result := Average([]float64{2,4})
  if result != 3 {
    t.Error("Expected 3, got ", result)
  }
}

Después de definir el paquete, que es el mismo que el del archivo que contiene la función que estamos probando, has de importa el paquete testing, porque las funciones probadoras usan el tipo *testing.T como parámetro. Dentro de la función probadora, TestAverage, tienes que usar la función que va a ser probada, que en este caso es la función Average. La idea es sencilla, se trata de que le pases a la función Average unos parámetros que generen unos valores de salida que conozcas de antemano, y así podrás comparar los valores devueltos por la función que estás probando con los que tú ya sabes que debería devolver. En el ejemplo se pasan los valores 2 y 4, cuyo resultado previsto, su promedio, es 3. En el caso de que la función Average no devolviera 3 se usa t.Error, que es similar a fmt.Println, con la finalidad de indicarle al programa go test que se ha detectado un error.

Todo listo, ahora sólo te resta ejecutar go test, el cual te debería mostrar un resultado similar al que sigue.
$ go test
PASS
ok    goWorkspace/src/Repository/Project/math    0.029s

State en React

Ya has visto como configurar componentes con props en React, pero ¿cómo puedes definir comportamientos o interacciones con dichos componentes? Para ello necesitas que los componentes puedan definir su estado, y con las props es imposible, pues no pueden ser modificadas por el componente, sólo por su componente padre. Para esto existe this.state, donde los componentes pueden disponer de datos privados modificables a traves de la función this.setState().

Ya sabes que función usar para ajustar this.state, pero ¿Cómo podrías definir un estado inicial del componente? Bien, pues para eso disponemos del constructor de clase. En la función render comprobamos el estado del componente para decidir como va a ser mostrado, y ahora viene la magia: cuando modificamos el estado de un componente, automáticamente se volverán a renderizar todos sus componentes hijos y el propio componente. Esto, además, es bastante ágil gracias al DOM virtual de React.

class Dashboard extends Component {
  constructor() {
    super(...arguments);
    this.state = {
        showAdvancedFeatures: false
    }
  }

  render(){
    let advancedFeatures;
    if(this.state.showAdvancedFeatures){
      advancedFeatures = (
        <AvancedFetaures/>
      )
    }
    return (
      <div className="dashboard">
        <BasicFeatures/>
        {advancedFeatures}
      </div>
    );
  }
}
 

Props en React

React es una biblioteca de JavaScript que se basa en la fabricación y combinación de componentes para construir interfaces de usuario. Cada componente se define por separado en un archivo javascript, y tiene un aspecto similar a este que sigue, el cual se encontraría en el archivo listaCompra.js:

import React, { Component } from 'react';
import Articulo from './Articulo';

class ListaCompra extends Component {
  render() {
    return (
      <ul>
        <Articulo cantidad="1">Pan</Articulo>
        <Articulo cantidad="6">Leche</Articulo>
        <Articulo cantidad="2">Huevos</Articulo>
      </ul>
    );
  }
}

Las propiedades, que veremos en el código escritas como props, se usan para configurar componentes, y son pasadas desde los componentes padres a los componentes hijos. Es importante recordar que el componente hijo no puede modificarlas, el propietario es el componente padre.

En el ejemplo anterior, el componente ListaCompra usa otro componente que aún no hemos escrito, el componente Articulo. En el JSX que devuelve su método render las props son pasadas al componente hijo como etiquetas de atributos similares a las de HTML. En nuestro caso se está pasando la propiedad cantidad. El contenido entre las etiquetas de apertura y cierre también se puede usar como propiedad del componente hijo. En ListaCompra se trata del nombre del artículo.

import React, { Component } from 'react';

class Articulo extends Component {
  render() {
    return (
      <li>
        {this.props.cantidad}× {this.props.children}
      </li>
    );
  }
}

Buscador de texto en Neovim

Otro recurso importante que vas a necesitar en el editor es un buscador de textos. Ante el hecho de que el proyecto que permitía el uso de El surfero de plata en vim, ag.vim, ha quedado obsoleto, te podrías decantar por ack.vim. Con ack.vim puedes hacer uso de ack, que no es ni más ni menos que un grep optimizado para programadores.

Instalar ack es bastante sencillo en distribuciones Linux deribadas de Debian.
$ sudo apt-get install ack-grep
La pega es que, como el paquete ack ya existe, ack es empaquetado como ack-grep. Esto supone teclear más al usar el comando en consola, pero lo puedes solucionar usando las desviaciones de la siguiente manera:
$ sudo dpkg-divert --local --divert /usr/bin/ack --rename --add /usr/bin/ack-grep
Listo, ya dispones de la herramienta ack. Ahora, para poder usarla en tu editor Neovim, sólo añádela como un Plugin de un modo similar a como hicíste con fzf aquí.
" ¡Cualquier URL de git es admitida por vim-plug!
Plug 'https://github.com/mileszs/ack.vim'
Luego en Neovim, ejecuata el comando PlugInstall ack.vim. Está bien familiarizarse con los comandos de vim-plug, así que échales un vistazo aquí.

¿Cómo se usa ack en Neovim? Sencillo...
:Ack [options] {pattern} [{directories}]
Y aquí están los atajos disponibles con esta herramienta.

Buqueda de archivos en Neovim

fzf se define a sí mismo como un buscador difuso de línea de comandos para propósitos generales. Más detalladamente, se trata de un filtro para líneas de comandos Unix, y que puedes aplicar a listas, archivos, procesos, históricos de comandos, etcétera.

Lo puedes instalar en tu carpeta home clonando su repositorio en GitHub de la siguiente manera:
$ git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf

Luego sólo tienes que ejecutar el script de instalación:
$ ~/.fzf/install

Ahora viene lo mejor, y es que fzf puede ser usado como un plugin de Neovim. Si usas el gestor de plugings vim-plug, que aprendimos a instalar aquí, es muy sencillo preparar nuestro buscador de archivos, sólo habría que añadir las siguientes líneas al documento de configuración ~/.config/nvim/init.vim:
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim'

Para ejecutar fzf cómodamente en neovim puedes asignarle una combinación de teclas, por ejemplo Ctrl + p.
nnoremap <c-p> :FZF<cr>

Cómo instalar vim-plug para Neovim

vim-plug es un gestor de paquetes para Neovim con características muy interesantes. Lo tienes disponible en https://github.com/junegunn/vim-plug, donde puedes encontrar toda la información necesaria para usarlo. Su instalación en sistemas Unix se puede realizar con un sencilo comando:
$ curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vi

Una vez instalado sólo tienes que preparar un archivo de configuración en la dirección ~/.config/nvim/init.vim. Aqui abajo tienes un ejemplo con alguna información:
" Inicia la configuración usando el comando call plug#begin(),
" con el cual puedes especificar el directorio donde se colocarán
" los plugins que queremos usar en nuestro editor.
" En el caso concreto de Neovim puedes usar ~/.local/share/nvim/plugged.

plug#begin('~/.local/share/nvim/plugged')


" A continuación se solicitarán los plugins necesarios. Hay muchos modos de
" hacerlo, por ejemplo, usando una dirección URL de Github.

Plug 'https://github.com/junegunn/vim-github-dashboard.git'


" Finalmente cierra el archivo de configuración con el
" comando call plug#end().

call plug#end()

Para probarlo abre Neovim y ejecuta el comando PlugInstall. Verás un panel lateral donde se muestra el estado de instalación de los plugins indicados en el archivo de configuración de vim-plug.

El workspace de Go

Estoy convencido de que tienes un estilo personal para organizar tu código, pero cuando trabajas con Go, es conveniente que te adaptes al estilo de su wokspace. El workspace de Go es una carpeta que se compone, a su vez, de otras tres carpetas: bin, pkg y src. Mi workspace, o espacio de trabajo, para los proyectos escritos en Go es ~/Documents/projects/go, por tanto, ahí creé la carpeta src, en la cual guardo los distintos trabajos escritos en este lenguaje.

~/Documents/projects/go/src/project1
~/Documents/projects/go/src/project2
etc...


Cuando elijas cual será tu workspace es fundamental que configures Go para que conozca cual es su ubicación. Para esto, únicamente tienes que apuntar la variable de entorno $GOPATH a dicha dirección. En mi caso:
$ export GOPATH=$HOME/Documents/projects/go
En el workspace habrá una carpeta que contenga binarios, así que no olvides añadirla a tu $PATH:
$ export PATH=$PATH:$GOPATH/bin
Por último, es recomendable que las añadas al archivo de configuración de tu terminal para, de este modo, no tener que definirlas repetidamente al iniciarlo.

Cuentos de bichos: Estrategia de gestión de errores

En entradas anteriores te comenté el origen de los errores de software y realicé una pequeña y divertida clasificación. Hoy sigo con la temática bichos para recomendarte una aproximación interesante al modo de gestionar aquellos errores que, en ocasiones, puedan aparecer en tu código. Hay cuatro preguntas fundamentales que deberías hacerte a ti mismo para definir tu estrategia en lo referente a la gestión de cada casuística de error en tu desarrollo:

1. ¿Voy a mostrar estos errores?

Si bien es cierto que en un entorno de desarrollo esto es más que necesario hacerlo, en producción, el hecho de mostrar los errores de nuestra aplicación con toda la información que pueden facilitar es, cuando menos, una invitación a hackearla. Añade a esto que tu desarrollo parecerá mal diseñado y poco profesional a ojos de los usuarios y clientes. Es fundamental, por tanto, que puedas manejar la visibilidad de las notificaciones de error de tu aplicación según el entorno en el que se esté ejecutando, y que nunca se muestren en producción.

2. ¿Voy a registrar estos errores?

Anotar las notificaciones de error en un registro donde poder consultarlas más tarde es un modo excepcional para rastrear posteriormente sus causas. También disponemos de la posibilidad de, por ejemplo mediante syslog, realizar esta gestión a través del sistema operativo.

3. ¿Voy a ignorar estos errores?

Pueden darse errores que no resulten críticos para tu ampliación, como puede ser el intento de lectura de un archivo de configuración inexistente. En este caso, la función de lectura podría lanzar un error crítico que detuviera la ejecución de tu aplicación, sin que el usuario haya recibido ningún tipo de información sobre dicha interrupción. En este caso puede ser interesante ignorar el error para preservar la ejecución.

4. ¿Voy a actuar frente a estos errores?

Seguimos con el caso anterior. Al ignorar el error has evitado un cierre inesperado de la aplicación. Con el fin de facilitar un poco más de información a tu usuario, una vez echo esto, hay que comprobar si disponemos del archivo y podemos hacer uso de él. En el caso que comentamos, no es así, pero ahora podemos informar al usuario de que no ha sido posible disponer del archivo de configuración, informar de posibles causas y soluciones y, a continuación, cerrar nosotros mismos la aplicación de un modo elegante.

La combinación de respuestas frente a estas cuatro preguntas te ayudarán a determinar, de un modo sencillo, tu estrategia de gestión para cada casuística de error.

Cuentos de bichos: Bestiario

Heisenbug

Fisonomía

 Toma su nombre del físico especializado en mecánica cuántica Werner Heisenberg, quien dedujo que el mero hecho de observar un sistema de una manera determinada altera el estado de éste. Cuando se usan herramientas durante el proceso de depuración para localizar y eliminar bichos, se producen pequeñas diferencias respecto al entorno de producción, es decir, con respecto al entorno final en el cual deberá funcionar nuestro dispositivo de software. El Heisenbug es especialista en aprovechar cualquiera de estas leves diferencias para mostrar comportamientos distintos que confundan al programador o para simplemente desaparecer.

Habilidad principal

 Su principal fortaleza consiste en la capacidad de mutar o desaparecer cuando se siente amenazado por un depurador.

Capacidad de destrucción

 Es especialmente destructivo con respecto a los compromisos de entrega de software, pues puede elevar muchísimo los tiempos de depuración. Se conocen casos de programadores que, víctimas de la desesperación, han propuesto depurar en el entorno de producción para localizar y destruir a este esquivo bicho.

Bohrbug

Fisonomía

 Debe su nombre al modelo atómico que desarrolló el físico Danés Niels Bohr para explicar, entre otros hechos, la estabilidad de la materia. El Bohrbug puede atormentar amargamente al cerebro lógico de un desarrollador, pues tan lógico seso no comprenderá como dicho bug sigue mostrándose una y otra vez, impasible, ante las innumerables correcciones realizadas en el código con el ánimo de destruirlo.

Habilidad principal

 Es conocido por su capacidad de permanecer inalterable ante cualquier acción de depuración.

Capacidad de destrucción

 Como suele presentarse en etapas tempranas, y se detecta con facilidad en pruebas y depuraciones, a lo que ataca principalmente es al orgullo y a la paciencia de los programadores.

Mandelbug

Fisonomía

 El conjunto fractal descubierto por Benoit Mandelbrot, un monstruo matemático de gran complejidad, inspiró el nombre de este bicho. Su modo de operar consiste en cimentar su existencia en causas tan complejas que sea difícil comprenderlas y atacarlas. Debido a esto, su comportamiento parece caótico, pues tras cada solución aplicada en el código, únicamente se conseguirá que el bicho actúe de un modo distinto, pero no quedará eliminado.

Habilidad principal

 Es capaz de formarse a sí mismo a partir de una combinación de pequeños detalles en muchísimas porciones de código aparentemente inconexas. Dar con la combinación que lo sustenta puede llegar a ser una ardua tarea de ingeniería inversa.

Capacidad de destrucción

 No es un bicho que se muestre en las últimas fases del desarrollo, así que se detecta a tiempo para depurarlo, pero es ahí donde radica su máximo poder. Destruir un Mandelbug puede ocasionar que se deba corregir muchas porciones de código, creando otros tipos de bugs distintos y alterando la arquitectura y la lógica de la aplicación. Puede, por tanto, herir gravemente e incluso malograr un proyecto a la mitad de su desarrollo.

Schroedinbug

Fisonomía

 Schrödinger describió una paradoja según la cual, teniendo un gato en una caja, no podemos saber si está vivo o muerto hasta abrir dicha caja, y por lo tanto se considera que se encuentra vivo y muerto a la vez hasta que la abramos. Esta paradoja aplica a la perfección a los Schrodinbugs, pues dichos bichos no se manifiestan hasta que alguien, leyendo el código o usando el programa de un modo poco habitual, descubre que nunca debería haber funcionado. ¡Desde ese momento, la caja queda abierta, y en el programa se muestra una y otra vez el bug que parecía no haber existido nunca!

Habilidad principal

 Su capacidad de permanecer invisible el mayor tiempo posible y su omnipresencia una vez determinada la certeza de sus existencia.

Capacidad de destrucción

 Depende de la parte que ataque de nuestra aplicación, pero el principal peligro que acarrea este tipo de bichos es la dificultad de una detección prematura, lo cual lo hace muy peligroso.

Stotle

Fisonomía

 Es más que un simple bicho, es la idea de bicho atormentando la mente de un desarrollador que ha sido engañado, confundido. Se trata de introducir, sin ser conscientes, datos incorrectos en la entrada del programa. Al percibir que la salida no es correcta, y estando convencidos de que la entrada si lo era, comenzamos a buscar un bicho que no existe, y que ocupará durante un buen rato nuestro tiempo y nuestra mente. Es como si teclearas en una calculadora la multiplicación de dos por tres, cuando realmente quisiste teclear la suma de estos números. Al ver el resultado de seis en lugar de cinco dudarás del correcto funcionamiento del artilugio, e intentarás arreglar algo que no estaba roto. Su nombre deriva de Aristóteles (Aristotle) porque del mismo modo que Aristóteles no era cuestionado antiguamente, y se asumía que debía estar en lo cierto, el programador no cuestiona la entrada de datos, asumiendo que hay un bicho en el programa.

Habilidad principal

 Hacer creer a los programadores que existe.

Capacidad de destrucción

  Dado que no es más que una idea de bug, no existe, no es peligroso para el proyecto en sí. No obstante, puede desquiciar a algún desarrollador.

Bugs de fase lunar

Fisonomía

 Son aquellos bichos que se muestran por los motivos más aleatorios o esotéricos que se puedan imaginar. Son fallos en el programa que únicamente suceden cuando la lluvia cae sobre los cristales de las ventanas de la oficina, cuando la chica rubia de recursos humanos pasa por delante de la puerta del despacho donde trabaja el equipo de desarrollo, cuando el aire acondicionado está a veinticuatro grados...

Habilidad principal

 No pertenecen al mundo lógico y racional del desarrollo de software.

Capacidad de destrucción

   Mientras no exista dentro del endémico grupo de probadores o depuradores una especialización en exorcismos de dispositivos de software, o algo similar, estos bichos harán estragos allá donde quieran pulular.

Fantasmas en el código

Fisonomía

   Estos bichitos suelen ocultarse en rutinas o subprogramas que se usan en raras ocasiones y, a diferencia del Schroedinbug, no es necesario detectarlos para que se materialicen. Son muy difíciles de descubrir en las fases de desarrollo o pruebas.

Habilidad principal

    Se mostrarán motu proprio en el peor momento posible, ya sea cuando estemos presentando el proyecto finalizado a nuestro cliente o cuando lo hayamos puesto en producción.

Capacidad de destrucción

   Debido a su habilidad para ocultarse y aparecerse en el momento más inconveniente, pueden herir principalmente la imagen del equipo de desarrollo.