Friday, November 25, 2016

Creating custom effects in re-frame

In previous posts, we learned how to use coeffects and effects in re-frame to have effectful event handlers that are pure functions.

The example with effects we saw, used two of re-frame's built-in effect handlers (dispatch and dispatch-later). Since the set of possible side-effects is open-ended, re-frame gives you a way to define your own effects.

In this post, we'll show how to create your own effect by defining one that writes to the local storage.

Let's have a look at an event handler using that effect that writes to the local storage:

Notice the a key-value pair having the key :write-localstore in the effects map returned by the event handler. This key-value pair is telling re-frame to do a side-effect, which is uniquely identified by that key and requires the data in the corresponding value. But, how does re-frame know how to action on the :write-localstore effect?

We have to use re-frame's reg-fx function to associate the effect key, (:write-localstore), with an effect handler, (local-store/write function):

reg-fx receives two arguments: the key that identifies the effect and the function which actions the side-effect, the effect handler.

When an event handler returns an effects map which contains a given effect key, the effect handler associated with it using reg-fx will be called to action on the effect, passing it the value associated to the effect key in the effects map.

The local-store/write function is passed a map containing the key-value pairs it has to write to the local store.

Finally, this is how we'd test the event handler using it:

being check-writing-to-local-storage-contains and check-writing-to-local-storage:

And that's all we need to know in order to create a custom effect in re-frame.

Thursday, November 17, 2016

Interesting Podcast: "Cognicast with Paul Stadig"

I've just listened to this great Cognicast podcast with Paul Stadig talking about about Polymorphism and other interesting things:

Quotes from "Why should physicists study history?"

My top highlights from the wonderful paper Why should physicists study history? by Matthew Stanley:
"History is not a list of names and dates. It's a way of thinking that can be powerful and illuminating."

"Social interactions really do influence what scientist produce."

"How a community tells its history changes the way it thinks about itself."

"A historical perspective on science can help physicists understand what is going on when they practice their craft, and it provides numerous tools that are useful for physicists themselves."

"Physics is a social endeavor."

"Research is done by people. And people have likes and dislikes, egos and prejudices. Physicists, like everyone else get attached to their favorite ideas and hang on them perhaps long after they should let them go."

"The history of science can help dismantle the myth of the purely rational genius living outside the everyday world. It makes physics more human."

"And a more human physics is a good thing. For starters, it makes physics more accessible."

"A field in which people are aknowledged as people is much more appealing than one in which they are just calculating machines."

"Physics only work when people talk to each other and communication is not always easy."

"Everything seems obvious in retrospect."

"The history of physics can remind us how difficult is to justify ideas that now seem obvious."

"Complexity, not simplicity , has ruled the practice of science."

"Every discovery has come out of a messy mix of people, ideas, accidents and arguments."

"Students and young researchers are often heartened to learn that physics is hard work and that it is ok for their own efforts not to look like a text-boo presentation. Messiness is a standard. Mistakes are normal. The results of physics are not self-evident."

"The history of physics suggests that there are usually several ways to approach a problem."

"Turning complexity into good physics requires creativity. You can never tell what weird idea will help clarify a confusing observation or provide the key to interpreting an equation. History uncovers the strange stew of concepts that were necessary for the development of physics."

"The interplay of various approaches is what brought us a modern view."

"Strange but ultimately useful perspectives come from fields and disciplines apparently distant from the problem at hand."

"The history of science shows how important it is for scientists across different fields to talk to each other. Conversations among separate groups are healthy. Apparently isolated problems are often closedly tied together, and you never know where you will find the weird idea that solves your difficulty."

"The best strategy for encouraging diverse ideas is to cultivate a diverse community."

"Underrepresented groups that offer different ways of thingking are often the source of fresh insights and novel methods."

"Underrepresented groups are usually marginalized because of cultural inertia or deliberate decisions made long ago."

"The diversity of ideas and interpretations serves as a reminder that physics is a work in progress. Knowledge is provisional. There are always new ways to tackle a problem, and there is always more to be learned."

"Accepting uncertainty would require changes in how science is taught."

"Curiosity should be revered, and everyone should be encouraged to ask, what else?"

"If scientist are not explicit and honest about their doubts, a crisis of confidence arises when that uncertainty is revealed."

"Physics wasn't always as it is."

"The flip side of accepting physics will be different in the future is accepting that it was different in the past. Everyone has a tendency to assume that the way things are now is the norm. But history makes it clear that things were not always this way. An understanding of why people used to think differently is a powerful tool for understanding people today. By drawing attention to older, usnpoken assumptions, history shows us how to start paying attention to our own."

"A knowledge of the historic and physical background, gives the kind of independence from prejudices of his generation from which most scientists are suffering" Einstein


"..they should study the history of those ideas and understand the circumstances in which they were justified and found useful."

"History trains you to think critically about received ideas. History provides evidence of roads not taken."

"Science's plurality of interpretation can make the history of science a resource for modern scientific research." Hasok Chang
"Complementary Science -> recovering forgotten and unsolved puzzles from the past."

"Putting complementary science into practice demands difficult self-examination. Thinking deeply about assumptions and accepted knowledge can be hard to do in professional scientific contexts, but history is a mode in which it's encouraged."

"The simple realization that people used to think differently can be quite powerful."

"Physics doesn't have rigid rules."

"Scientist simply don't follow a rigid, linear problem-solving system. Sometimes they start with a hypothesis, sometimes with a strange observation, sometimes with a weird anomaly in an otherwise straightforward experiment."

"... a scientist must be an "unscrupulous opportunist", adopting and adapting various approaches as new challenges arise."

"History teaches that knowledge is not fixed."

"Engaging with history will teach you to understand ideas on their own terms."

"Historical thinking makes its subject dynamic. It helps you think about science as a series of questions rather than a series of statements. Those questions will continue into the future, and it is helpful to know what has been asked so far." "In the end, history of science exposes scientists to new ways of thinking and forces them to reexamine what is already known. Such intellectual flexibility is essential for any discipline, but it's particularly important for fields as influential and authoritative as physics and other sciences."

Thursday, November 10, 2016

Using effects in re-frame

In re-frame, we'd like to use pure event handlers because they provide some important advantages, (mentioned in a previous post about coeffects in re-frame): local reasoning, easier testing, and events replay-ability.

However, as we said, to build a program that does anything useful, it's inevitable to have some side-effects and/or side-causes. So, there will be many cases in which event handlers won't be pure functions.

We also saw how using coeffects in re-frame allows to have pure event handlers in the presence of side-causes.

In this post, we'll focus on side-effects:
If a function modifies some state or has an observable interaction with calling functions or the outside world, it no longer behaves as a mathematical (pure) function, and then it is said that it does side-effects.
Let's see some examples of event handlers that do side-effects (from a code animating the evolution of a cellular automaton):

These event handlers, registered using reg-event-db, are impure because they're doing a side-effect when they dispatch the :evolve event. With this dispatch, they are performing an action at a distance, which is in a way a hidden output of the function.

These impure event handlers are hard to test. In order to test them, we'll have to somehow spy the calls to the function that is doing the side-effect (the dispatch). Like in the case of side-causes from our previous post, there are many ways to do this in ClojureScript, (see Isolating external dependencies in Clojure), only that, in this case, the code required to test the impure handler will be a bit more complex, because we need to keep track of every call made to the side-effecting function.

In this example, we chose to make explicit the dependency that the event handler has on the side-effecting function, and inject it into the event handler which becomes a higher order function. Actually, we injected a wrapper of the side-effecting function in order to create an easier interface.

Notice how the event handlers, evolve and start-stop-evolution, now receive as its first parameter the function that does the side-effect, which are dispatch-later-fn and dispatch, respectively.

When the event handlers are registered with the events they handle, we partially apply them, in order to pass them their corresponding side-effecting functions, dispatch-later for evolve and dispatch for start-stop-evolution:

These are the wrapping functions:

Now when we need to test the event handlers, we use partial application again to inject the function that does the side-effect, except that, in this case, the injected functions are test doubles, concretely spies which record the parameters used each time they are called:

This is very similar to what we had to do to test event handlers with side-causes in re-frame before having effectful event handlers (see previous post). However, the code for spies is a bit more complex than the one for stubs.

Using test doubles makes the event handler testable again, but it's still impure, so we have not only introduced more complexity to test it, but also, we have lost the two other advantages cited before: local reasoning and events replay-ability.

Since re-frame's 0.8.0 (2016.08.19) release, this problem has been solved by introducing the concept of effects and coeffects.

Whereas, in our previous post, we saw how coeffects can be used to track what your program requires from the world (side-causes), in this post, we'll focus on how effects can represent what your program does to the world (side-effects). Using effects, we'll be able to write effectful event handlers that keep being pure functions.

Let's see how the previous event handlers look when we use effects:

Notice how the event handlers are not side-effecting anymore. Instead, each of the event handlers returns a map of effects which contains several key-value pairs. Each of these key-value pairs declaratively describes an effect using data. re-frame will use that description to actually do the described effects. The resulting event handlers are pure functions which return descriptions of the side-effects required.

In this particular case, when the automaton is evolving, the evolve event handler is returning a map of effects which contains two effects represented as key/value pairs. The one with the :db key describes the effect of resetting the application state to a new value. The other one, with the :dispatch-later key describes the effect of dispatching the :evolve event after waiting 100 microseconds. On the other hand, when the automaton is not evolving, the returned effect describes that the application state will be reset to its current value.

Something similar happens with the start-stop-evolution event handler. It returns a map of effects also containing two effects. The one with the :db key describes the effect of resetting the application state to a new value, whereas the one with the :dispatch key describes the effect of immediately dispatching the :evolve event.

The effectful event handlers are pure functions that accept two arguments, being the first one a map of coeffects, and return, after doing some computation, an effects map which is a description of all the side-effects that need to be done by re-frame.

As we saw in the previous post about coeffectts, re-frame's effectful event handlers are registered using the reg-event-fx function:

These are their tests:

Notice how by using effects we don't need to use tests doubles anymore in order to test the event handlers. These event handlers are pure functions, so, besides easier testing, we get back the advantages of local reasoning and events replay-ability.

:dispatch and :dispatch-later are builtin re-frame effect handlers already defined. It's possible to create your own effect handlers. We'll explain how and show an example in a future post.

Interesting Paper: "Designing software for ease of extension and contraction"

I've just read this great paper by David L.Parnas

Wednesday, November 2, 2016

Codesai

I'm very happy to announce that I've joined Codesai's team.

Many reasons made my path converge with Codesai's one.

First of all, the people in Codesai.
I met Carlos in 2011, because he was teaching the first TDD course I attended. Carlos is a humble and honest person that tries very hard to make sure his actions match what he believes. Later I've known him as a quiet, open-minded leader who is always willing to listen what other people have to say, and this permeates the whole Codesai team. During the last two years, I had the opportunity to meet most of Codesai's apprentices. They are very enthusiastic and eager to learn. I had great fun participating with them in some Software Craftsmanship Gran Canaria events and talking about code and life in general in Codesai's apartment.

I share Codesai's values and feel very confortable with their culture and communication style because the team creates a healthy and safe environment which respects the diversity of its members and the debate of ideas.

I met the rest of the team last week during Codesai's summit (aka #flejesai16) and it was a confirmation that I'm in the right place.

Second, the opportunity to learn from experienced XP practicioners.
I've been developing software for 6 years now. I've learned a lot, most of it by reading books, practising on my own, attending courses and from colleagues, both from the community and at work. However, I felt the need of having a mentor, because I think I'll learn more and better than if I keep working on my own. I've found some great mentors in Codesai who acknowledge that I need a safe environment to get experience step by step.

Finally, the last reason is more personal.
I live in Barcelona but I'm from Canary Islands. Codesai is a remote-first team but the core of Codesai's team is currently in my hometown in the Canary Islands. So being a part of Codesai also gives me the chance of visiting my family more often.

So far I'm enjoying the Codesai experience a lot.

I think we'll keep on evolving as a team and do great things.

Thanks a million for letting me in!