Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Don't Go Changin'

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

Don't Go Changin'

Recorded talk @ ScotlandJS 2014 :: https://vimeo.com/96425437

JavaScript is a flexible, dynamic programming language, but along with this flexibility comes a cost: ubiquitous mutability. Trying to keep track of the internal state of your JavaScript application can be an endless source of confusion. As our applications get bigger and bigger, it only gets worse. In fact, mutable state is the cause of enough confusion and complexity that entire languages have been written around the idea of avoiding it!

We're taught to write our programs like they're a step-by-step set of instructions. We say "do this" and it happens; "change that", and it changes. We're encouraged to reassign variables and change the contents of our data structures at will, for example. In fact, ever since we wrote our first line of JavaScript, we've been taught that this dynamism is a good thing, but the problems mutability introduce are just something that we just have to put up with.

What if there was a better way? What if we could go a long way towards solving these problems and make our programs much easier to build, maintain and test? We can!

In this talk, we'll revisit exactly what we think we understand about 'state', look at the concept of 'values' as our core orientation, and look at how we can pull ourselves out of the complexity quagmire by taming our applications using immutability.

Avatar for Matt Field

Matt Field

May 10, 2014

Other Decks in Programming

Transcript

  1. “We believe that the major contributor to...complexity in many systems

    is the handling of state and the burden that this adds when trying to analyse and reason about the system.” #sjsMatt
  2. “...it is ironic that introductory programming is most often taught

    in a highly imperative style.” - Structure and Interpretation of Computer Programs, Abelson and Sussman #sjsMatt
  3. ๏ Uncertainty of state at a particular time ๏ Hard

    to analyse and reason about #sjsMatt Problems
  4. ๏ Sprawling test suites ๏ Limited degree of code confidence

    ๏ Uncertainty of state at a particular time ๏ Hard to analyse and reason about #sjsMatt Problems
  5. “The most disastrous thing that you can ever learn is

    your first programming language” - Alan Kay #sjsMatt
  6. The value of an identity at a moment in time

    Snapshot Immutable #sjsMatt
  7. Definitions Value: An immutable entity or a composite thereof Identity:

    A concept associated with a causally- related set of values over time State: Value of an identity at a moment in time #sjsMatt Change: Movement from one state to another
  8. Redefining data structures ๏ A series of states over time

    that we attach an identity to #sjsMatt
  9. Redefining data structures ๏ Entities whose change is the movement

    between immutable states not time-sensitive mutation ๏ A series of states over time that we attach an identity to #sjsMatt
  10. Redefining data structures ๏ Entities whose change is the movement

    between immutable states not time-sensitive mutation ๏ A series of states over time that we attach an identity to #sjsMatt ๏ Structures whose state can be captured with certainty, stored and re-used later without fear of change
  11. ๏ Don’t rely on data that changes outside of it’s

    control ๏ Result calculated only from values of arguments #sjsMatt Pure functions
  12. ๏ Can’t change the state of something external ๏ Don’t

    rely on data that changes outside of it’s control ๏ Result calculated only from values of arguments #sjsMatt Pure functions
  13. ๏ Can’t change the state of something external ๏ Don’t

    rely on data that changes outside of it’s control ๏ Result calculated only from values of arguments #sjsMatt Pure functions ๏ Pure functions are values
  14. #sjsMatt ๏ Updated by creating a copy with modifications (copy-on-write)

    i.e. a new state ๏ Immutable (can’t be modified in place) v. Persistent Data Structures
  15. #sjsMatt ๏ Updated by creating a copy with modifications (copy-on-write)

    i.e. a new state ๏ Immutable (can’t be modified in place) v. Persistent Data Structures ๏ Preserve historical versions of its state with same update and lookup complexity guarantees
  16. var listOne = cons(5); //=> {value: 5} var listTwo =

    cons(4, listOne); //=> {value: 4, prev: {value: 5}} var listThree = cons(3, listTwo); //=> {value: 3, prev: {value: 4, prev: {value: 5}}} cons(3, cons(4, cons(5))) //=> {value: 3, prev: {value: 4, prev: {value: 5}}} #sjsMatt
  17. Clojure (def my-map {:a 1, :b 2}) ;; {:a 1,

    :b 2} (assoc my-map :c 3) ;; {:a 1, :b 2, :c 3} my-map ;; {:a 1, :b 2} #sjsMatt
  18. Mori #sjsMatt ๏ Uniform iteration for all types, including nearly

    all native JavaScript types ๏ Efficient, immutable data structures - no defensive cloning required
  19. Mori #sjsMatt ๏ Value-based equality ๏ Uniform iteration for all

    types, including nearly all native JavaScript types ๏ Efficient, immutable data structures - no defensive cloning required
  20. Mori #sjsMatt ๏ Value-based equality ๏ Uniform iteration for all

    types, including nearly all native JavaScript types ๏ Efficient, immutable data structures - no defensive cloning required ๏ Lazy evaluation and memoization
  21. var v1 = mori.vector(1, 2, 3); var v2 = mori.conj(v1,

    4); v2.toString(); //=> [1 2 3 4] v1.toString(); //=> [1 2 3] Mori #sjsMatt
  22. function Calendar(appts) { appts = appts || mori.sorted_set_by(compareAppts); var cal

    = {}; cal.add = function(appt) { var withAppt = mori.conj(appts, appt); return Calendar(withAppt); }; cal.upcoming = function(start, n) { var futureAppts = mori.filter(function(a) { return a.date >= start; }, appts); return mori.take(n, futureAppts); }; return cal; } #sjsMatt
  23. var myCal = Calendar().add({ title: "Portland JavaScript Admirers' Monthly Meeting",

    date: Date.parse("2014-09-25T19:00") }).add({ title: "Code 'n' Splode Monthly Meeting", date: Date.parse("2014-09-24T19:00") }).add({ title: "WhereCampPDX 6", date: Date.parse("2014-09-28T09:00") }); var nextAppts = myCal.upcoming(Date.now(), 2); mori.map(function(a) { return a.title; }, nextAppts); //=> ("Code 'n' Splode Monthly Meeting" "Portland JavaScript Admirers' Monthly Meeting") #sjsMatt
  24. Undo #sjsMatt function Calendar(appts, prevCal) { cal.add = function(appt) {

    var withAppt = mori.conj(appts, appt); return Calendar(withAppt, cal); }; cal.undo = function() { return prevCal || Calendar(); }; } var prevCal = myCal.undo().undo(); var appts = prevCal.upcoming(Date.now(), 2); mori.map(function(a) { return a.title; }, appts); //=> ("Portland JavaScript Admirers' Monthly Meeting")
  25. Conclusion #sjsMatt ๏ A better way to reason about our

    software - make state change explicit ๏ Unchecked, ubiquitous mutation is the root of all evil
  26. Conclusion #sjsMatt ๏ Take values as our primary orientation ๏

    A better way to reason about our software - make state change explicit ๏ Unchecked, ubiquitous mutation is the root of all evil
  27. Conclusion #sjsMatt ๏ Take values as our primary orientation ๏

    A better way to reason about our software - make state change explicit ๏ Unchecked, ubiquitous mutation is the root of all evil ๏ Constantly be questioning whether the complexity you’re facing is essential or incidental