In the last Clojure Developers Barcelona meetup, we started to use re-frame to animate in the browser the code to evolve cellular automata that we wrote some weeks ago.
We managed to make a rough version but we didn't have time to test it and make it nice.
When I got home I redid the exercise from scratch using a mix of TDD and REPL Driven Development.
First, I coded a couple of evolution rules. These are their tests:
and this is their code:
Next, I coded the cellular automata evolution, these are its tests:
and the resulting code:
Once I had the evolution working, I started to work on the view, using Figwheel and a hard-coded list of cellular automaton states on the db. This way I focused only on rendering the list of cellular automaton states.
With that working, I played on the REPL to create a subscriber that reacted to changes on the cellular automaton states making the view render.
This is the resulting code of the view:
the code of the subscriber:
and the default db:
Then, I used TDD to write the event handlers.
The use of effects keeps re-frame handlers pure. They allow us to avoid making side effects. We just have to describe as data the computation that will be made instead of doing it. re-frame takes care of that part.
These are the handlers tests:
these are the handlers:
Notice, how in order to dispatch to another handler (a side effect) we just have to add a key-value pair to the map of effects returned by the handler. In this case, I used the :dispatch and :dispatch-later effects which are part of re-frame's built-in effects. You can also create and register your own effects (I will talk about it in some future post).
To see the whole picture this is the code that registers the handlers:
I think that effects and coeffects (I'll talk about them in a future post) are just great!
They make testing handlers logic very easy (since handlers keep being pure functions) and avoid having to use test doubles.
Finally, everything is put together in the core namespace:
You can see the cellular automaton evolving in this video (I used garden library to add some CSS to make it look nicer):
You can find the code on this GitHub repository.
In this post I've tried to, somehow, describe the process I followed to write this code, but the previous gists just reflect the final version of the code. If you want to follow how the code evolved, have a look to all the commits on Github.
I really love using ClojureScript and re-frame with Figwheel.
Record of experiments, readings, links, videos and other things that I find on the long road.
Registro de experimentos, lecturas, links, vídeos y otras cosas que voy encontrando en el largo camino.
Friday, September 30, 2016
Thursday, September 29, 2016
Interesting Talk: "The Clockwork Gardener: Growing an Elm App With Templates"
I've just watched this interesting talk by Jessica Kerr
Wednesday, September 28, 2016
Kata: Variation on Lights Out, a bit of FRP using reagi library
To finish with the series of exercises we've been doing lately around the Lights Out kata, I decided to use reagi library to raise the level of abstraction of the communications between the Lights and the LightsGateway components.
reagi is an FRP library for Clojure and ClojureScript which is built on top of core.async. I discovered it while reading Leonardo Borges' wonderful Clojure Reactive Programming book.
I started from the code of the version using the component library I posted recently about and introduced reagi. Let's see the code.
Let's start with the lights-gateway name space:
The main change here is that the ApiLightsGateway component keeps a lights-stream which it's initialized in its start function and disposed of in its stop function using reagi.
I also use, reagi's deliver function to feed the lights-stream with the response that is taken from the channel that cljs-http returns when we make a post request to the server.
Next,the lights name space:
Notice how the dependency on core.async disappears and the code to update the lights atom is now a subscription to the lights-stream (look inside the listen-to-lights-updates! function). This new code is much easier to read and is at a higher level of abstraction than the one using core.async in previous versions of the exercise.
Now the lights-view name space:
Here I also used reagi to create a stream of clicked-light-positions. Again the use of FRP makes the handling of clicks much simpler (in previous versions a callback was being used to do the same).
Another change to notice is that we made the view a component (LightsView component) in order to properly create and dispose of the clicked-light-positions stream.
Finally, this is the core name space where all the components are composed together:
This was a nice practice to learn more about doing FRP with reagi. I really like the separation of concerns and clarity that FRP brings with it.
You can find my code in these two GitHub repositories: the server and the client (see the master branch).
You can check the changes I made to use reagi here (see the commits made from the commit d51d2d4 (using a stream to update the lights) on).
Ok, that's all, next I'll start posting a bit about re-frame.
reagi is an FRP library for Clojure and ClojureScript which is built on top of core.async. I discovered it while reading Leonardo Borges' wonderful Clojure Reactive Programming book.
I started from the code of the version using the component library I posted recently about and introduced reagi. Let's see the code.
Let's start with the lights-gateway name space:
The main change here is that the ApiLightsGateway component keeps a lights-stream which it's initialized in its start function and disposed of in its stop function using reagi.
I also use, reagi's deliver function to feed the lights-stream with the response that is taken from the channel that cljs-http returns when we make a post request to the server.
Next,the lights name space:
Notice how the dependency on core.async disappears and the code to update the lights atom is now a subscription to the lights-stream (look inside the listen-to-lights-updates! function). This new code is much easier to read and is at a higher level of abstraction than the one using core.async in previous versions of the exercise.
Now the lights-view name space:
Here I also used reagi to create a stream of clicked-light-positions. Again the use of FRP makes the handling of clicks much simpler (in previous versions a callback was being used to do the same).
Another change to notice is that we made the view a component (LightsView component) in order to properly create and dispose of the clicked-light-positions stream.
Finally, this is the core name space where all the components are composed together:
This was a nice practice to learn more about doing FRP with reagi. I really like the separation of concerns and clarity that FRP brings with it.
You can find my code in these two GitHub repositories: the server and the client (see the master branch).
You can check the changes I made to use reagi here (see the commits made from the commit d51d2d4 (using a stream to update the lights) on).
Ok, that's all, next I'll start posting a bit about re-frame.
Tuesday, September 20, 2016
Kata: Variation on Lights Out, introducing component library
Recently at a Clojure Barcelona Developers event, we had a refactoring session in which we introduced Stuart Sierra's component library in a code that was already done: our previous solution to the Lights out kata.
First, we put the code in charge of talking to the back end and updating the lights atom in a separated component, ApiLightsGateway:
Then, we did the same for the lights code which was put in the Lights component:
This component provided a place to create and close the channel we used to communicate lights data between the Lights and the ApiLightsGateway components.
Next, we used the Lights component from the view code:
And, finally, we put everything together in the lights core name space:
This was a nice practice to learn more about component and what it might take to introduce it in an existing code base.
You can find the code we produced in these two GitHub repositories: the server and the client (see the componentization branch).
You can check the changes we made to componentize the code here (see the commits made on Aug 30, 2016).
As usual it was a great pleasure to do mob programming and learn with the members of Clojure Developers Barcelona.
First, we put the code in charge of talking to the back end and updating the lights atom in a separated component, ApiLightsGateway:
Then, we did the same for the lights code which was put in the Lights component:
This component provided a place to create and close the channel we used to communicate lights data between the Lights and the ApiLightsGateway components.
Next, we used the Lights component from the view code:
And, finally, we put everything together in the lights core name space:
This was a nice practice to learn more about component and what it might take to introduce it in an existing code base.
You can find the code we produced in these two GitHub repositories: the server and the client (see the componentization branch).
You can check the changes we made to componentize the code here (see the commits made on Aug 30, 2016).
As usual it was a great pleasure to do mob programming and learn with the members of Clojure Developers Barcelona.
Wednesday, September 14, 2016
Kata: Scrabble sets in Clojure
I recently did the Scrabble sets kata in Clojure.
I used a mix of a bit of TDD, a lot of REPL-driven development (RDD) following this cycle:
These are the tests I wrote using Midje:
and this the resulting code:
See all the commits here if you want to follow the process.
You can find all the code on GitHub.
I used a mix of a bit of TDD, a lot of REPL-driven development (RDD) following this cycle:
- Write a failing test (using examples that a bit more complicated than the typical ones you use when doing only TDD).
- Explore and triangulate on the REPL until I made the test pass with some ugly but complete solution.
- Refactor the code to make it more readable.
These are the tests I wrote using Midje:
and this the resulting code:
See all the commits here if you want to follow the process.
You can find all the code on GitHub.
Monday, September 12, 2016
Kata: Parrot Refactoring in Clojure
I did Emily Bache's Parrot Refactoring Kata again (I did this kata in Java some time ago) but this time in Clojure. This is a very simple kata that is meant to practice the Replace Conditional with Polymorphism refactoring.
This is the initial code of the kata that have to be refactored:
Since Clojure provides several ways of achieving polymorphism, I did two versions of the kata:
- One using protocols:
This refactoring was a bit more involved than the one I did for the next version, but I managed to get rid of the exception and the resulting tests were more readable.
If you feel like following the refactoring process, check the baby steps in the commits. You can find the code in this GitHub repository.
- And another one using multimethods:
This version is much shorter and the refactoring is less involved than the previous one, but the resulting tests read much worse and the map representing the parrot has many "optional" entries.
Again, check the commits of the refactoring baby steps here, if you feel like following the refactoring process. You can find the code of this second version in this GitHub repository. I'd like to thank Emily Bache for sharing this kata.
This is the initial code of the kata that have to be refactored:
Since Clojure provides several ways of achieving polymorphism, I did two versions of the kata:
- One using protocols:
This refactoring was a bit more involved than the one I did for the next version, but I managed to get rid of the exception and the resulting tests were more readable.
If you feel like following the refactoring process, check the baby steps in the commits. You can find the code in this GitHub repository.
- And another one using multimethods:
This version is much shorter and the refactoring is less involved than the previous one, but the resulting tests read much worse and the map representing the parrot has many "optional" entries.
Again, check the commits of the refactoring baby steps here, if you feel like following the refactoring process. You can find the code of this second version in this GitHub repository. I'd like to thank Emily Bache for sharing this kata.
Saturday, September 10, 2016
Interesting Talk: "How the web is democratizing science (join in!)"
I've just watched this interesting talk by Abigail Cabunoc Mayes about Open Science
Thursday, September 8, 2016
Mob Kata: Cellular Automata in Clojure
At this week's Clojure Developers Barcelona meetup, we did the Cellular Automata kata in Clojure.
We did mob programming and used a mix of TDD and RDD.
This is the code we wrote:
First, the tests using Midje for the rules 30 and 90:
and the tests for the evolution and rendering of automata:
This is the corresponding code for the rules:
and for the automaton evolution and rendering:
Printing on the REPL the result of rendering the Rule 90 automaton evolution during 15 steps, we obtain a nice Sierpinski triangle :
You can find the code in this GitHub repository.
As usual, it was a pleasure to meet and program with Clojure Developers Barcelona members.
We did mob programming and used a mix of TDD and RDD.
This is the code we wrote:
First, the tests using Midje for the rules 30 and 90:
and the tests for the evolution and rendering of automata:
This is the corresponding code for the rules:
and for the automaton evolution and rendering:
Printing on the REPL the result of rendering the Rule 90 automaton evolution during 15 steps, we obtain a nice Sierpinski triangle :
You can find the code in this GitHub repository.
As usual, it was a pleasure to meet and program with Clojure Developers Barcelona members.
Friday, September 2, 2016
Kata: Varint in Clojure using Midje and test.check
In last week's Barcelona Software Craftsmanship Dojo we did the Varint kata created by Eric Le Merdy.
Since I was facilitating it, I couldn't code during the event.
Once I got home, I did it using Clojure.
These are the tests using Midje and Clojure test.check libraries:
and this is the resulting code:
I used a mix of a bit of TDD, a lot of REPL-driven development (RDD) and some property-based testing.
Basically, the cycle I followed was like this:
This way I wrote both encode and decode functions.
Once I had then working with a few examples, I added property-based tests using Clojure test.check library (a QuickCheck like library for Clojure) to automatically explore more examples by checking that the property of "decoding and encoded number returns the number" held for 1000 randomly generated examples.
I think that these three techniques are complementary and its combination makes me more productive.
To document the development process I commit after each TDD green step and after each refactoring. I also committed the REPL history.
See all the commits here if you want to follow the process.
You can find all the code on GitHub.
Since I was facilitating it, I couldn't code during the event.
Once I got home, I did it using Clojure.
These are the tests using Midje and Clojure test.check libraries:
and this is the resulting code:
I used a mix of a bit of TDD, a lot of REPL-driven development (RDD) and some property-based testing.
Basically, the cycle I followed was like this:
- Write a failing test (using more complicated examples than the typical ones you use when doing only TDD).
- Explore and triangulate on the REPL until I made the test pass with some ugly complete solution.
- Refactor the code to make it more readable.
This way I wrote both encode and decode functions.
Once I had then working with a few examples, I added property-based tests using Clojure test.check library (a QuickCheck like library for Clojure) to automatically explore more examples by checking that the property of "decoding and encoded number returns the number" held for 1000 randomly generated examples.
I think that these three techniques are complementary and its combination makes me more productive.
To document the development process I commit after each TDD green step and after each refactoring. I also committed the REPL history.
See all the commits here if you want to follow the process.
You can find all the code on GitHub.
Subscribe to:
Posts (Atom)