Las Tareas Son del Equipo

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

 

Posted in Desarrollo Agil, Programacion | Comments Off on Las Tareas Son del Equipo

Alineando las Sillas en la Cubierta del Titanic

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

 

Posted in Desarrollo Agil, Programacion, Uncategorized | Comments Off on Alineando las Sillas en la Cubierta del Titanic

Resoluciones del Nuevo Mes: Abril 2017

Un nuevo comienza, ya pasó el verano, estamos en otoño por estos lares. Tiempo de escribir mis resoluciones mensuales, pero primero un repaso de las del mes anterior:

– Continuar RskSharp [complete] ver repo
– Continuar SimpleBlockchain [pending]
– Continuar Solidity Compiler [complete] ver repo
– Continuar ChineseP [pending]
– Continuar TensorSharp [complete] ver repo

Además estuve trabajando en:

– Mejorar SimpleProlog [completo] ver repo
– Continuar RSharp [completo] ver repo
– Mejorar AjDrawJS [completo] ver repo
– Mejorar SimpleForth [completo] ver repo

Mis resoluciones del nuevo mes son:

– Continuar RskSharp
– Continuar SimpleBlockchain
– Continuar Solidity Compiler
– Continuar ChineseP
– Continuar TensorSharp
– Continuar RSharp
– Continuar SimpleForth

Nos leemos!

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

Posted in C#, JavaScript, NodeJs, Proyectos Open Source, Test-Driven Development | Leave a comment

El Programador Profesional, The Clean Coder (1)

Cada tanto vuelvo a leer algunos libros clásicos de programación, como The Pragmatic Programmer, Programming Pearls, The C Programming Language, Code Complete, Clean Code… En estos días me reencuentro con el excelente The Clean Coder del bueno de @unclebobmartin (ver el blog http://blog.cleancoder.com/ y el sitio asociado https://cleancoders.com/). Me gustó darme cuenta que en estos años estuve mejorando en varios de los puntos que menciona para un programador profesional (en otros todavía estoy en deuda). Quisiera comentar en esta nueva serie de posts las cualidades y actitudes que menciona como importantes.

Primero, Martin se refiere a programadores PROFESIONALES: todo lo que expone es lo que él ve como deseable para un programador que quiera llamarse profesional, no solamente porque trabaja programando sino por el respeto y la posición que alcanza entre sus colegas y clientes.

La primera gran regla que da se basa en el juramento hipocrático:

First, Do Not Harm

Es decir, lo primero, al programar, es no hacer daño. Esto se traduce en NO INTRODUCIR ERRORES (bugs que le dicen). Cualquier software exitoso necesita ser modificado en el tiempo, y es signo de profesionalismo en un programador el no introducir errores en las modificaciones que haga. Uno podría decir: la programación es una actividad muy complicada, tanto que como seres humanos no podemos evitar introducir bugs. Pero Martin retruca: un médico también puede equivocarse, pero el juramento hipocrático lo lleva a esforzarse, a hacer todo lo posible que esté a su alcance y bajo su entendimiento para evitar lastimar a sus pacientes. Eso mismo tenemos que hacer nosotros como programadores: esforzarnos por no introducir bugs cuando corregimos alguno o agregamos nueva funcionalidad. Martin da algunos ejemplos de su propia historia profesional sobre las consecuencias nefastas que puede provocar el agregar bugs sin darnos cuenta.

Pienso que estamos todos de acuerdo en que necesitamos hacer ese esfuerzo, pero ¿cómo lograrlo? Una estrategia, desaconsejable, es hacer que los clientes finales sean los que reporten bugs. ¡Qué bueno! Entreguemos algo rápido, así nos destacamos en nuestro cumplimiento de los plazos y luego, reparemos lo que ellos detectaron, también rápido. Pero no: no es un camino a seguir en los tiempos que corren. Otra aproximación: hacer que el equipo de QA (Quality Assurance), se encargue de detectar los problemas. De nuevo, así podemos entregar algo rápido, avanzar, total, ya alguien va a reportar los errores. Tampoco este es el camino esperado para un programador profesional: malgastar el tiempo de otros cuando uno debería directamente entregar código que funciona, no es profesional, es chapucero.

Entonces ¿cómo hacemos que lo que codificamos no tenga errores? Una es aplicar las mejores prácticas, todos los patrones del mundo, y confiar en nuestra capacidad de escribir bien, de “compilar” los resultados de una función que escribimos en nuestra cabeza, sin nunca probarla. Esta estrategia sigue siendo tan común que me asombra. Aún cuando seamos los “grandes” programadores que toman todas sus precauciones para no introducir errores, los errores siguen apareciendo. ¿Qué propone Martin (y es agua para mi molino, si ya conocen mi postura sobre el tema)? Pues bien:

How can you know your code works? That’s easy. Test it. Test it again. Test it up. Test it down. Test it seven ways to Sunday!

Siempre probar el código. Siempre. ¿Sugiere entonces Martin tener un 100% de cubrimiento de código? No, no lo sugiere, lo DEMANDA. Cada línea de producción que uno escriba debe ser puesta a prueba.

Every single line of code that you write should be tested. Period.

Parece no realista. Pero no lo es. Cada línea que uno escribe es para ser ejecutada alguna vez, entonces, DEBEMOS asegurarnos que funciona como esperamos. No basta con leer el código y “compilar” el resultado en nuestros sesos, decir simplemente: “esto hace lo que se espera”. Martin (y permítanme que yo me sume) DEMANDA que sea probada con un test.

Una estrategia que veo seguir, entonces, es escribir las pruebas DESPUES de escribir el código. He escuchado cosas como: “con escribir código DESPUES, me aseguro que funcione, y el código que YA escribí tiene buena calidad”. Bueno, pocas veces he visto que se cumpliera. Lo que sucede muchas veces es que el código a probar a posteriori, es un código enrevesado, o al menos, difícil de ser probado. Es por eso que Martin escribe:

The solution to that is to design your code to be easy to test. And the best way to do that is to write your tests first, before you write the code that passes them.

¡¡SI!! Es tan simple como eso: escribir las pruebas ANTES del código. Esto nos lleva a TDD (Test-Driven Development), flujo de trabajo del que Martin es un “big supporter” (y yo también).

Por supuesto que esto no quita que probemos nuestro software con pruebas automáticas de integración, o con pruebas manuales de QA. Siempre probar, probar, probar… Hacer todo el esfuerzo como profesionales para quedar seguros de que nuestro software funciona como se espera. Pero el paso inicial es usar TDD: me temo que no encuentro todavía una disciplina o flujo de trabajo que reemplace a TDD para conseguir el “First, Do Not Harm”.

Alguno podrá decir que practicar TDD lleva “más tiempo”. Pues yo todavía tengo que ver eso en el contexto de un proyecto con lógica no trivial: el aparente más tiempo que involucra escribir los tests antes del código, y el trabajo de refactor, que permite hacer que el código evolucione, en vez de “escribirlo bien en la primera vez”, es menor que el tiempo tradicional si contamos el tiempo de depurar, los días y horas gastados en identificar las causas de errores, y el tiempo que se tarda en corregirlos.

Puedo dar como evidencia experiencia propia, lamentablemente sin poder mostrar código concreto por haber sidos proyectos privados. El cliente final fue el mismo, el dominio fue parecido en complejidad y alcance, y los equipos de programadores de muy buen y similar nivel.

Proyecto A: escrito sin TDD, con pruebas de QA, pruebas manuales, pruebas de usuarios en ambiente de test, y luego en stage, antes de llegar a producción.

Proyecto B: escrito con TDD, con tests automáticos de integración, pruebas de QA, pruebas manuales, pruebas de usuarios en ambiente de test y stage, antes de llegar a producción.

El segundo proyecto, escrito con TDD, se implementó evolutivamente, con TRES implementaciones esencialmente diferentes, en el TIEMPO que se había estimado hacerlo sin TDD: Luego, fue más fácil en este proyecto introducir pruebas automáticas de integración, incluso directamente en el código. Y cada vez que modificábamos código o agregamos algo nuevo, al quedar las pruebas de código en “verde” luego las pruebas de integración y manuales de QA eran “un trámite”: muchas muchas veces pasaban, al habernos asegurado el cumplimiento de las pruebas escritas con TDD.

El primer proyecto también tenia pruebas de código, con un cubrimiento de código mayor de ochenta por ciento, escritas DESPUES de escribir el código. Pero aún cuando esas pruebas pasaran a “verde”, eso NO ASEGURABA el buen funcionamiento del sistema final. Y había que dar muchas vueltas para probar un código que no había sido escrito como para ser probado fácilmente. Muchas veces las pruebas de QA fallaban. Y cada vez que se introducía un cambio o se arreglaba un bug conocido, aparecía algún otro problema detectado en QA. Aún dos semanas antes de la entrega final, se introdujo un problema que sólo fue detectado en producción: dos clicks en el browser, y el sistema explotaba en cuatro continentes.

Del segundo proyecto, no escuché nada por más de un año, luego de su entrega. Pregunto un día ¿lo están usando? Sí, lo estaba usando. Ah ¿lo están usando para probarlo cada tanto? No, lo usaban cada día YA EN producción. Se le había entregado el mantenimiento del sistema a otro equipo, lejano. Entonces pregunto; ¿cómo? ¿lo están usando desde hace meses? ¿cómo es que no nos llegan reportes de bugs? La respuesta: porque NO LOS ENCONTRARON (o por lo menos hasta ese momento). Todo había sido escrito ordenadamente, aplicando “baby steps”, programación evolutiva, escribiendo explícitamente los casos de uso esperados, tanto de funcionamiento correcto como de conducta ante entradas inválidas. Estaba armado de tal forma que, al tener ese tipo de pruebas, y código que fuera fácilmente probable, las modificaciones se podían implementar y enterarse inmediatamente si algo anterior se rompía o no. Porque eso es también nos da TDD: el facilitar la profesión de los que vengan después a modificar el software que estamos construyendo.

Por supuesto que TDD solo no asegura la AUSENCIA TOTAL de bugs. Pero su aplicación a conciencia, junto con refactor casi continuo, la aplicación CONCIENZUDA de patrones y otros conceptos (no solamente por que sí), el diseño evolutivo (que permite ir construyendo algo que no se aparta de la simplicidad sino hasta la llegada de un caso de uso que haga necesario agregar algo), todo eso, que llamo “TDD y cabeza”, es lo que permitió el resultado exitoso del proyecto B.

Como programadores que aspiramos a ser profesionales tenemos que poner todo nuestro esfuerzo en este tema, en escribir código sin introducir errores. Y para eso, veo como esencial el escribir las pruebas antes del código, y mantener el sistema en un estado simple, claro, entendible y mantenible. Más sobre el tema en próximo post.

Nos leemos!

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

Posted in Desarrollo Agil, Programacion, Test-Driven Development | Comments Off on El Programador Profesional, The Clean Coder (1)

Resoluciones del Nuevo Mes: Marzo 2017

Un nuevo mes comienza y es tiempo de escribir mis resoluciones. Primero, una revisión de las de febrero:

– Mejorar SharpGo [completo] ver repo
– Mejorar BlockchainSharp [pendiente]
– Mejorar SimpleBlockchain [completo] ver repo
– Continuar Solidity Compiler [completo] ver repo
– Continuar ChineseP [pendiente]
– Mejorar ErlSharp [completo] ver repo

Además estuve trabajando en:

– Comenzar RskSharp [completo] ver repo
– Comenzar TensorSharp [completo] ver repo
– Mejorar AjDrawJs [completo] ver repo
– Mejorar SimpleForth [completo] ver repo
– Mejorar CrysSharp [completo] ver repo
– Nuevo ejemplo Bitcoin en SimpleGA [completo] ver repo
– Mejorar Husky, mi intérprete Haskell [completo] ver repo
– Mejorar SimpleLisp [completo] ver repo
– Mejorar CrysJS [completo] ver repo

Mis nuevas resoluciones:

– Continuar RskSharp
– Continuar SimpleBlockchain
– Continuar Solidity Compiler
– Continuar ChineseP
– Continuar TensorSharp

Nos leemos!

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

Posted in Blockchain, C#, JavaScript, NodeJs, Proyectos Open Source | Leave a comment

Profesión

El título de este post está inspirado en un relato de Isaac Asimov, “Profession”. Más información en:

https://en.wikipedia.org/wiki/Profession_(novella)

Pueden leerla en:

http://www.inf.ufpr.br/renato/profession.html

Transcurre en el siglo LXVI (sesenta y seis), cuando la humanidad todavía ocupa la Tierra como planeta central, pero donde la actividad excitante está en los Mundos Exteriores. Los jóvenes se educan con “cintas” donde van aprendiendo sobre temas, antes de llegar a la “Olimpíada”, una competencia donde poner a prueba sus conocimientos, y son elegidos entocnes por distintos empleadores de los Mundos Exteriores, en base a su resultado.

George quiere ser programador de computadores, pero se le rechaza la oportunidad de estudiar y especializarse, aduciendo que su mente no es adecuada. Queda internado en un lugar, la Casa. Mientras, un compañero de estudios, estudia con la “cinta” y llega a la “Olimpíada”. George se escapa de la Casa, y al llegar a la ciudad de la “Olimpíada” se encuentra con este compañero, que se lamenta de no haber obtenido el mejor empleo posible, porque su “cinta” estaba desactualizada, y no trataba de los últimos modelos del espectrógrafo Beechman.

Al final, George es encontrado (en realidad, siempre lo vigilaron) y luego de algunos pasos más, se le revela que fue apartado y ahora aprobado, para ser parte de otro grupo, desconocido. La Casa no es un lugar para inadaptados mentales, es un Instituto de Altos Estudios, donde la gente creativa se dedica a crear, a mejorar el conocimiento de la sociedad, no solo a aprender “cintas”. Alguien llamado Beechman tuvo que ser el inventor del espectrógrafo Beechman, y no estudió eso de una “cinta”.

Siempre me impresionó este relato, que habré leido hace unas décadas en el siglo pasado. En los ochenta, me encontré trabajando como pasante en una sucursal en Buenos Aires de una multinacional. En un piso, estaba el especialista en el Sistema Operativo X17, digamos. Sabía todo de eso, cómo instalar, que instalar, cómo corregir tal cosa; era el especialista preferido del tema. Estaba siempre ocupado, y reclamado desde otros paises incluso. Pero no sabía mucho más. Había entrado en el camino de la especialización.

No digo que “esté mal”, pero no era eso lo que yo quería. Antes y después, en otros ámbitos, volví a encontrar ese “síndrome” de estudiar algo especializado. Desde entonces, he tratado de estudiar algo concreto pero siempre teniendo en el panorama el paisaje general, los fundamentos de algo, más que los detalles circunstanciales del momento. Además, nuestra profesión está signada por el cambio permanente, así que veo interesante tener siempre en vista el aspecto general de algo, más allá de las “technicalities” del framework, lenguaje o librería de moda.

De ahí que rara vez me especialicé en algo, con la SuperLibrary 17.2, o el MegaFramework MVC 18.2. Prefiero entender las fuerzas, contexto, casos de uso de esa librería, antes que los métodos detallados. Prefieron conocer por qué adoptamos MVC en estos tiempos, o modelos similares, y luego ver de aplicar eso en cada caso.

Hay un caso concreto actual, del camino estudio algo especializado, sin ver lo general. Lo noto en “machine learning”. Muchos quieren aprender TensorFlow o algún framework en particular de redes neuronales, sin tomarse el trabajo de aprender los fundamentos de los distintos “approaches” que hoy tenemos en “machine learning”. Hay que estudiar algoritmos genéticos, redes neuronales, árboles de decisión, distintos algoritmos de clasificación, y hasta recordar los sistemas expertos y la historia de la “inteligencia artificial”, para realmente comenzar a entender y poder tomar decisiones y extender todo lo que hay para hacer en “machine learning”.

Nos leemos!

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

 

 

Posted in Programacion | Comments Off on Profesión

Muerte a Spring

En el título me refiero al Spring Framework de Java. Pero no se tome al pie de la letra ese título. La idea del post es mostrar que podemos usar mal algo, como una librería, cuando el contexto y los casos de usos no son los adecuados. Muchas veces, como programadores, usamos lo que conocemos, pero no siempre es el camino más adecuado a tomar dado los casos de uso que tenemos entre manos. Es por eso que muchas veces hago énfasis en tener en cuenta los casos de uso y el contexto.

Spring Framework nació en este siglo de la mano de Rod Johnson para poner orden en el desarrollo de un proyecto Java. Una de sus primeras “features” es permitir configurar un grafo de objetos desde un archivo o declaración XML. Eso permitía, hasta en deployment, configurar la conducta de nuestra aplicación, por ejemplo, cambiar el objeto concreto de persistencia, para pasar de usar Oracle a usar otra base de datos. Con el tiempo, esa capacidad de configuración se extendió al uso o no de otros frameworks, por ejemplo, de ORMs como Hibernate.

Pero había que mantener esos archivos XML de configuración. No recuerdo qué framework permitió declarar en atributos la relación entre los objetos, y Spring adoptó con el tiempo esa estrategia también.

Hoy quiero apuntar a código real, de un proyecto de código abierto, que comencé a conocer en @RSKSmart hace un año: la implementación en Java de Ethereum:

https://github.com/ethereum/ethereumj

Es un servidor que ejecuta en una red de servidores similares. implementando una blockchain con smart contracts. Hay implementaciones en otros lenguajes, como Go y Python. Al arrancar, levanta un conjunto de objetos, algunos apuntan a otros, y comienza a funcionar. Pero veamos, como ejemplo, un objeto de los que levanta, el WorldManager:

https://github.com/ethereum/ethereumj/blob/develop/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java

Veamos parte del código inicial:

 @Autowired
private PeerClient activePeer;

@Autowired
private ChannelManager channelManager;

@Autowired
private AdminInfo adminInfo;

@Autowired
private NodeManager nodeManager;

@Autowired
private SyncManager syncManager;

@Autowired
private FastSyncManager fastSyncManager;

@Autowired
private SyncPool pool;

@Autowired
private PendingState pendingState;

@Autowired
private UDPListener discoveryUdpListener;

@Autowired
private EventDispatchThread eventDispatchThread;

@Autowired
private DbFlushManager dbFlushManager;
    
@Autowired
private ApplicationContext ctx;

y además usando @Autowired en el constructor:

@Autowired
public WorldManager(final SystemProperties config, final Repository repository,
                    final EthereumListener listener, final Blockchain blockchain,
                    final BlockStore blockStore) {
    this.listener = listener;
    this.blockchain = blockchain;
    this.repository = repository;
    this.blockStore = blockStore;
    this.config = config;
    loadBlockchain();
}

En total, más de una docena de objetos referenciados y creados al principio de la vida de WorldManager. Además, muchos de esos objetos tienen en su implementación más @Autowired. Prácticamente todos estos objetos terminan siendo “singletons”, creados al y relacionados al principio, y nada más. Pero muchos terminan siendo entonces objetos globales, con un estado mutable, que dificulta muchas veces su uso adecuado. En un objeto podemos tener acceso entonces al objeto “global” K, pero cualquier otro código puede alterar el estado de K mientras lo estamos usando. Es notable ese caso en el uso de BlockchainImpl y de Repository, pero eso daría para tema de otro post.

Veamos también la implementación de la interface Ethereum:

https://github.com/ethereum/ethereumj/blob/develop/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java

Vemos ahí:

@Autowired
WorldManager worldManager;

@Autowired
AdminInfo adminInfo;

@Autowired
ChannelManager channelManager;

@Autowired
ApplicationContext ctx;

@Autowired
BlockLoader blockLoader;

@Autowired
ProgramInvokeFactory programInvokeFactory;

@Autowired
Whisper whisper;

@Autowired
PendingState pendingState;

@Autowired
SyncManager syncManager;

@Autowired
CommonConfig commonConfig = CommonConfig.getDefault();

más objetos referenciados mágicamente con @Autowired. Y de nuevo más en el constructor:

@Autowired
public EthereumImpl(final SystemProperties config, final CompositeEthereumListener compositeEthereumListener) {
    this.compositeEthereumListener = compositeEthereumListener;
    this.config = config;
    System.out.println();
    this.compositeEthereumListener.addListener(gasPriceTracker);
    gLogger.info("EthereumJ node started: enode://" + Hex.toHexString(config.nodeId()) + "@" + config.externalIp() + ":" + config.listenPort());
}


Recordemos que @Autowired es una anotación de Spring que, cuando es el encargado de construir el objeto, completa automáticamente estas referencias anotadas con autowired, con objetos QUE NO SABEMOS cuáles son así viendo el código de arriba, desperdigados por todo el resto del proyecto como beans que cumplen con lo que pide el autowired.

Y notemos que el EthereumImpl, con todos sus objetos referenciados automáticamente, para colmo referencia a un WorldManager. Ambas implementaciones terminan referenciando muchos objetos. Esto tiene toda la facha de “code smell”.

Alguien podría decir: “pero seguramente es necesario, porque el sistema es complejo y tiene muchas relaciones…”. Despues de haber estado un año trabajando sobre este código, usándolo como base, les puedo asegurar que bien se podría implementar mucho más fácil. Lo que sospecho que pasó: el @Autowired es un camino de ida, y cada vez fue más fácil agregar un campo autowired a uno de los objetos ya existentes, que sentarse a pensar cómo armar un grafo de objetos inicial, donde a cada objeto se le inyecte sus colaboradores APROPIADOS. De hecho, es prácticamente el único uso de Spring en el proyecto: armar el grafo inicial. No hay “lifecycle” de objetos ni nada más. Tranquilamente se puede armar un grafo de objetos más armónico, con un código propio. Además, sería más fácil de escribir tests, donde por código, queda explícito que objetos usa cada objeto para funcionar.

He dejado de lado algunos otros temas, como el uso de @PostInit para completar el estado de un objeto, luego de construirlo, y el armado de los listeners: ¿cuándo un objeto comienza a escuchar los eventos de otro? Toda esta conducta queda desperdigada en anotaciones y código separado, y prácticamente sin tests. Y un @Autowired mal resuelto puede detectarse recién con la ejecución del servidor. El proyecto original es muy interesante, y tiene otras cualidades. Pero hoy le tocó el turno a esto que veo como anti patrón, y un claro ejemplo de abandonar lo simple (crear el grafo nosotros) por lo fácil (que lo haga Spring).

En definitiva, el ABUSO de @Autowired ha derivado en la existencia de dos objetos “bolsa de gatos”, objetos “God”. Spring Framework es una gran herramienta, pero como toda herramienta, hay que usarla adecuadamente y respetando el contexto. Espero que en el proyecto en el que estoy trabajando, podamos erradicar esta complejidad y conseguir una implementación más simple. No repitan esto en su casa! 😉

Nos leemos!

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

Posted in Ethereum, Java, Programacion, Proyectos Open Source, Spring Framework | Comments Off on Muerte a Spring

Resoluciones del Nuevo Mes: Febrero 2017

El segundo mes del año comienza, es tiempo de escribir mis resoluciones, pero antes, un repaso de las de enero:

– Mejorar CrysSharp [pendiente]
– Mejorar SharpGo [completo] ver repo 
– Mejorar BlockchainSharp [completo] ver repo
– Mejorar SimpleBlockchain [pendiente]
– Continuar Solidity Compiler [completo] ver repo
– Mejorar ChineseP [pendiente]
– Continuar PegSharp [pendiente]

También estuve agregando una mejora menor en ErlSharp ver repo.

Mis resoluciones para febrero:

– Mejorar SharpGo 
– Mejorar BlockchainSharp
– Mejorar SimpleBlockchain
– Mejorar Solidity Compiler
– Mejorar ChineseP
– Mejorar ErlSharp

Nos leemos!

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

Posted in Blockchain, C#, JavaScript, NodeJs, Proyectos Open Source, Solidity | Leave a comment

Resoluciones del Nuevo Mes: Enero 2017

Comenzó un nuevo año, yo sigo con resoluciones públicas mensuales, tiempo de escribirlas, pero antes a repasar las de diciembre:

– Mejorar CrysSharp [pendiente
– Mejorar SharpGo  [complete] see repo
– Mejorar BlockchainSharp [pendiente]
– Mejorar SimpleBlockchain [pendiente]
– Continuar Solidity Compiler [completo] see repo
– Continuar ChineseP [pendiente]
– Continuar PegSharp [pendiente]

He tenido temas personales, de salud, para atender, pero ahora estoy en una mejor posición para volver al ruedo.

Mis resoluciones de enero son:

– Mejorar CrysSharp
– Mejorar SharpGo 
– Mejorar BlockchainSharp
– Mejorar SimpleBlockchain
– Continuar Solidity Compiler
– Continuar ChineseP
– Continuar PegSharp

Nos leemos!

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

Posted in C#, Golang, JavaScript, NodeJs, Proyectos Open Source, Solidity | Leave a comment

Resoluciones del Nuevo Mes: Diciembre 2016

Y llegamos al fin de año. Tiempo de revisar las resoluciones de noviembre:

– Mejorar CrysSharp [pendiente]
– Mejorar SharpGo [pendiente] ver repo
– Mejorar BlockchainSharp [pendiente]
– Mejorar SimpleBlockchain [pendiente]
– Mejorar Solidity Compiler [pendiente] see repo
– Continuar ChineseP [pendiente]
– Continuar PegSharp [pendiente] see repo

Mis resoluciones para el nuevo mes de diciembre:

– Mejorar CrysSharp
– Mejorar SharpGo
– Mejorar BlockchainSharp
– Mejorar SimpleBlockchain
– Mejorar Solidity Compiler
– Mejorar ChineseP
– Mejorar PegSharp

Nos leemos!

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

Posted in Blockchain, C#, Golang, JavaScript, NodeJs, Proyectos Open Source, Solidity | Leave a comment