Skip to content

Instantly share code, notes, and snippets.

@ashumeow
Forked from addyosmani/composition.md
Last active August 29, 2015 14:11
Show Gist options
  • Save ashumeow/673af8f875d393adecac to your computer and use it in GitHub Desktop.
Save ashumeow/673af8f875d393adecac to your computer and use it in GitHub Desktop.

In architectural terms, the way we craft large-scale applications in JavaScript has (in my opinion) changed in one fundamental way in the last three years. Once you remove the minutia of machinery bringing forth data-binding, immutable data-structures and virtual-DOM the one key concept that many devs seem to have organically converged on is composition. Composition is incredibly powerful, allowing us to stitch together reusable pieces of functionality to "compose" a larger application. Composition eschews in a mindset of things being good when they're modular, smaller and easier to test. Easier to reason with. Easier to distribute. Heck, just look at how well that works for Node via npm. Composition is one of the reasons we regularly talk about React "Components", "Ember.Component", Angular directives, Polymer elements and of course, straight-up Web Components. We may argue about the frameworks and libraries surrounding these different flavours of component, but not that composition is inherently a bad thing. Note: undoubtedly earlier players in the JS framework game touched on composition but it's taken us a while for most people to grok the true power of this model.

Composition is one solution to the problem of application complexity. Now, the way that languages in the web platform evolve are in direct response to the pain caused by such complexity. Pain is generally a bad thing and so it’s with better patterns and platform primitives that we can ease some of this complexity in the browser. Complexity on its own can take lots of forms, but when we look at the landscape of how developers have been building for the web over the last few years, common patterns can be one the most obvious things worth considering baking in solutions for. This is why an acknowledgement by browser vendors that Web Components are important is a big deal. Even if you absolutely don't use 'our' flavour of them (I'll contest they are powerful), hopefully you dig composition enough to use a solution that offers it.

I've written in the past about the net gains of large-scale systems that take advantage of decoupling and a sane approach to JavaScript 'modules'. I consider us in a far far better position now than we were a few years ago. It's almost passe to frown at someone using a build-step in their authoring workflow and we can thank the abundance of increasingly reliable tooling around Browserify and ES6 for this. Whether it's ES6 modules, classes or CJS we have sufficient tooling to gift our projects with strong compositions whether they're client or server-side, isomorphic or otherwise. That's kind of amazing. Don't get me wrong, we have a long road ahead towards maturing the quality of our ecosystems but our composition story for the front-end is strong today.

One could argue that the "facade pattern" I've touched on in previous literature is still viable today, especially if you don't allow the implementation details of your component leak into its public API. If you are able to define a clean, robust interface to your component, consumers of it can continue to utilize said components without worrying about the implementation details . Those can change at any time with minimal breakage. An addendum to this could be that this is a good model for framework and library authors to follow for public components they ship. While this is absolutely not tied to Web Components, I've enjoyed seeing the Polymer paper-* elements evolve over time with the machinery behind the scenes having minimal impact to public component APIs. This is inherently good for users. Try not to violate the principle of least astonishment i.e the users of your component API shouldn't be surprised by behaviour. Hold this true and you'll have happier users and a happier team.

Beyond an agreement that composition is fundamentally good, we still disagree on a lot. Separation of concerns. Structure. Data-flow. The necessity for immutable data structures. The correct level of magic for our abstractions. The right place to solve issues with our rendering pipelines (native vs. virtual diffing). How to hit 60fps in our user-interfaces. How to deliver offline experiences to everyone, whether their browsers support Service Worker or not. Ultimately how you 'solve' these problems today comes down to asking yourself three questions:

  1. Are you happy delegating such decisions and choices to an opinionated framework?
  2. Are you happy 'composing' solutions to these problems using existing modules?
  3. Are you happy crafting (from scratch) the architecture and pieces that solve these problems on your own?

I'll attempt to write more soon, but until then; good luck ; )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment