Thursday, January 3, 2019

Avoid using subscriptions only as app-state getters

Introduction.

Subscriptions in re-frame or re-om are query functions that extract data from the app-state and provide it to view functions in the right format. When we use subscriptions well, they provide a lot of value[1], because they avoid having to keep derived state the app-state and they dumb down the views, that end up being simple “data in, screen out” functions.

However, things are not that easy. When you start working with subscriptions, it might happen that you end up using them as mere getters of app-state. This is a missed opportunity because using subscriptions in this way, we won’t take advantage of all the value they can provide, and we run the risk of leaking pieces of untested logic into our views.

An example.

We’ll illustrate this problem with a small real example written with re-om subscriptions (in an app using re-frame subscriptions the problem would look similar). Have a look at this piece of view code in which some details have been elided for brevity sake:

this code is using subscriptions written in the horizon.domain.reports.dialogs.edit namespace.

The misuse of subscriptions we’d like to show appears on the following piece of the view:

Notice how the only thing that we need to render this piece of view is next-generation. To compute its value the code is using several subscriptions to get some values from the app-state and binding them to local vars (delay-unit start-at, delay-number and date-modes). Those values are then fed to a couple of private functions also defined in the view (get-next-generation and delay->interval) to obtain the value of next-generation.

This is a bad use of subscriptions. Remember subscriptions are query functions on app-state that, used well, help to make views as dumb (with no logic) as possible. If you push as much logic as possible into subscriptions, you might achieve views that are so dumb you nearly don’t need to test, and decide to limit your unit tests to do only subcutaneous testing of your SPA.

Refactoring: placing the logic in the right place.

We can refactor the code shown above to remove all the leaked logic from the view by writing only one subscription called next-generation which will produce the only information that the view needs. As a result both get-next-generation and delay->interval functions will get pushed into the logic behind the new next-generation subscription and dissappear from the view.

This is the resulting view code after this refactoring:

and this is the resulting pure logic of the new subscription. Notice that, since get-next-generation function wasn’t pure, we had to change it a bit to make it pure:

After this refactoring the view is much dumber. The previously leaked (an untested) logic in the view (the get-next-generation and delay->interval functions) has been removed from it. Now that logic can be easyly tested through the new next-generation subscription. This design is also much better than the previous one because it hides how we obtain the data that the view needs: now both the view and the tests ignore, and so are not coupled, to how the data the view needs is obtained. We might refactor both the app-state and the logic now in get-next-generation and delay->interval functions without affecting the view. This is another example of how what is more stable than how.

Summary

The idea to remember is that subscriptions by themselves don’t make code more testable and maintainable. It’s the way we use subscriptions that produces better code. For that the logic must be in the right place which is not inside the view but behind the subscriptions that provide the data that the view needs. If we keep writing “getter” subscriptions” and placing logic in views, we won’t gain all the advantages the subscriptions concept provides and we’ll write poorly designed views coupled to leaked bunches of (very likely untested) logic.

Acknowledgements.

Many thanks to André Stylianos Ramos and Fran Reyes for giving us great feedback to improve this post and for all the interesting conversations.

Footnotes:

[1] Subscriptions also make it easier to share code between different views and, in the case of re-frame (and soon re-om as well), they are optimized to minimize unnecessary re-renderings of the views and de-duplicate computations.

Interesting Talk: "Improving as developers"

I've just watched this wonderful talk by Belén Albeza

Monday, December 31, 2018

Books I read 2018

January
- The Plateau Effect: Getting from Stuck to Success, Bob Sullivan & Hugh Thompson
- The Thirty-Nine Steps, John Buchan
- Memento Mori, Muriel Spark
- Cosmonauta, Pep Brocal
- The Man Who Was Thursday: A Nightmare, G. K. Chesterton
- Ébano, Alberto Vázquez-Figueroa
- The Subtle Art of Not Giving a F*ck: A Counterintuitive Approach to Living a Good Life, Mark Manson
- The Importance of Being Earnest, Oscar Wilde

February
- The Maltese Falcon, Dashiell Hammett
- This Is Water, David Foster Wallace
- Judas, Amos OZ
- Never Let Me Go, Kazuo Ishiguro.
- Microservice Architecture: Aligning Principles, Practices, and Culture, Mike Amundsen, Matt McLarty, Ronnie Mitra, Irakli Nadareishvili

March
- On Anarchism, Noam Chomsky
- The Fire Next Time, James Baldwin
- Esperanza en la oscuridad, La historia jamás contada del poder de la gente (Hope in the Dark: Untold Histories, Wild Possibilities), Rebecca Solnit
- The Dispossessed: An Ambiguous Utopia, Ursula K. Leguin
- Release It!: Design and Deploy Production-Ready Software, Michael T. Nygard

April
- Sin blanca en Paris y Londres (Down and Out in Paris and London), George Orwell
- The Garden of the Finzi-Continis (Il giardino dei Finzi-Contini), Giorgio Bassani
- Test Driven Development: By Example, Kent Beck (2nd time)
- Just Enough: Tools for Creating Success in Your Work and Life, Laura Nash and Howard Stevenson
- The Left Hand of Darkness, Ursula K. Leguin
- The Heat of the Day, Elizabeth Bowen

May
- Radetzky March (Radetzkymarsch), Joseph Roth
- Death of a Salesman, Arthur Miller
- A Raisin in the Sun, Lorraine Hansberry
- Improve Your People Skills: Build and Manage Relationships, Communicate Effectively, Understand Others, and Become the Ultimate People Person, Patrick King
- Flatland: A Romance of Many Dimensions, Edwin Abbott
- The Hard Truth About Soft Skills: Workplace Lessons Smart People Wish They'd Learned Sooner, Peggy Klaus

June
- The Little Guide to Empathetic Technical Leadership, Alex Harms
- Patria, Fernando Aramburu
- How to Be an Imperfectionist: The New Way to Fearlessness, Confidence, and Freedom from Perfectionism, Stephen Guise
- Dragon's Egg, Robert L. Forward

July
- Deep Work: Rules for Focused Success in a Distracted World, Cal Newport
- Essay and report writing skills, The Open University
- El candelabro enterrado (Der begrabene Leuchter), Stefan Zweig
- To Engineer Is Human: The Role of Failure in Successful Design, Henry Petroski
- La evolución de Calpurnia Tate (The Evolution of Calpurnia Tate), Jacqueline Kelly
- The Secret Agent: A Simple Tale, Joseph Conrad
- Men Explain Things to Me, Rebecca Solnit
- Facts And Fallacies Of Software Engineering, Robert L. Glass

August
- The Lonely Londoners, Samuel Selvon
- El poder y la palabra: 10 ensayos sobre lenguaje, política y verdad, (Spilling the Spanish Beans, New Words, Literature and Totalitarianism, Pamphlet Literature, Propaganda and Demotic Speech, The Prevention of Literature, Politics and the English Language, In Front of Your Nose, Writers and the Leviathan, The Principles of Newspeak), George Orwell
- Comportarse como adultos: mi batalla contra el establishment europeo, (Adults in the Room: My Battle With Europe's Deep Establishment), Yanis Varoufakis
- Patterns of Software: Tales from the Software Community, Richard P. Gabriel
- Passing, Nella Larsen
- Why Information Grows: The Evolution of Order, from Atoms to Economies, César A. Hidalgo
- The Martians of Science: Five Physicists Who Changed the Twentieth Century, István Hargittai

September
- On Dialogue, David Bohm
- The Alteration, Kingsley Amis
- Pavane, Keith Roberts
- The Logic of Failure: Recognizing and Avoiding Error in Complex Situations, Dietrich Dörner
- Extending and developing your thinking skills, The Open University

October
- Skin in the Game: Hidden Asymmetries in Daily Life, Nassim Nicholas Taleb
- Hard to Be a God (Трудно быть богом), Arkady Strugatsky and Boris Strugatsky
- The Buddha of Suburbia, Hanif Kureishi
- The Power of the Powerleses (Moc bezmocných), Václav Havel
- Contra el fascismo (Ur-Fascism), Umberto Eco
- The Fifth Season, N. K. Jemisin
- The Obelisk Gate, N. K. Jemisin

November
- The Stone Sky, N. K. Jemisin
- Beyond Blame: Learning from Failure and Success, Dave Zwieback
- A Philosophy of Software Design, John Ousterhout
- Muerte en Estambul (Παλιά, Πολύ Παλιά), Petros Markaris
- 168 Hours: You Have More Time Than You Think, Laura Vanderkam

December
- Heart of Darkness, Joseph Conrad
- Working Effectively with Legacy Code, Michael C. Feathers (2nd time)
- Frankenstein or The Modern Prometheus, Mary Shelley
- The Myth of Sisyphus (Le Mythe de Sisyphe), Summer in Algiers (L'été à Alger), The Minotaur or The Stop in Oran (Le minotaure ou la halte d'Oran), Helen's Exile (L'exil d'Hélène), Return to Tipasa (Retour à Tipasa), The Artitst and his Time (L'artiste et son temps), Albert Camus
- A Room of One's Own, Virginia Woolf