Eric Elliott
Aug 28, 2017 · 3 min read

‘I’m not sure so much that’s “hard”, it’s more that most serious projects (with 30k+ LOC, 30+ developers, very complicated workflows, etc) are going to require something more than “pure functions” at the unit level.’

I developed my current approach while working on a Million+ LOC codebase with 100+ contributing developers. I have since mentored people on teams building apps with hundreds of millions of users and customers to reproduce those benefits at multiple fortune 500 companies.

The advantage of using more pure functions is that it introduces very important simplifying factors:

  • Deterministic state reproduction
  • Removal of state dependencies
  • Easier refactoring, moving code around
  • Easier maintenance
  • Easier to extend code

For more on these topics and advantages, see:

This is not to say that functional programming is better than object-oriented programming, but it definitely is an assertion that imperative and object-oriented programmers can learn a lot from functional programming with regard to writing more loosely-coupled, deterministic code — especially to simplify very large codebases and ease coordination overhead on very large teams.

Shared-mutable state is just another form of spaghetti code, and spaghetti code is the last thing you want in a large enterprise app with lots of contributors. The advantage of purity is that it isolates and encapsulates complexity so that side-effects, network I/O, etc… do not bleed into other parts of the app. It has a radically simplifying effect on large apps.

That makes it much easier for a large group of developers to understand what’s going on in their part of the app, without needing to understand the full mutation history of every variable they touch.

“‘Most of your test value there is in integration land, not unit land, since your backend code is mostly just marshalling data to/from your database and likely also depending on logic that is applied from other services (microservices architecture). I don’t think the approach you are suggesting stands up to realistic demands in larger projects, especially on the backend.”

More reliance on pure functions and less reliance on shared mutable state and side-effects leads to a shift in balance between unit tests and integration tests, making it much easier to test much larger chunks of your apps using simple, pure functions and equational reasoning. The benefits are many:

  • Pure code is synchronous, and generally much faster — unit tests finish in milliseconds, not minutes or hours
  • Faster tests = more reliance on tests = better coverage = fewer bugs
  • Faster tests = realtime developer feedback = enhanced productivity — developers spend less time manually checking their work building, loading up the whole app with the whole UI + networking layer, so they can spend more time just making their functions behave as expected instead of manually testing things.

You still do need integration & functional tests, of course, but they become more of a sanity check — “does everything fit together as expected?” rather than the primary check for application correctness.

For more on that topic, and the correct role of various types of tests, see “JavaScript Testing: Unit vs Functional vs Integration Tests”.

)

    Eric Elliott

    Written by

    Make some magic. #JavaScript

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade