Transacciones Offchain en Ethereum/RSK

June 27th, 2017

Anterior Post

Cada contrato en Ethereum/RSK tiene asociado un almacenamiento, el llamado “storage”. Este almacenamiento tiene celdas con contenido, accesibles por dirección numérica de celda  (32 bytes de dirección). El contenido de cada celda en Ethereum es la representación en bytes de un número de 32 bytes (en RSK, se ha conseguido modificar esto para que cada celda pueda albergar una cantidad arbitraria de bytes, a decisión del programador; hoy esta característica está solo disponible para contratos precompilados). Entonces, el almacenamiento de un contrato onchain (público en la blockchain, deducible desde la blockchain por cada nodo interesado de la red), es algo como:

(direcciones y contenidos simplificados). Cada dirección no usada tiene un valor asumido (cero en Ethereum, donde todos los contenidos son números enteros). Cuando el contrato se ejecute OFFCHAIN (fuera de la blockchain, como describí en el anterior post), el estado del almacenamiento se mantiene en la memoria del nodo ejecutante del contrato, y NO SE COMPARTE con el resto de la red. El estado offchain sólo es conocido por el nodo designado para ejecutar el contrato offchain. Este estado puede ser alterado enviando transacciones offchain al contrato, y haciendo calls offchain a ese contrato en ese nodo.

Un contrato offchain tiene código especial (escrito por el programador) que anuncia la confirmación (commit) del contrato. Esta operación es un nuevo opcode de la Ethereum Virtual Machine, se podría invocar desde código solidity también. Si la operación de commit es invocada entonces el contrato y el sistema EMITE una transacción ONCHAIN, a ser repartida, minada, validada y publicada por el resto de la red. La llamo la transacción delta. Es una transacción que cuando se ejecuta ALTERA el estado público, ONCHAIN, del contrato, para reflejar el nuevo estado OFFCHAIN. Para eso le basta tener información de los valores alterados NO TODA LA HISTORIA de las transacciones offchain que se ejecutaron:

Hay detalles a decidir, por ejemplo, el costo de esas transacciones y quién paga ese costo (mi primera respuesta: paga el que envió la transacción offchain que provocó la ejecución del commit).

La transacción delta comienza a tener sentido si su tamaño y costo es MENOR que el costo probable de ejecutar todas las transacciones OFFCHAIN enviadas como si fuera ONCHAIN. Podría ser así, por ejemplo, en los contratos que mantienen saldos de token por cuenta: las transferencias podría ser cientos, y afectar a POCOS saldos, y entones, alterar en poco el storage resultante.

Aunque estas ideas podrían ser algo difíciles de implementar en una red ya en ejecución como Ethereum, en RSK tenemos una implementación nueva, pero todavía en prueba, que podría aceptar fácilmente este tipo de nueva conducta soportada. Y estaría alineado con el propósito de RSK de llevar toda esta infraestructura a una escala que permita cientos o miles de transacciones por segundo, a bajo costo. El gran desafío es dar herramientas de desarrollo a gente que no está bancarizada o que no puede afrontar grandes costos de operaciones.

Próximos temas a tratar: la transaferencia de valor (ether) en las transacciones offchain, y cómo se transfiere ese valor en la delta transaction.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Propuesta Alternativa para el Contrato Remasc en Ethereum/RSK

June 26th, 2017

Desde el lanzamiento de la testnet pública de RSK, el código fuente ha sido publicado. Y ahora, puedo escribir sobre algunos detalles de la actual implementatión.

La plataforma Ethereum soporta el concepto de contratas precompilados: contratos que se implementan directamente en el código de cada nodo implementando, claro que respetando compatibilidad entre lenguajes de implementación. En el caso de RSK, se agregaron dos contratos precompilados: el contrato Bridge, y el contrato Remasc. En este post, quiero proponer una implementación alternativa al contrato Remasc (todavía sin una propuesta concreta en código, no hay una descripción oficial de la conducta esperada del contrato Remasc).

¿Qué es el contrato Remasc? Por lo que sé (recuerden, todavía no hay una descripción publicada del mismo, sólo el código), es un contrato que asigna premios a los mineros, examinando la actividad reciente de la blockchain en proceso. Para calcular y asignar esos premios, tiene estado relacionado con a los bloques pasados de la blockchain, no le basta con la información del bloque actual en proceso. Este estado está  en esta clase. Además, hay  una transacción especial Remasc AGREGADA a CADA bloque minado, al final de la lista de transacciones del bloque (no hay bloque válido SIN esa transacción Remasc). Así, que al final del proceso del bloque, esa transacción especial es ejecutada.

Pero, de acuerdo al Ethereum Yellow Paper, hay un paso especial en el proceso de un bloque:

11. Block Finalisation
The process of finalising a block involves four stages:
(1) Validate (or, if mining, determine) ommers;
(2) validate (or, if mining, determine) transactions;
(3) apply rewards;
(4) verify (or, if mining, compute a valid) state and nonce.

Entonces, mi primer propuesta consiste en eliminar ese transacción “agregada compulsivamente” en cada bloque, y usar el paso de finalización de un bloque para calcular y asignar los premios a los mineros. De esta manera, podemos eliminar el cálculo del nonce de la cuenta remasc, el armado y firmado de esa transacción, la inclusión de esta transacción para que el bloque sea considerado válido, la serialización de esos datos, el almacenamiento del transaction receipt…. bien, todos esos recursos pueden liberarse, veo que usar una transacción explícita puede simplificarse.  Para mí, tener un proceso de premiado implícito al final de un bloque es un modo más simple de hacer las cosas. Y ya saben mi preferencia: simplicity pays 🙂

La otra propuesta, a ser evaluada y explorada, es simplificar el uso del almacenamiento. El cálculo del próximo estado podría ser ejecutado con la información YA disponible en la blockchain en proceso, ya esa información está disponible. Así, el uso actual de almacenamiento (storage) en la implementación, es más un hack por performance, que algo estrictamente necesario (punto a revisar, porque al no tener una descripción de las responsabilidades del contrato, desconozco lo que tiene para hacer). El cálculo del próximo estado puede ser ejecutado apelando a la información de la blockchain. Si es necesario acceder a ese estado rápidamente, el contrato puede apelar a un cache en memoria. Si fuera necesario algún dato que NO se pueda obtener de la blockchain, ahi sí: eso va al storage, así todos los nodos pueden a partir de ahí calcular el nuevo estado. El storage en Ethereum es costoso, y RSK no es la excepción: en la implementación actual, luego de haber procesado 100000 en mi máquina con un nodo local conectado a la testnet, el espacio en disco ocupado por el contrato Remasc da cuenta de UN TERCIO del espacio total.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Transacciones Offchain en Ethereum/RSK (1)

June 21st, 2017

Siguiente Post

En Ethereum/RSK, un contrato inteligente tiene un ciclo de vida como:

Un contrato es una cuenta, tiene dirección pública y un balance como cualquier otra cuenta. Pero, además, tiene código asociado y almacenamiento. Las transacciones que recibe pueden tener valor a transferir y datos para invocar código. Y cada transacción tiene un costo, y se graba y publica en la blockchain.

En esta serie de post, quiero describir una posible implementación para soporte de transacciones “offchain”, que no vayan directas a la blockchain, sino que puedan estar en un lugar alternativo, manteniendo estado, sin usar el costo de la blockchain. Solo en algunos momentos el resultado DE VARIAS transacciones se publica en la blockchain. La idea es que un contrato puede estar en otros estados, además del estado normal:

Cuando un contrato está en el estado “offchain”, se ejecuta en un UNICO nodo designado, su nodo de ejecución, y no en toda la red. Las transacciones que recibe son ejecutadas solamente por ESE NODO, y no son agregadas a la blockchain. De esta manera, se pueden ejecutar muchas transacciones contra ese contrato con un costo mucho menor. Solamente cuando el contrato decide pasar de nuevo a modo normal, se emite un “commit” que genera una transacción “onchain”, que cuando se mina y ejecuta, actualiza de en un solo paso el estado de almaceniemto público del contrato en la blockchain. La llamo la transacción delta.

El cambio de estado de normal a “offchain” es disparada por código de contrato, con una nueva instrucción (que se implementa como un nuevo opcode de la máquina virtual Ethereum), para cambiar al estado “offchain”. Las transacciones “onchain” que se reciban de ahí en mas, no se procesan por el contrato. Solo se procesan las transacciones “offline” (podría alternativamente procesar TODAS las que vengan, desde el estado “offchain”, pero me parece más claro al principio, que los usuarios que envíen transacciones ESPECIFICAMENTE las marquen como “onchain” o como “offchain”). Entonces, todas las transacciones “onchain” se rechazan, y ningún minero las agrega a un bloque, mientras el contrato público esté marcado como “offchain” en la blockchain. Las transacciones “offchain” se reconocen con algún dato adicional, por ejemplo, podrían implementarse con campo “nonce” en –1, pero eso es un detalle de implementación a discutir.

De nuevo, el código de contrato es el que decide CUANDO pasar de “offchain” a normal, haciendo un “commit” o un “rollback” al estado público previo. Si decide hacer “commit”, cambia a un estado temporario de congelamiento, hasta que una transacción delta emitida en ese momento, sea minada e incorporada a la blockchain pública. Esta transacción delta tiene como misión actualizar el estado público del contrato para reflejar el estado privado que en nodo ejecutor tiene en ese momento del contrato. De esta manera, en vez de ocupar cientos o miles de transacciones, un contrato usa la blockchain cada tanto, sólo para actualizar el estado público usando este tipo de transacciones delta.

En los próximos posts describiré la transacción delta con más detalle, y discutiré los casos de TRANSFERENCIA de valor (no solo cambio de estado interno) en las transacciones “offchain”. Ahora que el código principal de RSK es público, puede que escriba alguna implementación liviana de estas ideas, como referencia concreta. Como dice Linus, “talk is easy, show me the code” 😉

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Multi-Blockchains en Ethereum/RSK

June 19th, 2017

La implementación de una blockchain incluye la creación, distribución y manejo de bloques como éste:

Un bloque, en Bitcoin, Ethereum o RSK tiene:

  • Un hash único en el sistema
  • Un bloque padre, identificado por un hash
  • Un número de bloque (que es uno más que el número de bloque del padre)
  • Una lista de transacciones

En el caso de Ethereum y RSK, una transacción tiene:

  • Una cuenta enviadora
  • Una cuenta receptora
  • Un valor a transferir
  • Datos adicionales (usados si la cuenta receptora es un contrato inteligente)

Una lista de bloques válidos encadenados forma lo que se llama una blockchain:

En Ethereum/RSK, un bloque también tiene:

  • Bloques tíos (“uncles”)
  • Dificultad asociada al bloque (la dificulta de la prueba de trabajo (“proof of work”) más la suma de las dificultades de los tíos)

De esta forma, la presencia de bloques tíos contribuye a la dificultad del bloque. Y este número suma a la dificultad TOTAL de la blockchain a la que este bloque se agrega. Varios nodos en la red, llamados mineros, generan bloques en la blockchain. Si hay varias alternativas, el algoritmo de consenso distribuido elige la blockchain con mayor dificiltad total:

(en Bitcoin, la blockchain más larga siempre gana; en Ethereum/RSK una blockchain más corta puede ganar a otra más larga si tiene mayor dificultad acumulada total).

Un problema es mantener el estado de todas las cuentas y contratos en el sistema. Cada transacción tiene entonces algo adicional:

  • El hash del estado del mundo

Un  hash que referencia al estado del sistema DESPUES de la ejecución de la transacción. Ese hash es verificado en cada nodo de la red que procesa el bloque y la transacción; de esa manera todos los nodos de la red termina coincidiendo en el resultado del estado del mundo controlando el hash resultante en cada paso. Un estado del mundo se almacena en un trie, una estructura de árbol donde cada nodo tiene un hash asociado dependiendo del contenido de ese nodo. Ver mi trabajo anterior sobre tries en Building a Blockchain (5) Building a Blockchain (12)

El bloque mismo también tiene un hash de estado, representado el estado del mundo LUEGO de la ejecución del bloque. Puede ser DIFERENTE que el estado del mundo luego de la ULTIMA transacción del bloque, porque se admite que al final del bloque se realicen operaciones que alteren el estado, por ejemplo, la asignación de premios a los mineros. Este hash de estado de bloque también es controlado por todos los nodos de la red, para mantener el consenso y validar el bloque.

Un problema es el armado de un bloque, que puede ser un cuello de botella cuando se intenta procesar muchas transacciones (por ejemplo, cientos o miles de transacciones por segundo). Este es el principal caso de uso que inspira esta serie de posts. Sería interesante tener MUCHAS blockchains:

Entonces, una blockchain podría estar dedicada a las transacciones de un contrato/token muy popular, mientras que otra blockchain puede estar dedicada a las transacciones de una nación o región. Sólo de vez en cuando habrá transferencias entre blockchains. Este esquema de cosas no se limita a sólo dos blockchains, se podría manejar muchas más, y tener nodos dedicados a procesar sólo una o dos blockchains. Entonces, en cada nodo se requieren menos recursos para mantener el estado, y el estado global está distribuido en los nodos que atienden a DISTINTAS blockchains. Describo blockchains con esquemas iguales, no Bitcoin vs Ethereum, sino todas Ethereum o todas RSK.

En los próximos posts, describirér los cambios necesarios en Ethereum/RSK para manejar múltiples blockchains en la red.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Ejecutando un Nodo Ethereum/RSK

June 12th, 2017

La testnet pública de RSK fue lanzada, y el código principal fue abierto. Si no conoce a RSK, visitar:

http://rsk.co/

Técnicamente, es un fork de Ethereum, de la versión Java, con un 2-way peg contra Bitcoin, y con capacidades de merge-mining. Pueden correr su propio nodo, en solitario, o en su propia red, o pueden ejecutar nodos uniéndose a la testnet pública. Hay instrucciones de como hacerlo en el wiki del proyecto:

https://github.com/rsksmart/rskj/wiki

En este post, quiero describir mi flujo de trabajo para compilar, configurar y ejecutar un nodo, pudiendo así hacer experimentos, probar ideas de implementación distintas (nota: actualmente soy miembro del equipo de desarrollo de RSK, pero esta descripción en este posts, es una descripción personal de lo que uso). Primero, bajarse el código fuente de:

https://github.com/rsksmart/rskj

Actualmente, la versión que se usa en testnet, está en el branch Ginger:

https://github.com/rsksmart/rskj/tree/ginger

También pueden clonarse el repositorio y modificarlo en el suyo propio. Para compilar, se puede usar el IntelliJ Idea Community edition, o usar el comando de línea:

.\gradlew build shadow -x testnet

(usualmente trabajo con Windows; en Linux, Max, cambiar la barra invertida por la barra normal /). Más detalles en:

https://github.com/rsksmart/rskj/wiki/Compile-and-run-a-RSK-node-locally

La opción shadow es para armar un archivo jar que tenga todas las dependencias. La opción –x test permite saltear la ejecución de los tests durante la tarea de build. El comando genera un archivo jar en un subdirectorio. Ejecutar:


cd rskj-core\build\libs
java -Drsk.conf.file=<path> -cp rskj-core-0.2.0-GINGER-all.jar co.rsk.Start

Eso lanza al nodo. ¿Cuál es el archivo de configuración a usar? Más info en:

https://github.com/rsksmart/rskj/wiki/How-to-initialize-RSK-node-configuration-file-settings

Hay un archivo de configuración de ejemplo en:

https://github.com/rsksmart/rskj/blob/master/rskj-core/src/main/resources/config/rsk-sample.conf

Una de las cosas que hay que hacer, es que cada instancia de nodo que queremos lanzar tenga su id de nodo. Para generar el id de nodo y una clave privada asociada, ejecutar primero el comando de línea:


java -cp rskj-core-0.2.0-GINGER-all.jar co.rsk.GenNodeKeyId

Vuelva un JSON en consola. Hay que copiar de los datos que vuelta, la clave privada en el archivo de configuración, y opcionalmente, el id de nodo:


# Private key of the peer
nodeId = 66cf57...
privateKey = 46f850...

Sólo es mandatorio el privateKey para ejecutar el nodo, pero puede copiar el id de nodo para mantener una referencia. La otra línea a definir es el llamado secreto coinbase:


# this string is computed
# to be eventually the address
# that get the miner reward
coinbase.secret = mytreasure

Puede poner una palabra arbitraria.

Para permitir el CORS (Cross-Origin Resource Sharing) para exponer el estado del nodo por JSON RPC (Remote Procedure Call), hay que modificar la propiedad cors:


rpc {
enabled = true # you can disable rpc
port = 4444

cors = "*.rsk.co" # you can put "localhost here"

La capacidad de RPC es solamente usada para consultar al nodo, y enviar transferencias desde un cliente, pero desabilitarla no interfiere con el proceso normal del nodo. ¿Cómo hacemos que el nodo se conecte a la red testnet pública? Hay definidos nodos de bootstrap:


peer {
discovery = {
# if peer discovery is off
# the peer window will show
# only what retrieved by active
# peer [true/false]
enabled = true
# List of the peers to start
# the search of the online peers
# values: [ip:port]
ip.list = [
"bootstrap01.testnet.rsk.co:50505",
"bootstrap02.testnet.rsk.co:50505",
"bootstrap03.testnet.rsk.co:50505",
"bootstrap04.testnet.rsk.co:50505"
]

para usar como puntos de partida en lo que se llama el proceso de descubrimiento de pares, peer discovery. Se puede desabilitar, por ejemplo, si quiere usar el nodo para su propia red, o quiere poner en otro lugar de la configuración (ver más abajo) a qué nodos explícitos quiere conectarse al principio.

Si quiere ejecutar VARIOS nodos locales, debe tener entonces VARIOS archivos de configuración. En estos archivos, ajustar las propiedas siguientes, para que los nodos no se pisen entre sí:

# Peer for server to listen for incoming connections
# 50505 for testnet
listen.port = 50505 # ie to 50506

y también la ya mencionada:


rpc {
enabled = true
port = 4444 # ie to 4445

También, cambiar el directorio de database, donde cada nodo graba los bloques, el estado, etc, sus datos de funcionamiento en archivos. Adicionalmente, pueden poner su propio id de red, para que sus nodos sólo se entiendan entre ellos:


# Network id
networkId = 777 # ie to 42

También puede especificar directamente a qué nodos conectarse. Debe conocer entonces la IP o nombre de máquina, el port del otro nodo, y el id: el otro nodo no aceptará conexiones de quien no conozca su id de nodo:


# Boot node list
# Use to connect to specific nodes
active = [
#{
# ip = 11.22.33.44
# port = 50505
# nodeId = e437a483...
#}
]

En el ejemplo, la propiedad ip está puesta con números, pero puede ponerse el nombre de máquina directamente.

Si quieren que su nodo mine bloques, pueden cambiar estas propiedades a verdadero:


# miner options
miner {
server.enabled = false # change to true
client.enabled = false # change to true

Si sólo cambia la propiedad server.enabled a verdadero, dejando client.enabled en false, podrá minar apoyándose en merge mining con software y hardware de minería, pero esa característica está más allá del alcance de este post.

¿Alguna duda? Siempre pueden visitar, preguntar o comentar en el canal de gitter de RSK Java:

https://gitter.im/rsksmart/rskj

Interesados? RSK busca desarrolladores, ver los tweets:

https://twitter.com/RSKsmart/status/872169805515718657


Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Resoluciones del Nuevo Mes: Junio 2017

June 7th, 2017

Un nuevo mes comienza, y es tiempo de escribir las resoluciones mensuales. Como siempre, primero un repaso de las del mes anterior:

– Continuar RskSharp [pendiente]
– Continuar SimpleBlockchain [completo] ver repo
– Continuar BlockchainSharp [pendiente]
– Continuar ChineseP [pendiente]
– Continuar TensorSharp [pendiente]
– Continuar RSharp [completo] ver repo

I also worked on:

– Mejorar AjDrawJS [completo] ver repo
– Mejorar AjTalkJS [completo] ver repo
– Mejorar SimpleForth [completo] ver repo
– Mejorar ClojJS Clojure in JavaScript [completo] ver repo
– Ejemplo adicional para SimpleGA, algoritmos genéticos [completo] ver repo
– Experimentos con RSKJ fork [completo] ver repo
– Creaar wordie, lenguaje de programación en inglés [completo] ver repo
– Creaar domie, un DOM para tests en JavaScript [completo] ver repo
– Crear vyu, un framework a la vue.js [completo] ver repo

Mis nuevas resoluciones:

– Continuar RskSharp
– Continuar SimpleBlockchain
– Continuar BlockchainSharp
– Continuar ChineseP
– Continuar TensorSharp
– Continuar RSharp
– Experimentar con RSKJ fork
– Continuar Vyu
– Continuar Domie
– Continuar Wordie

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Lanzando la TestNet RSK

May 23rd, 2017

El proyecto arrancó en 2015, y yo estoy participando en el equipo de desarrollo desde hace algo más de un año. Ayer se lanzó la TestNet pública, en medio de la conferencia Consensus 2017:

http://www.coindesk.com/events/consensus-2017/

Ver instrucciones para participar en la prueba:

https://github.com/rsksmart/rskj/wiki

El repositorio de código principal en:

https://github.com/rsksmart/rskj

Pueden observar el estado de la testnet en:

http://stats.rsk.co/

El gran tema del proyecto es correr una red Ethereum, pero separada, que permita la ejecución de “smart contracts”, usando bitcoins, transferidos a cuentas de la red RSK. Un usuario que tenga bitcoins puede transferir ese valor a la red RSK para que pueda aplicarlos en la ejecución de “smart contracts”.

Si el mundo de contratos inteligentes es nuevo para Uds., comenzar estudiando:

https://www.ethereum.org/

Si quieren saber cómo programar una blockchain (usando TDD por supuesto 🙂 estoy escribiendo en:

http://blogs.msmvps.com/lopez/category/blockchain/

Espero poder escribir más en detalle sobre las ideas de este proyecto.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com

Resoluciones del Nuevo Mes: Mayo 2017

May 9th, 2017

Como pasa el año, tiempo de escribir las nuevas resoluciones, veamos el resultado de las anteriores:

– Continuar RskSharp [completo] ver repo
– Continuar SimpleBlockchain [completo] ver repo
– Continuar Solidity Compiler [pendiente]
– Continuar ChineseP [completo] ver repo
– Continuar TensorSharp [completo] ver repo
– Continuar RSharp [completo] ver repo
– Continuar SimpleForth [pendiente]

Además, estuve trabajando en:

– Continuar BlockchainSharp [completo] ver repo
– Comenzar Neurum, redes neuronales en C# [completo] ver repo
– Comenzar AjTalkJS, intérprete Smalltalk en JavaScript [completo] ver repo
– Comenzar SimpleProlog, intérprete Prolog en JavaScript [completo] ver repo
– Comenzar AjDrawJS [completo] ver repo

Resoluciones del nuevo mes:

– Continuar RskSharp
– Continuar SimpleBlockchain
– Continuar BlockchainSharp
– Continuar ChineseP
– Continuar TensorSharp
– Continuar RSharp

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Las Tareas Son del Equipo

April 17th, 2017

Es común en ek planeamiento de una iteración, elegir las tareas del backlog, por prioridad dada por los “stakeholders”. Una vez elegidas las tareas, se van ejecutando, generalmente teniendo subtareas. Hay tareas de programación, de diseño de interfaz, de deployment, etc…

He visto dos formas de encarar la ejecución las tareas: o se las asigna UNA persona, o se la ejecutan entre varios, tal vez UN miembro del equipo por SUBTAREA. Y luego de ver mucho éxito en la segunda forma, pienso que es lo más adecuado (siempre dependiendo del context y las fuerzas del proyecto, el estado del equipo, etc…). Incluso participé de un proyecto donde no había más de DOS tareas abiertas, de tal forma que los miembros del equipo colaboraban para terminar cualquiera de esas dos tareas (en este caso en particular, las dos tareas en general eran de programación o de diseño).

El que varios trabajen en una tarea, y no se pase a la siguiente hasta tenerla terminada, veo que favorece el “ownership” colectivo, donde no se forman silos de programación, donde cada miembro del equipo termina colaborando viendo el proyecto en general, y no solamente la parte que a él/ella le toca. Permite también la adopción de programación de pares, la difusión del conocimiento, y un “code review” permanente, adoptando agilidad, en lugar de etapas de codificación y “code review” por separado.

En un equipo maduro, debería adoptarse esta forma de encarar las tareas del “sprint” (siempre y cuando, respetando el contexto y las fuerzas del proyecto en particular). Por lo menos, he visto mejora en el resultado cuando se adopta esa forma de trabajo.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com

 

Alineando las Sillas en la Cubierta del Titanic

April 15th, 2017

Desde la aparición de la agilidad aplicada a equipos de desarrollo de software, hemos estado avanzando en nuestra profesión. En mi experiencia, veo que la calidad de lo producido ha mejorado, en general. Por lo menos, cuando veo los proyectos en los que he participado en este siglo, comparados con anteriores, noto esa mejora general. Y también en la satisfacción personal de cada miembro del equipo, en el manejo de los tiempos, los esfuerzos, y demás. Y veo lo mismo en decenas de proyectos en los que no participé pero he visto crecer de cerca.

Pero a veces, veo tomar decisiones que no son las más ágiles, o no están alineadas con lo que el contexto del proyecto pide. Una tendencia, no muy frecuente por suerte, es poner énfasis en alguna métrica o herramienta en lugar de lo que es importante para el proyecto.

Por ejemplo, he visto “sprints”, iteraciones, dedicadas a “incrementar el porcentaje de code coverage a 80%”. Por más que repaso las circunstancias de los casos que conozco, no logro ver que sea realmente lo importante. Es más, tomar ese tipo de trabajo es perder una oportunidad de mejora real en el equipo. El trabajar “a posteriori” en el incremento del code coverage, es poner el carro delante del caballo. Lo que buscamos en un sistema que estamos armando es que funcione como esperamos. Y eso se logra mejor si escribimos los tests de la conducta esperada, de cada caso de uso que queremos cumplir (uso “caso de uso” en un sentido amplio, desde la conducta esperada en una simple clase, hasta el resultado esperado luego de una serie de pasos de negocio). Cuando uno sigue ese “approach”, el “code coverage” nos da automáticamente cumplido como métrica, casi seguro mayor que el 80%, o que el 90%. Eso es lo que tiene que ser la medición del “code coverage”: una métrica que de evidencia de que estamos siguiendo el buen camino, antes que un objetivo en sí mismo. Trabajar a “posteriori” para incrementar esta métrica NO ASEGURA que estemos escribiendo un buen sistema. Ver ejemplo mencionado en el post El Programador Profesional (1) , donde aún con un gran “code coverage”, lo entregado se rompía luego de dos clicks en el browser, en cuatro continentes.

Otra versión parecida de errar en el blanco, es adoptar prácticas porque parecen las “mejores prácticas” o poner procesos obligatorios en el desarrollo, como obligación de manejarse con “branch por feature”, y “code review”, para mantener “la calidad del código”. Las veces que vi que se llegara a esa situación, son pocas, por suerte. Pero igual de vez en cuando aparecen, y veo que es de nuevo atacar un problema con procesos y herramientas, adoptar prácticas que tienen sentido en otro contexto, sin aprovechar atacar las causas raíces y obtener una mejora en el equipo.

Por ejemplo, “branch por feature”, podría adoptarse, pero en casos particulares. Si se necesita adoptar en un caso, es seguramente porque no estamos trabajando en forma incremental, simplemente mejorando el “branch” de desarrollo, trabajando juntos, esforzándonos por no romper algo (por ejemplo, usando TDD (Test-Driven Development) me facilita mucho el saber automáticamente si la conducta esperada no se cumple). Y dificulta la integración, tenemos que trabajar más casi siempre al final de la iteración para tener algo entregable. Y vi que promueve el trabajo en silos, donde cada cual trabajar en un “branch”, en lugar de trabajar todos juntos en una tarea. Cuando la adopción de “branch por feature” se hace obligatoria, es como que se naturalizan esos “bad smell” de equipo, y no podemos activamente trabajar en la mejora. He visto DECENAS de proyectos de equipos ágiles donde no se usa “branch por feature” y todo funciona de forma armoniosa. Esto me lleva a pensar que “branch por feature” es algo más útil cuando el proyecto es de código abierto. En un equipo ágil, donde hay una reunión diaria, donde hay comunicación (aun remota), donde el sistema se va armando de tal forma de saber cuando algo no funciona o cuando introducimos un bug sin quererlo, donde el sistema no se ha dejado llevar por la complejidad accidental y puede entonces ser desarrollado incrementalmente, cuando veo que se da este contexto, veo que no es tan necesario el “branch por feature”.

En cuanto a “pull request con code review” obligatorio, de nuevo: veo que es un síntoma de no atacar otra causa raíz. Por ejemplo, no lo vi tan necesario cuando hay trabajo de a pares. O cuando hay confianza en los miembros del equipo, y se sabe que cualquier cosa que uno agregue puede ser revisada en cualquier momento, porque estamos armando un sistema evolutivo, sin complejidad accidental, que admite cambios como todo lo ágil promueve. Cualquier cosa que parezca mejorable, se puede mejorar en cualquier momento. Por supuesto, cada uno debe hacer el mejor esfuerzo desde el principio.

En definitiva: adoptar herramientas y procesos de esta forma, es como alinear las sillas en la cubierta del Titanic: estamos haciendo algo que parece bueno, en vez de hacer lo correcto, lo que la situación amerita. Y nos naturaliza los problemas, sin atacar las causas raíces.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com