Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Retrofitting a legacy SPA to use a functional architecture


Published on

Improved version of Retrofitting a legacy SPA to use a functional architecture talk for Perl BCN & Friends 2018 event

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Retrofitting a legacy SPA to use a functional architecture

  1. 1. Retrofitting a legacy Om SPA to use a functional architecture Manuel Rivero @trikitrok
  2. 2. About me ● I’m Manuel Rivero (@trikitrok). ● I’m a member of Codesai. ● I collaborate with BCN Software Craftsmanship, Clojure Developers BCN and Aprendices (@deAprendices) communities. ● One of my clients is Green Power Monitor where we develop a SPA using ClojureScript and Om.
  3. 3. Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.
  4. 4. Context
  5. 5. SPA for monitoring and managing renewable energy portfolios using ClojureScript and Om.
  6. 6. Several years of development
  7. 7. A prototype became the product
  8. 8. No testing culture
  9. 9. Initial architecture blurred by employee turnover, technical debt, lack of documentation and design flaws
  10. 10. Two times legacy
  11. 11. Lost mental models Programming as Theory Building, Peter Naur
  12. 12. No tests
  13. 13. The Big Problem
  14. 14. Business logic and effectful code not clearly separated
  15. 15. Conflating pure and effectful code destroys the advantages of functional programming
  16. 16. Imperative Programming everywhere
  17. 17. Some code samples ● Stateful logic ● Stateful view
  18. 18. Problems ● Action at a distance ○ Difficult to understand ● Difficult to test
  19. 19. Hard to Evolve Safely
  20. 20. Working against the architecture/design
  21. 21. A Pit of Failure
  22. 22. A possible solution: effects and coeffects
  23. 23. Effects and Coeffects ● Effects: describe your program’s side-effects (what it does to the world) ● Coeffects: track your program’s side-causes (what it requires from the world)
  24. 24. A design based on effects and coeffects 1. Extracting all needed data from “the world”
  25. 25. A design based on effects and coeffects 1. Extracting all needed data from “the world” 2. Using pure functions to compute effects
  26. 26. A design based on effects and coeffects 1. Extracting all needed data from “the world” 2. Using pure functions to compute effects 3. Performing the side effects described by effects
  27. 27. Clear isolation of effectful code and business logic
  28. 28. Business logic becomes pure
  29. 29. Advantages ● Local reasoning ○ Easier to understand ● Easier to test
  30. 30. Pure Functional Core, Imperative Shell
  31. 31. Declarative Effects pattern
  32. 32. Declarative Effects pattern ● Business logic is comprised by pure functions ● They receive coeffects and return effects ● Injecting the values coeffects track and interpreting effects to actually perform side-effects are done by sth else (the language run-time, a framework, etc)
  33. 33. re-frame
  34. 34. Unidirectional Data Flow Architecture from re-frame wonderful docs
  35. 35. Event Driven Data Flow
  36. 36. re-frame architecture
  37. 37. Imagine a re-frame app as a reduce
  38. 38. State Management ● At any point in time, app state results from reducing over all events dispatched in the app up until that time. ● The combining function for the reduce is the set of registered event handlers.
  39. 39. Pure functional Core
  40. 40. Pure Functional Core, Imperative Shell
  41. 41. re-frame subscriptions ● Query functions ● Extract data from the app state and provide it to view functions in the right format
  42. 42. Simpler model & Dumb Views ● Avoid having to keep derived state in the model (app state). ● Dumb down the views, that end up being simple “data in, screen out” functions
  43. 43. Improve Performance ● De-duplicating computations ● Reducing re-renderings
  44. 44. A Pit of Success
  45. 45. A Pit of Success “A well-designed system makes it easy to do the right things and annoying (but not impossible) to do the wrong things.” Jeff Atwood
  46. 46. Why not use re-frame then?
  47. 47. A rewrite was not an option
  48. 48. Strangler application pattern Progressively evolve to a re-frame like architecture, while being able to keep adding new features all the time
  49. 49. Strangler application pattern ● All new code would use the new architecture ● Only port bit by bit those legacy parts that needed to change
  50. 50. If you're in a hole, stop digging!
  51. 51. Ok, but why not use re-frame?
  52. 52. Om to reagent: too huge a change ● Heavy investment on Om ● Long coexistence of Om and reagent ● Rewriting components or ● Complicated wrapping to reuse components
  53. 53. re-om is born
  54. 54. Our real goal: having the advantages of re-frame’s architecture in our SPA
  55. 55. re-om was a less risky and progressive way to get it
  56. 56. We wrote an event-driven framework using effects and coeffects and called it re-om as a joke Using re-om event handlers, effects & coeffects sample code
  57. 57. We added subscriptions that worked like re-frame’s ones but with Om components Using re-om subscriptions
  58. 58. Evolving the SPA
  59. 59. ● re-om is not invasive ● Ideal for strangler application pattern re-om
  60. 60. Open-sourcing re-om & reffectory
  61. 61. ● We extracted from re-om the code that was independent of any view technology. ● It might be used as the base for creating frameworks similar to re-om for other view technologies, like for example rum, or used directly in Clojure projects. reffectory
  62. 62. ● Delegates to reffectory for the event-driven system withs effects and coeffects. ● Adds subscriptions that work with Om components. re-om
  63. 63. Conclusions
  64. 64. Thanks to re-om we could start carving islands of pure functional code inside our SPA’s imperative soup
  65. 65. This introduced some sanity in our code base and made its development more sustainable
  66. 66. ● GreenPowerMonitor for open-sourcing re-om and reffectory ● André Stylianos and Joel Sánchez, and the rest of our colleagues at GreenPowerMonitor ● re-frame project, a really wonderful way of writing SPAs, on which re-om is heavily inspired ● Francesc for introducing me to ClojureScript and re-frame Acknowledgements
  67. 67. Thanks!! Manuel Rivero @trikitrok