{"@attributes":{"version":"2.0"},"channel":{"title":"Chris Krycho - javascript","link":"http:\/\/v4.chriskrycho.com\/","description":{},"lastBuildDate":"Sat, 20 Jul 2019 15:05:00 -0400","item":[{"title":"Ember Type-Defs Livestreaming","link":"http:\/\/v4.chriskrycho.com\/2019\/ember-type-defs-livestreaming.html","description":"<p><i><b><a href=\"https:\/\/v4.chriskrycho.com\/2018\/assumed-audiences.html\">Assumed Audience<\/a>:<\/b> People interested in <a href=\"https:\/\/emberjs.com\">Ember<\/a> and\/or <a href=\"http:\/\/www.typescriptlang.org\">TypeScript<\/a>.<\/i><\/p>\n<p>Over the course of the rest of this year, I\u2019m going to be working regularly on expanding the set of available <a href=\"http:\/\/www.typescriptlang.org\">TypeScript<\/a> type definitions in the <a href=\"https:\/\/emberjs.com\">Ember.js<\/a> community. A huge part of that effort is <em>enabling others to do the work<\/em>. It\u2019s completely unfeasible for me to be the only person (or even the Typed Ember team the only people) doing this work. There\u2019s simply too much to be done!<\/p>\n<p>One part of my work, then, is figuring out how to level up the community\u2019s ability to take on these tasks. I\u2019m going to be doing this in a few ways:pairing with people who want to convert their addons to TypeScript or write type definitions for them, creating much deeper guides on <em>how<\/em> to convert a library to TypeScript or write effective types for a third-party library, and\u2014more notably for <em>this<\/em> post\u2014live-streaming, and sharing recordings of, as many of those efforts as I can.<\/p>\n<p>I\u2019m hoping that this will prove a boon not only to the Ember community, but also to the TypeScript community at large. Many people are comfortable working in these spaces\u2026 but especially as TypeScript\u2019s popularity grows, having more of this kind of advanced material will hopefully be a boon to <em>lots<\/em> of teams in <em>lots<\/em> of frameworks and contexts.<\/p>\n<p>You can check out the recording of the first live-stream (working on types for a new module layout in Ember Data 3.11) <a href=\"https:\/\/www.youtube.com\/watch?v=eNLXi-s7-5o\">here<\/a>, and I created a dedicated YouTube playlist for <em>all<\/em> of this content, as well: <a href=\"https:\/\/www.youtube.com\/watch?v=eNLXi-s7-5o&amp;list=PLelyiwKWHHApVB8gKKqZJw8Tv8qqCJGUv\">Typing the Ember.js Ecosystem!<\/a><\/p>\n<p>Here\u2019s <a href=\"https:\/\/www.youtube.com\/watch?v=eNLXi-s7-5o\">the first episode<\/a>! (Note that I accidentally overlapped the tool I\u2019m using to show keystrokes and the video\u2014noob mistake for sure!)<\/p>\n<iframe width=\"560\" height=\"315\" src=\"https:\/\/www.youtube-nocookie.com\/embed\/eNLXi-s7-5o\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\n<\/iframe>\n<p>I expect to be doing this on the following dates almost certainly:<\/p>\n<ul>\n<li>August 16<\/li>\n<li>September 20<\/li>\n<li>October 18 or<\/li>\n<li>November 15<\/li>\n<li>December 20<\/li>\n<\/ul>\n<p>I will also be doing it a number of <em>other<\/em> Fridays throughout the year\u2014most likely beginning with August 9. To watch live, you can <a href=\"https:\/\/www.twitch.tv\/chriskrycho\">follow me on Twitch<\/a>. I\u2019ll also always announce those plans in <a href=\"https:\/\/discordapp.com\/invite\/zT3asNS\">the Ember Discord<\/a> at least one day ahead of time, and I\u2019ll shortly be setting up an ongoing thread in <a href=\"https:\/\/discuss.emberjs.com\">the Ember forums<\/a> for discussion and feedback and the like.<\/p>\n<p>Here\u2019s hoping both Ember and non-Ember users find the materials helpful in picking up TypeScript!<\/p>\n","pubDate":"Sat, 20 Jul 2019 15:05:00 -0400","guid":"tag:v4.chriskrycho.com,2019-07-20:\/2019\/ember-type-defs-livestreaming.html","category":["emberjs","typescript","javascript"]},{"title":"#EmberJS2019, Part 2","link":"http:\/\/v4.chriskrycho.com\/2019\/emberjs2019-part-2.html","description":"<p>Over the last year, the Ember community has steadily delivered on the vision we all traced out in last year\u2019s #EmberJS2018 and Roadmap <abbr title=\"Request for Comments\">RFC<\/abbr> process, culminating with the shipping-very-soon-now <a href=\"https:\/\/emberjs.com\/editions\/octane\/\">Ember Octane Edition<\/a>. (All the pieces are pretty much done and are either on stable or will be shortly; we just need another <abbr title=\"long term support\">LTS<\/abbr> release before we cut a full new edition!)<\/p>\n<p>So\u2026 what should we tackle next? This year, I have only two parts, unlike <a href=\"https:\/\/v4.chriskrycho.com\/emberjs2018\">last year\u2019s four<\/a> (and I\u2019m sneaking them in just under the wire, as today is the deadline for entries!):<\/p>\n<ul>\n<li><b>Part 1:<\/b> <a href=\"https:\/\/v4.chriskrycho.com\/2019\/emberjs2019-part-1\">Let\u2019s finish modernizing the Ember programming model!<\/a><\/li>\n<li><b>Part 2 (this post):<\/b> <a href=\"https:\/\/v4.chriskrycho.com\/2019\/emberjs2019-part-2\">Let\u2019s make TypeScript a first-class citizen of the Ember ecosystem.<\/b><\/a><\/li>\n<\/ul>\n<hr \/>\n<p>For the last two and a half years, I have been working off and on towards making TypeScript viable in Ember apps and addons. I was delighted when others came along to help pick up the load, and we\u2019ve <a href=\"https:\/\/v4.chriskrycho.com\/2019\/emberconf-2019-typed-ember-team-report.html\">charted a course<\/a> for what we\u2019d like to do over the year ahead. The major priorities we identified all point at what I\u2019ve wanted since I started down this road back at the very end of 2016: for TypeScript to be a first-class citizen in the Ember ecosystem. Here\u2019s my roadmap for how we get there. (Note that here I\u2019m speaking only for myself\u2014neither for the Typed Ember team nor for LinkedIn!)<\/p>\n<section id=\"the-roadmap\" class=\"level2\">\n<h2>The Roadmap<\/h2>\n<section id=\"execute-on-our-priorities\" class=\"level3\">\n<h3>1. Execute on Our Priorities<\/h3>\n<p>All of us want this to happen. It\u2019s not yet clear what all of our priorities will be in our jobs over the back half of 2019\u2014but if we can, we\u2019d like to see those efforts across the line.<\/p>\n<p>The TypeScript team has eased one of our heavy burdens, by investing in performance monitoring infrastructure over the course of this year and paying close attention to how their changes affect us as well as other TypeScript consumers. We\u2019re deeply appreciative! But there\u2019s still a lot of work to be done that just needs time to actually do the work\u2014reducing churn in type definitions, building type-checked templates, and improving our documentation.<\/p>\n<p>None of those are insurmountable by any stretch. But they\u2019d also be far likelier to happen if they were concretely identified as priorities for Ember as a whole, and we had commitment from the community to help!<\/p>\n<p>To briefly summarize <a href=\"https:\/\/v4.chriskrycho.com\/2019\/emberconf-2019-typed-ember-team-report.html\">those priorities<\/a> again:<\/p>\n<ul>\n<li><p>We need to make it so that consumers of our type definitions do not face breakage from updates to Ember\u2019s types <em>or<\/em> TypeScript definitions. We already worked out a basic strategy to solve this problem, and I\u2019ve done further exploration to validate that with key stakeholders of large apps (both TypeScript users and apps which <em>want<\/em> to use TypeScript) and core Ember contributors\u2026 but none of us have had time since EmberConf to write out the strategy as a Typed Ember <abbr title=\"Request for Comments\">RFC<\/abbr>, much less to do the actual implementation work.<\/p><\/li>\n<li><p>We need to make templates type-aware and type-safe. As fantastic as the experience of writing Glimmer components is\u2014and I genuinely do love it!\u2014it\u2019ll be an order of magnitude better when you get autocomplete from your editor as soon as you type <code>&lt;SomeComponent @<\/code>\u2026 and see the names of the valid arguments to a <code>SomeComponent<\/code> and the types of things you can pass to them. Everyone who has used TSX in a well-typed React app knows just how good this can be. We can make the experience equally great in Ember, while maintaining the authoring and performance advantages of separate templates. Again: we know how to do this (and the TypeScript team is also working on things which may make it even better for us). We just need the time allocated to take the work from prototype to ready-for-real-world-use.<\/p><\/li>\n<li><p>We need to dramatically expand the documentation we provide. Right now, ember-cli-typescript provides a minimal (and very useful!) set of docs. It\u2019s enough to get you <em>started<\/em>, and if you\u2019re already comfortable with TypeScript you\u2019ll do all right. However, we\u2019d love to provide helpful guides that show people not just the <em>mechanics<\/em> of using TypeScript with an Ember app, but best practices and techniques and the happy path. There\u2019s a world of difference between being able to run <code>ember install ember-cli-typescript<\/code> successfully and being able to author an app or addon in TypeScript successfully, and we need to bridge that gap for successful ecosystem-wide adoption!<\/p><\/li>\n<\/ul>\n<\/section>\n<section id=\"type-the-ecosystem\" class=\"level3\">\n<h3>2. Type the Ecosystem<\/h3>\n<p>We also need to do the work\u2014and this simply <em>cannot<\/em> be done solely by the handful of us that make up the core team\u2014to get types in place for the whole of the Ember ecosystem. Two years ago, I started drafting a blog post outlining a quest to type the ecosystem. I rewrote a good chunk of it last year. I even began working on a draft of the quest in our repository in 2018! But we haven\u2019t actually done it, and while a handful of important addons do now have types, (a) most still don\u2019t, and (b) many of those which <em>do<\/em> have type definitions could use further iteration to tighten them up to make them more reliable or more useful.<\/p>\n<p>I <em>hope<\/em> to actually open that quest sometime during the third quarter of this year. If things go as I hope, I will be doing some of that work myself, and I will be building documentation and training materials for others so <em>they<\/em> can see how to do it, and I will be available for code reviews on conversion efforts. I cannot guarantee that by any stretch\u2014but it is my fervent hope, and there is very good reason to think it may actually come to pass!<\/p>\n<p>In many ways, this also hinges on our ability to provide a good story for reducing churn in type definitions. Just as it\u2019s important that we make Ember\u2019s <em>own<\/em> types stable for consumers, it\u2019s also important that we help addon developers provide the same kinds of guarantees for <em>their<\/em> consumers. The entire Ember community takes SemVer seriously, and that means the tools have to support that.<\/p>\n<\/section>\n<section id=\"define-embers-typescript-story\" class=\"level3\">\n<h3>3. Define Ember\u2019s TypeScript Story<\/h3>\n<p>If we manage to execute on all the priorities outlined above, then there\u2019s one last step for making TypeScript an official part of Ember\u2019s story: an <abbr title=\"Request for Comments\">RFC<\/abbr> defining <em>exactly<\/em> how Ember can officially support TypeScript\u2014including two major commitments:<\/p>\n<ul>\n<li>shipping its own type definitions, with a well-considered approach to SemVer and TypeScript<\/li>\n<li>considering TypeScript a <em>peer<\/em> to JavaScript in <abbr title=\"Application Programming Interface\">API<\/abbr> design decisions<\/li>\n<\/ul>\n<p>I have an basic frame in mind for how we tackle both of those. The first is by far the more important of the two; the latter is already happening in an <i>ad hoc<\/i> way and merely requires the former before it can be formalized. But getting to the point where Ember can ship its own type definitions while upholding its semantic versioning commitments <em>and<\/em> taking advantage of the advances always happening with TypeScript itself is a large and non-trivial task.<\/p>\n<p>It means a substantial amount of work within the Ember codebase. It means building new tooling for Ember\u2019s core development process\u2014so that the experience of working on Ember itself can remain ever-more productive even as we make sure that the types published for consumers are reliable, accurate, and stable. It means investing in both further education of the community and more static analysis tooling, to make sure that breaking <em>type<\/em>-level changes are not introduced accidentally.<\/p>\n<p>These efforts are worth the investment they will require, but they <em>are<\/em> serious efforts.<\/p>\n<\/section>\n<\/section>\n<section id=\"why-it-matters\" class=\"level2\">\n<h2>Why It Matters<\/h2>\n<p>This is not just me speaking as TypeScript fanboy and promoter. These things matter for TypeScript consumers of Ember\u2014and they do, profoundly. But I would not suggest even that <abbr title=\"Request for Comments\">RFC<\/abbr> for official support merely to that end. The TypeScript user community in Ember has done extremely well to date <em>without<\/em> that kind of official commitment, and could continue to do so (as do many other communities in the broader JavaScript ecosystem).<\/p>\n<p>Why, then, do I suggest we make this not just a commitment for our little informal team but for the Ember community as a whole? Because while TypeScript users will benefit the <em>most<\/em> from these improvements, JavaScript developers will <em>also<\/em> benefit from them.<\/p>\n<p>When both Ember core and every major addon in the Ember ecosystem has top-notch types available, <em>every<\/em> other app and addon author will be able to take advantage of those types, courtesy of the integration offered by TypeScript in every major editor. Whether they\u2019re using Vim or Visual Studio, Ember developers will be able to get rich documentation, suggestions, and inline errors\u2014even for their templates! This can be a massive win for developer productivity throughout the ecosystem. Investing to make TypeScript a first-class citizen fo the Ember ecosystem will make the experience of authoring Ember apps and libraries better for <em>everyone<\/em>. So let\u2019s do it!<\/p>\n<\/section>\n","pubDate":"Mon, 17 Jun 2019 21:20:00 -0400","guid":"tag:v4.chriskrycho.com,2019-06-17:\/2019\/emberjs2019-part-2.html","category":["emberjs","emberjs2019","TypeScript","JavaScript","open-source software"]},{"title":"#EmberJS2019, Part 1","link":"http:\/\/v4.chriskrycho.com\/2019\/emberjs2019-part-1.html","description":"<p>Over the last year, the Ember community has steadily delivered on the vision we all traced out in last year\u2019s #EmberJS2018 and Roadmap <abbr title=\"Request for Comments\">RFC<\/abbr> process, culminating with the shipping-very-soon-now <a href=\"https:\/\/emberjs.com\/editions\/octane\/\">Ember Octane Edition<\/a>. (All the pieces are pretty much done and are either on stable or will be shortly; we just need another <abbr title=\"long term support\">LTS<\/abbr> release before we cut a full new edition!)<\/p>\n<p>So\u2026 what should we tackle next? This year, I have only two parts, unlike <a href=\"https:\/\/v4.chriskrycho.com\/emberjs2018\">last year\u2019s four<\/a> (and I\u2019m sneaking them in just under the wire, as today is the deadline for entries!):<\/p>\n<ul>\n<li><b>Part 1 (this post):<\/b> <a href=\"https:\/\/v4.chriskrycho.com\/2019\/emberjs2019-part-1\">Let\u2019s finish modernizing the Ember programming model!<\/a><\/li>\n<li><b>Part 2:<\/b> <a href=\"https:\/\/v4.chriskrycho.com\/2019\/emberjs2019-part-2\">Let\u2019s make TypeScript a first-class citizen of the Ember ecosystem.<\/a><\/li>\n<\/ul>\n<hr \/>\n<p>The Octane Edition represents the <em>delivery<\/em> of several years worth of work and experimentation. It represents a willingness to say \u201cno\u201d to many good efforts and things Ember needs to continue succeeding. All of that is <em>very<\/em> much to the good! It\u2019s precisely what I and many others called for last year.<\/p>\n<p>This year, it\u2019s time to deliver on a number of other long-standing goals of the Ember effort. That means:<\/p>\n<ul>\n<li>a modernized <em>build-system<\/em>, and with it the long-promised \u201csvelte\u201d builds, tree-shaking, and the ability to npm-install-your-way-to-Ember<\/li>\n<li>a modernized <em>routing system<\/em>, leaving behind the final bits of cruft from the Ember 1.x era and fully-embracing the component-service architecture suggested last year<\/li>\n<\/ul>\n<section id=\"modernized-build-system\" class=\"level2\">\n<h2>Modernized Build System<\/h2>\n<p>Others have covered the build system in some detail, and I largely agree with their assessments. We <em>do<\/em> need to focus on landing that and continuing to modernize our build pipeline, and the Embroider effort and everything it unlocks should absolutely be a core part of the roadmap. One of the biggest ones, for many potential adopters of Ember <em>and<\/em> many existing Ember users who have large codebases they\u2019d like to migrate <em>into<\/em> Ember is that long-awaited npm-install-your-way-to-Ember story. Let\u2019s make that happen! I\u2019m confident that as long as we make that commitment, we\u2019ll get it done.<\/p>\n<p>Given that confidence, I\u2019m going to focus for the rest of this post on the <em>directional<\/em> question with our routing system\u2014both why we need a change and what I think the change should look like.<\/p>\n<\/section>\n<section id=\"modernized-routing-system\" class=\"level2\">\n<h2>Modernized Routing System<\/h2>\n<p>The Ember Router was years ahead of its time, and it remains very solid and reliable; it\u2019s a workhorse. Unfortunately, the routing system <em>as a system<\/em> is showing its age, and has entered something of a period of instability of just the sort Editions are meant to address. Today, routing concerns are spread across four different parts of the application: the <i>route map<\/i>, <i>route classes<\/i>, <i>controller classes<\/i>, and <i>the router service<\/i>. Over the next year, we should iteratively design and implement our way toward a future without controllers\u2026 and possibly some other simplifications, if we can manage them. We can make working with Ember simultaneously <em>easier for newcomers<\/em> and <em>better for old hands<\/em>.<\/p>\n<p>\u201cControllers are dead!\u201d is one of the great bogeymen of Ember lore at this point; but I hope quite sincerely that a year from now it\u2019s basically true. Controllers are the single part of Ember today that shows <em>very<\/em> clearly the application\u2019s SproutCore roots. When I started learning AppKit and UIKit early this year, I was struck by all the things that sounded like Ember 1.x\u2014or rather, vice versa! And just as Apple itself is now <a href=\"https:\/\/developer.apple.com\/xcode\/swiftui\/\">moving aggressively toward a programming model without controllers<\/a>, so should we!<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p>\n<p>It\u2019s not that controllers are <em>bad<\/em>, exactly. It\u2019s that they don\u2019t <em>fit<\/em> with the rest of the framework at this point. They\u2019re long-lived singletons (like services) but serve as backing classes for templates (like components). They are eagerly instantiated as soon as a <code>LinkTo<\/code> component with references them is instantiated, but not <em>set up<\/em> until the app transitions to the route associated with them. They\u2019re required if you want to use query parameters, and query parameters don\u2019t work with Ember\u2019s \u201cdata down, actions up\u201d paradigm\u2026 pretty much at all.<\/p>\n<p>Controllers need to go, but they need a well-designed set of replacements\u2014in particular, we need a good design for query parameter handling and for what template should be associated with a given route.<\/p>\n<p>Query param handling is, I admit, mostly outside my wheelhouse. All of the situations where I\u2019ve used it would be trivially solved by putting them on the router service, tracking changes on them with the <code>@tracked<\/code> decorator, and updating them with actions. However, I\u2019m reliably informed that some of the more gnarly scenarios out there require a bit more than this, and I defer to the folks who know what they\u2019re talking about there!<\/p>\n<p>React and Vue simply solve the template problem by mounting <em>components<\/em> at given route locations. Ember should probably follow <em>roughly<\/em> the same path, while baking in good defaults along the way. Don\u2019t call them \u201croutable components\u201d though! It\u2019s not just that it\u2019s too much baggage; it\u2019s that a good design in this space should not require the components themselves to be anything special at all. Instead, whether it\u2019s part of the route map or the router class grows a small bit of new, purely declarative <abbr>API<\/abbr>\u2014e.g.\u00a0static class properties specifying the relevant components for the loading, resolved, and error states of the route\u2019s model\u2014the route itself should be able to specify exactly what component to render.<\/p>\n<p>If we put in the work to get a design that satisfies all these constraints, we can come out with a <em>much<\/em> simpler routing system\u2014and Ember\u2019s entirely programming model will be <em>much<\/em> more coherent as a result.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> We\u2019ll simply have components, services, and routes\u2014and routes will simply be a mapping from URL to a particular set of data and a corresponding component to render it into. That in turn will take us most of the rest of the way toward the programming model Chris Garrett proposed a year ago: <a href=\"https:\/\/medium.com\/@pzuraq\/emberjs-2018-ember-as-a-component-service-framework-2e49492734f1\">Ember as a Component-Service Architecture<\/a>. This is the fitting conclusion to what we started in Octane: bringing the <em>whole<\/em> Ember programming model into coherence.<\/p>\n<\/section>\n<section id=\"bonus\" class=\"level2\">\n<h2>Bonus<\/h2>\n<p>I\u2019d also like to strongly commend my friend Dustin Masters\u2019 post, <a href=\"https:\/\/dev.to\/dustinsoftware\/the-case-for-embeddable-ember-4120\">The Case for Embeddable Ember<\/a>. Call this a stretch goal: if we ship all the build pipeline elements represented above, the extra work required to get to that point is <em>relatively<\/em> small\u2014and extremely valuable for many teams who want to replace legacy applications written wholly with Backbone, jQuery etc., or who just want to see if Ember might have value to add without doing a full rewrite of their existing React\/Vue\/Angular\/Aurelia apps.<\/p>\n<p>Oh\u2026 and it turns out that the design constraints I suggested for a routing system that works well with components would lead fairly nicely and easily to Dustin\u2019s proposal, and make for a straightforward path to fully adopt Ember and map its component tree to the router when you\u2019re ready. Just saying.<\/p>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>You can expect to hear a <em>lot<\/em> more from me about Swift <abbr title=\"user interface\">UI<\/abbr> in this space, both in a general sense <em>and<\/em> as it relates to Ember. There are some fascinating points of contact between the two programming models!<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>There may also be opportunities for further simplification past this, along with more substantial rethinks of our router as we have it. But those are not <em>necessary<\/em> for the next year, and making these changes will unlock further experimentation in that direction while making Ember more usable in the meantime.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Mon, 17 Jun 2019 20:25:00 -0400","guid":"tag:v4.chriskrycho.com,2019-06-17:\/2019\/emberjs2019-part-1.html","category":["emberjs","emberjs2019","JavaScript","open-source software"]},{"title":"JavaScript is C","link":"http:\/\/v4.chriskrycho.com\/2018\/javascript-is-c.html","description":"<p><i><b><a href=\"https:\/\/v4.chriskrycho.com\/2018\/assumed-audiences.html\">Assumed Audience:<\/a><\/b> software developers, especially those interested in modern, typed programming languages.<\/i><\/p>\n<p>Earlier this week, I was working on a problem in the Ember app where I spend most of my day job, and realized: <i>JavaScript is the same as C.<\/i><\/p>\n<p>That probably doesn\u2019t make any sense, so let\u2019s back up. The scenario I was dealing with was one where there was a bit of invariant around a piece of data that I <em>had<\/em> to maintain for the application not to blow up in horrible ways, but had no good way to enforce with the language\u2019s tools. <em>This<\/em> action on <em>that<\/em> piece of data was only valid if <em>this<\/em> condition held true\u2026 but even with the fully-type-checked TypeScript application we now have, the action (because of the entire application\u2019s architecture and indeed the entire way that Ember apps are wired together!) could not be statically verified to be safe.<\/p>\n<p>As I considered the best way to handle this\u2014I ended up having the function involved in the action just throw an error if the invariant wasn\u2019t properly maintained\u2014I was reminded of the years I spent writing C. In C, it\u2019s quite <em>possible<\/em> to write safe code around memory management. I managed it fine in the applications I worked on, by carefully documenting the invariants a given function required to be safe. <em>This<\/em> piece of data is allocated by <em>that<\/em> function and then released to <em>the caller<\/em> to manage. Even with every bit of static analysis I threw at those kinds of things, it was possible to get it wrong.<\/p>\n<p>The exact same kinds of problems I had in C, I have in JavaScript or even TypeScript today. Experientially, JavaScript<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> <em>is<\/em> C, as far as having to deal with these kinds of invariants goes.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a><\/p>\n<p>Enter <a href=\"https:\/\/www.rust-lang.org\">Rust<\/a>: the kinds of management of memory that I was always having to keep track of in my head (or, better, with detailed documentation comments along the way\u2014but with the same problem that it was easy to get wrong), I could now have statically guaranteed by a compiler. Given that I spent the first six years of my career managing and carefully tracking all of that by hand, it\u2019s no wonder I <a href=\"https:\/\/newrustacean.com\">fell in love<\/a> with Rust. I could have the <em>compiler<\/em> guarantee the invariants I needed around memory management.<\/p>\n<p>And it turns out, this same dynamic exists in the world of front-end web development. People sometimes wonder why (and colleagues are often bemused that) I get so excited by <a href=\"https:\/\/elm-lang.org\">Elm<\/a>. But the step from JavaScript (or even TypeScript) to Elm is just like the step from C to Rust. It\u2019s a real and profound shift in what kinds of things you can <em>know for certain<\/em> about your program.<\/p>\n<p>In a C application, try as hard as I may, at the end of the day I am always on my own, making sure the invariants I need for memory safety hold. In Rust, I can be 100% confident that I will not have memory-unsafe code. Not 98%-and-I\u2019d-better-check-those-last-2%-really-closely. One hundred percent. That\u2019s a game-changer.<\/p>\n<p>In a JavaScript or TypeScript application, try as hard as I may, at the end of the day I am always on my own, making sure the invariants I need for state management hold. In Elm, I can be 100% confident that I will not have code which needs a given invariant about a piece of state to hold break the way it could in this TypeScript application. Because I can\u2019t even apply the relevant transformations in question if it isn\u2019t! That\u2019s a game-changer.<\/p>\n<p>Neither of those is a guarantee I won\u2019t have bugs. (A compiler that could guarantee that would have to be sentient and far smarter than any human!) Neither of them means I can\u2019t intentionally do stupid things that violate invariants in ways that get the program into broken states from the user\u2019s point of view. But both of them give me the tools and the confidence that I can absolutely guarantee that certain, very important kinds of invariants hold. We\u2019re not looking for an absence of all bugs or a system which can prevent us from making any kind of mistake. We\u2019re looking to be able to spend our times on the things that matter, <em>not<\/em> on minutiae the computer can check for us.<\/p>\n<p>So: I\u2019m not going back to C, and I\u2019m ready to move past JavaScript and TypeScript.<\/p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>This goes for plenty of languages that aren\u2019t JavaScript, too. It\u2019s equally true of c<sup>\u266f<\/sup> or Python.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>Obviously there are some kinds of things you don\u2019t have to worry about in JS that you do in C: memory management, for one. The point is that the manual-verification-of-every-invariant-you-care-about is the same.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Thu, 20 Dec 2018 18:45:00 -0500","guid":"tag:v4.chriskrycho.com,2018-12-20:\/2018\/javascript-is-c.html","category":["JavaScript","TypeScript","Elm","Rust","C","software development"]},{"title":"Internal and External Parameter Names in JavaScript and TypeScript","link":"http:\/\/v4.chriskrycho.com\/2018\/internal-and-external-parameter-names-in-javascript-and-typescript.html","description":"<p>Earlier this month I was working on a fairly thorny problem for work\u2014taking a total value and splitting it into numbers which summed up to it, possibly including with a rule about what the split-up values had to be a multiple of. E.g. you want to order 50 Buffalo wings, and you have to choose the flavors for the wings in increments of 5.<\/p>\n<p>I spent a lot of time thinking about the implementation of the algorithm for that, but I also spent a lot of time thinking about what its <abbr>API<\/abbr> should look like. Here, it\u2019s the latter I want to dive into (the former is a little tricky but not all that interesting).<\/p>\n<p>I started out with just simple parameters to the function:<\/p>\n<pre class=\"ts\"><code>function splitNicely(\n  total: number, components: number, factor?: number\n): number {\n  \/\/ the implementation\n}<\/code><\/pre>\n<p>This is nice enough to use internally. But calling it is pretty confusing:<\/p>\n<pre class=\"ts\"><code>const result = splitNicely(50, 5, 2);<\/code><\/pre>\n<p>Which number is what value here? Who knows!<\/p>\n<p>So then I just exposed <em>all<\/em> of the items as an options hash:<\/p>\n<pre class=\"ts\"><code>interface SplitArgs {\n  total: number;\n  components: number;\n  factor?: number;\n}\n\nfunction splitNicely(\n  { total, components, factor }: SplitArgs\n): number {\n  \/\/ the implementation\n}<\/code><\/pre>\n<p>This was a lot nicer to call:<\/p>\n<pre class=\"ts\"><code>splitNicely({ total: 50, components: 5, factor: 2 });<\/code><\/pre>\n<p>However, it was a bit verbose, and I realized that it\u2019s fairly obvious that the first argument should be the value we\u2019re splitting up, so I simplified a bit:<\/p>\n<pre class=\"ts\"><code>interface SplitArgs {\n  components: number;\n  factor?: number;\n}\n\nfunction splitNicely(\n  total: number,\n  { components, factor }: SplitArgs\n): number {\n  \/\/ the implementation\n}\n<\/code><\/pre>\n<p>Now calling it read <em>relatively<\/em> well:<\/p>\n<pre class=\"ts\"><code>splitNicely(10, { components: 5, factor: 2 });<\/code><\/pre>\n<p>However, the names were not my favorite for invoking the function. Really, what I wanted was for the function invocation to describe what I was doing, when reading it from the outside\u2014while having these useful names for operating on the implementation internally.<\/p>\n<p>At this point, I remembered two things:<\/p>\n<ol type=\"1\">\n<li>Swift and Objective-C have the nice notion of internal and external parameter names.<\/li>\n<li>JavaScript (and thus TypeScript) let you rename values in \u201cdestructuring assignment.\u201d<\/li>\n<\/ol>\n<p>The second one lets us get the same basic effect in JavaScript or TypeScript as we get in Swift, if we\u2019re using an options argument! Here\u2019s how destructuring works in the function definition. Let\u2019s see it first with just JavaScript. The object passed as a parameter has a key named <code>of<\/code>, which has a string value\u2014but <code>of<\/code> is a bad name inside the function; there, we can just call it <code>str<\/code> and it\u2019s perfectly clear.<\/p>\n<pre class=\"js\"><code>function length({ of: str }) {\n  return str.length;\n}\n\nconsole.log(length({ of: &quot;waffles&quot; }));  \/\/ 7<\/code><\/pre>\n<p>That\u2019s the equivalent of a function that looks like this:<\/p>\n<pre class=\"js\"><code>function length({ of }) {\n  const str = of;\n  return str.length\n}<\/code><\/pre>\n<p>Here\u2019s the same code but in TypeScript:<\/p>\n<pre class=\"ts\"><code>function length({ of: str }: { of: string }): number {\n  return str.length;\n}\n\nconsole.log(length({ of: &quot;waffles&quot; }));  \/\/ 7<\/code><\/pre>\n<p>This is a big more annoying to write out in TypeScript, because we need to supply the type of the whole object after the object we\u2019ve destructured, but the effect is the same once we get past the declaration. It\u2019s also pretty silly to do this kind of thing at all in this example\u2014but it becomes much more useful in more complicated functions, like the one that motivated me to explore this in the first place.<\/p>\n<p>Recall that I <em>liked<\/em> having <code>components<\/code> and <code>factor<\/code> as the internal names. They weren\u2019t great for <em>calling<\/em> the function, though. After some consideration, I decided invoking the function should look like this:<\/p>\n<pre class=\"ts\"><code>splitNicely(10, { into: 5, byMultiplesOf: 2 });<\/code><\/pre>\n<p>By using the destructuring technique, we can get exactly this, while keeping <code>components<\/code> and <code>factor<\/code> internally:<\/p>\n<pre class=\"ts\"><code>interface SplitArgs = {\n  into: number;\n  byMultiplesOf?: number;\n}\n\nfunction splitNicely(\n  total: number,\n  { into: components, byMultiplesOf: factor }: SplitArgs\n): number {\n  \/\/ the implementation\n}<\/code><\/pre>\n<p>This is a great pattern to put in your toolbox. You can of course overdo it with this, as with any technique, but it\u2019s a nice tool for these kinds of cases where you really want to make an expressive <abbr>API<\/abbr> for both callers and the internal implementation of a function.<\/p>\n","pubDate":"Mon, 26 Nov 2018 20:25:00 -0500","guid":"tag:v4.chriskrycho.com,2018-11-26:\/2018\/internal-and-external-parameter-names-in-javascript-and-typescript.html","category":["javascript","typescript","swift","software development"]},{"title":"Why We Want Pattern-Matching in JavaScript","link":"http:\/\/v4.chriskrycho.com\/2018\/why-we-want-pattern-matching-in-javascript.html","description":"<p>I\u2019ve often noted how much I want the <a href=\"https:\/\/github.com\/tc39\/proposal-pattern-matching\">JavaScript pattern-matching proposal<\/a> to land. I noted in conversation with some people recently, though, that it\u2019s not always obvious <em>why<\/em> it will be so helpful. Similarly, <a href=\"https:\/\/twitter.com\/littlecalculist\">Dave Herman<\/a> recently noted to me that <a href=\"https:\/\/twitter.com\/dhh\">DHH<\/a>\u2019s mantra of \u201cShow me the code\u201d is a really helpful tool for thinking about language design. (I tend to agree!) So with that in mind, here\u2019s a piece of example code from the Ember app I work on today, very slightly modified to get at the pure essentials of this particular example.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p>\n<p>The context is a <abbr>UI<\/abbr> component which shows the user their current discount, if any, and provides some nice interactivity if they try to switch to a different discount.<\/p>\n<p>First, some types that we\u2019ll use in the example, which I use in the actual component to avoid the problems that inevitably come with using string values for these kinds of things. Linters like ESLint or type systems like TypeScript or Flow will catch typos this way, and you\u2019ll also get better errors at runtime even if you\u2019re not using a linter or a type system!<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a><\/p>\n<pre class=\"js\"><code>const DiscountTypes = {\n  Offer: &#39;Offer&#39;,\n  Coupon: &#39;Coupon&#39;,\n  None: &#39;None&#39;,\n};\n\nconst Change = {\n  OfferToOffer: &#39;OfferToOffer&#39;,\n  OfferToCoupon: &#39;OfferToCoupon&#39;,\n  CouponToCoupon: &#39;CouponToCoupon&#39;,\n  CouponToOffer: &#39;CouponToOffer&#39;,\n};<\/code><\/pre>\n<p>Now, we set up a component which has a little bit of internal state to track the desired change before we submit it, which we display differently based on what the value of the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Functions\/get\"><abbr>ES5<\/abbr> getter<\/a> for <code>change<\/code> is here:<\/p>\n<pre class=\"js\"><code>class DiscountComponent {\n  constructor(currentDiscountType) {\n    this.currentDiscountType = currentDiscountType;\n    this.newDiscountType = null;\n  }\n\n  changeDiscount(newDiscountType) {\n    this.newDiscountType = newDiscountType;\n  }\n\n  submitChange() {\n    \/\/ logic for talking to the server\n  }\n\n  get change() {\n    const { currentDiscountType, newDiscountType } = this;\n\n    if (currentDiscountType === DiscountTypes.Offer) {\n      if (newDiscountType === DiscountTypes.Offer) {\n        return Change.OfferToOffer;\n      } else if (newDiscountType === DiscountTypes.Coupon) {\n        return Change.OfferToCoupon;\n      } else if (newDiscountType === DiscountTypes.None) {\n        return null;\n      } else {\n        assertInDev(\n          `Missed a condition: ${currentDiscountType}, ${newDiscountType}`\n        );\n      }\n    } else if (currentDiscountType === DiscountTypes.Coupon) {\n      if (newDiscountType === DiscountTypes.Offer) {\n        return Change.CouponToOffer;\n      } else if (newDiscountType === DiscountTypes.Coupon) {\n        return Change.CouponToCoupon;\n      } else if (newDiscountType === DiscountTypes.None) {\n        return null;\n      } else {\n        assertInDev(\n          `Missed a condition: ${currentDiscountType}, ${newDiscountType}`\n        );\n      }\n    } else if (currentDiscountType === DiscountTypes.None) {\n      return null;\n    } else {\n      assertInDev(\n        `Missed a condition: ${currentDiscountType}, ${newDiscountType}`\n      );\n    }\n  }\n}<\/code><\/pre>\n<p>Here\u2019s the <em>exact<\/em> same semantics for computing the <code>change<\/code> value we\u2019re interested, but with pattern matching:<\/p>\n<pre class=\"js\"><code>class DiscountComponent {\n  \/\/ ...snip\n\n  get change() {\n    case ([this.currentDiscountType, this.newDiscountType]) {\n      when [DiscountTypes.Offer, DiscountTypes.Offer] -&gt;\n        return Change.OfferToOffer;\n      when [DiscountTypes.Offer, DiscountTypes.Coupon] -&gt;\n        return Change.OfferToCoupon;\n      when [DiscountTypes.Coupon, DiscountTypes.Offer] -&gt;\n        return Change.CouponToOffer;\n      when [DiscountTypes.Coupon, DiscountTypes.Coupon] -&gt;\n        return Change.CouponToCoupon;\n      when [DiscountTypes.None, ...] || [..., DiscountTypes.None] -&gt;\n        return null;\n      when [...] -&gt;\n        assertInDev(\n          `Missed a condition: ${currentDiscountType}, ${newDiscountType}`\n        );\n    }\n  }\n}<\/code><\/pre>\n<p>The difference is stark. It\u2019s not just that there are fewer lines of code, it\u2019s that the actual intent of the code is dramatically clearer. (And while I\u2019ve formatted it for nice display here, those are all one-liners in my normal 100-characters-per-line formatting.)<\/p>\n<p>My preference would be for pattern-matching to have expression semantics, so you wouldn\u2019t need all the <code>return<\/code> statements in the mix\u2014and it\u2019s <em>possible<\/em>, depending on how a number of proposals in flight right now shake out, that it still will. Even if pattern matching doesn\u2019t ultimately end up with an expression-based syntax, though, we can still get a lot of those niceties if the <code>do<\/code>-expression proposal lands:<\/p>\n<pre class=\"js\"><code>class DiscountComponent {\n  \/\/ ...snip\n\n  get change() {\n    return do {\n      case ([this.currentDiscountType, this.newDiscountType]) {\n        when [DiscountTypes.Offer, DiscountTypes.Offer] -&gt;\n          Change.OfferToOffer;\n        when [DiscountTypes.Offer, DiscountTypes.Coupon] -&gt;\n          Change.OfferToCoupon;\n        when [DiscountTypes.Coupon, DiscountTypes.Offer] -&gt;\n          Change.CouponToOffer;\n        when [DiscountTypes.Coupon, DiscountTypes.Coupon] -&gt;\n          Change.CouponToCoupon;\n        when [DiscountTypes.None, ...] || [..., DiscountTypes.None] -&gt;\n          null;\n        when [...] -&gt;\n          assertInDev(\n            `Missed a condition: ${currentDiscountType}, ${newDiscountType}`\n          );\n      }\n    }\n  }\n}<\/code><\/pre>\n<p>Again, this is profoundly clearer about the intent of the code, and it\u2019s far easier to be sure you haven\u2019t missed a case.<a href=\"#fn3\" class=\"footnote-ref\" id=\"fnref3\" role=\"doc-noteref\"><sup>3<\/sup><\/a><\/p>\n<p><strong>Edit:<\/strong> after some comments on Twitter, I thought I\u2019d note how this is <em>even nicer<\/em> in pure functions. If we assume that it gets expression semantics (which, again, I\u2019m hoping for), a pure functional version of the sample above would look like this:<\/p>\n<pre class=\"js\"><code>const change = (currentType, newType) =&gt;\n  case ([currentType, newType]) {\n    when [DiscountTypes.Offer, DiscountTypes.Offer] -&gt;\n      Change.OfferToOffer;\n    when [DiscountTypes.Offer, DiscountTypes.Coupon] -&gt;\n      Change.OfferToCoupon;\n    when [DiscountTypes.Coupon, DiscountTypes.Offer] -&gt;\n      Change.CouponToOffer;\n    when [DiscountTypes.Coupon, DiscountTypes.Coupon] -&gt;\n      Change.CouponToCoupon;\n    when [DiscountTypes.None, ...] || [..., DiscountTypes.None] -&gt;\n      null;\n    when [...] -&gt;\n      assertInDev(\n        `Missed a condition: ${currentDiscountType}, ${newDiscountType}`\n      );\n  };<\/code><\/pre>\n<p>This may not be <em>quite<\/em> as clear as the same thing in F<sup>\u266f<\/sup> or Elm or another language in that family\u2026 but it\u2019s amazingly better than anything we\u2019ve seen in JavaScript to date.<\/p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p><code>assertInDev<\/code> looks a little different; we\u2019re actually using the <code>Maybe<\/code> type from my <a href=\"https:\/\/github.com\/chriskrycho\/true-myth\">True Myth<\/a> library instead of returning <code>null<\/code>; it\u2019s an Ember app; as such it uses a <code>@computed<\/code> decorator; and of course it\u2019s all in TypeScript. I chose to write it with standard JavaScript to minimize the number of things you have to parse as a reader.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>In the actual TypeScript, these are defined with an <a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/enums.html\"><code>enum<\/code><\/a>.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn3\" role=\"doc-endnote\"><p>Fun fact: the original code actually <em>had<\/em> missed a number of cases, which I learned only because TypeScript\u2019s <code>strictNullChecks<\/code> setting informed me.<a href=\"#fnref3\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Sun, 23 Sep 2018 13:00:00 -0400","guid":"tag:v4.chriskrycho.com,2018-09-23:\/2018\/why-we-want-pattern-matching-in-javascript.html","category":["javascript","programming languages"]},{"title":"A Real Victory","link":"http:\/\/v4.chriskrycho.com\/2018\/a-real-victory.html","description":"<p>On September 29, 2016, I started working on adding (<a href=\"https:\/\/flow.org\">Flow<\/a>) types to the <a href=\"https:\/\/emberjs.com\">Ember<\/a> app I had been working on since the start of the year. Throughout the rest of the year I worked on adding some basic Flow types to our app and for Ember. For my last commit in 2016, I switched us to TypeScript and began the rest of the long journey to fully type-checking our app. In early 2018, we made it to \u201cthe app type-checks\u201d\u2026 in the loosest strictness settings.<\/p>\n<p>And as of 6pm today\u2014September 5, 2018, almost two full years later, and 21 months after we switched from Flow to TypeScript (more on this below)\u2014we have a fully type-checked TypeScript Ember application, with the strictness notches dialed as strict as they will go.<\/p>\n<p>It took almost two full years for us to get there, and I\u2019m incredibly proud of that work.<\/p>\n<p>It took almost two full years because it was a lot of work, and slow work to do at that, and it was rare that I could block out any large chunks of time for that work\u2014we had to sneak in improvements between features we were working urgently on for our clients and our own internally goals. More, it wasn\u2019t just the work of adding types to our application. It was also the work of writing types for Ember itself, and for the surrounding ecosystem\u2014which thankfully I did not finish alone, but which I did have to start alone. It was the work of integrating (and reintegrating) TypeScript into Ember\u2019s build pipeline.<\/p>\n<p>Happily, I did <em>not<\/em> do most of that work alone, and even on our app I\u2019ve had a ton of help getting the types in place. But it has been a massive task, and finishing it today was a real victory. It\u2019s not perfect. We have 200-or-so instances of <code>any<\/code> in the application (most of them in semi-legitimate places, to be fair), and I wish it were more like 20. We have a number of places in the app with the <code>!<\/code> \u201cI promise this isn\u2019t <code>null<\/code> or <code>undefined<\/code> here\u201d operator on some nullable field, with long comments explaining <em>why<\/em> it\u2019s not possible for it to be null there.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p>\n<p>But it type-checks today, and type errors fail the builds, and that <em>is<\/em> a real victory.<\/p>\n<hr \/>\n<p>You can consider this \u201cpart 1\u201d of my thoughts on what feels to me like a pretty significant achievement. I\u2019ll hopefully follow this up with some backstory sometime in the next few weeks.<\/p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>See my <a href=\"https:\/\/v4.chriskrycho.com\/2018\/type-informed-design.html\">recent post<\/a> on thinking a lot about design decisions I would have made differently with TypeScript\u2019s strict null checking available from day one!<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Wed, 05 Sep 2018 21:45:00 -0400","guid":"tag:v4.chriskrycho.com,2018-09-05:\/2018\/a-real-victory.html","category":["TypeScript","JavaScript","Flow","Ember.js","software development"]},{"title":"Type-Informed Design","link":"http:\/\/v4.chriskrycho.com\/2018\/type-informed-design.html","description":"<p>I\u2019ve been working on getting the Ember app I work on fully type-checked in strict mode this week, and noticed something interesting along the way: there are a lot of design decisions\u2014a few of them really core to the behavior of the app!\u2014which we never, <em>ever<\/em> would have made if we had been using Typescript in the first place.<\/p>\n<p>One of these is pervasive references to certain optional properties that appear in services throughout our app\u2014the basket, for example. These can indeed be inset and at certain times they are. However, many of our components pull in this property from the service and simply assume it\u2019s there to use. We\u2019ve known for a while that this was a problem at times: <a href=\"https:\/\/raygun.com\/\">Raygun<\/a> has told us loud and clear. But it wasn\u2019t obvious how pervasive this was\u2014and how badly we were just assuming the presence of something that may well be absent <em>all over the app<\/em>!\u2014until I saw the type errors from it. Dozens of them.<\/p>\n<p>Some of them are places where we should have built the components differently: to take the item as an argument, for example, and to require it as an input, because the component just doesn\u2019t make any sense without it, indeed lives in a part of the app such that it\u2019s not even possible to render the component without it.<\/p>\n<p>And sure, we could document that invariant and use TypeScript\u2019s override tools to carry on. (What do you think I\u2019m doing this week?)<\/p>\n<p>But, and this is the thing that really caught my attention in thinking about all of this: it would be much better <em>not<\/em> to have to do that. Had we had TypeScript in place when we started, we simply would have designed large swaths of the app differently because we\u2019d have seen these kinds of things when we were building it in the first place!<\/p>\n<p>That\u2019s a bit of wishing for the impossible in one sense: we literally couldn\u2019t have done that when we started on the app, because TS didn\u2019t have the necessary pieces to support typing the Ember libraries. My team helped <em>build<\/em> the TS and Ember story over the last 18 months! But at a minimum I have a pretty good idea how the process will be different next time around, with this tool available and providing this kind of helpful design feedback from the outset!<\/p>\n","pubDate":"Thu, 30 Aug 2018 19:40:00 -0400","guid":"tag:v4.chriskrycho.com,2018-08-30:\/2018\/type-informed-design.html","category":["TypeScript","JavaScript","functional programming","types","software development","Ember.js"]},{"title":"Level up your `.filter` game","link":"http:\/\/v4.chriskrycho.com\/2018\/level-up-your-filter-game.html","description":"<p>Adam Giese\u2019s <a href=\"https:\/\/css-tricks.com\/level-up-your-filter-game\/\">\u201cLevel up your <code>.filter<\/code> game\u201d<\/a> does something really interesting and helpful: it introduces a bunch of fairly sophisticated functional programming concepts without ever mentioning functional programming and without ever using any of the jargon associated with those terms.<\/p>\n<p>\u201cLevel up your <code>.filter<\/code> game\u201d gives you a reason to use some standard FP tools\u2014currying, higher-order functions, composition\u2014in your ordinary work. It\u2019s pitched at working JS developers. It gives a real-world example of wanting to filter search results based on user input. It shows the utility of defining a bunch of small functions which can fit together like LEGO.<\/p>\n<blockquote>\n<p>Filters are an essential part of JavaScript development. Whether you\u2019re sorting out bad data from an API response or responding to user interactions, there are countless times when you would want a subset of an array\u2019s values. I hope this overview helped with ways that you can manipulate predicates to write more readable and maintainable code.<\/p>\n<\/blockquote>\n<p>I commend the piece to you not so much for the explanation of how to use JavaScript\u2019s <code>Array.prototype.filter<\/code> effectively (though it has some good suggestions that way!) but <em>primarily<\/em> as a great example of the kind of pedagogy we need a lot more of to demonstrate the value of functional programming in ordinary, day-to-day development work.<\/p>\n","pubDate":"Sat, 18 Aug 2018 10:00:00 -0400","guid":"tag:v4.chriskrycho.com,2018-08-18:\/2018\/level-up-your-filter-game.html","category":["links","pedagogy","javascript","functional programming"]},{"title":"Stable Libraries","link":"http:\/\/v4.chriskrycho.com\/2018\/stable-libraries.html","description":"<p><a href=\"https:\/\/github.com\/chriskrycho\/true-myth\">True Myth<\/a> has changed very little since I first released it, and although I have a few ideas for small additions I might make, I don\u2019t really expect it to change much in the future. <em>That\u2019s okay.<\/em><\/p>\n<p>There\u2019s a strange idea in some parts of the software development ecosystem\u2014a way of think I also find myself falling into from time\u2014which takes a lack of changes to a library as a sign that the library is <em>dead<\/em> and shouldn\u2019t be used. I call this idea \u201cstrange\u201d because if you take a step back, it\u2019s actually not necessarily very healthy for certain kinds of libraries to be changing all the time.<\/p>\n<p>But if you\u2019re in an ecosystem where rapid change in libraries is normal, you end up assuming that something which <em>isn\u2019t changing<\/em> is <em>unmaintained<\/em> or <em>not usable<\/em> when in fact the opposite may be true. If someone opens a pull request or an issue for True Myth, I generally get to it in under a day, often under an hour if it\u2019s in my normal working time. (That\u2019s easy enough for me to do because it\u2019s a small, simple library; I don\u2019t have the scale problems that larger projects do.) The project isn\u2019t <em>dead<\/em>. It\u2019s just mostly <em>done<\/em>.<\/p>\n<p>One of the things I\u2019d like to see in the front-end\/JavaScript community in particular is a growing embrace of the idea that some libraries can genuinely be finished. They might need a tweak here or there to work with a new packaging solution, or to fix some corner case bug that has been found. But the \u201cchurn\u201d we all feel to varying degrees would be much diminished if maintainers didn\u2019t feel a constant push to be changing for the sake of, well\u2026 change. The burden on maintainers would be lower, too. Maybe we\u2019d all get to spend less time on small changes that just keep us \u201cup to date\u201d and more on solving bigger problems.<\/p>\n<p>Don\u2019t get me wrong: sometimes changing perspective warrants a rewrite. But in libraries as in apps, just as often you\u2019ll end up with a bad case of <a href=\"https:\/\/en.m.wikipedia.org\/wiki\/Second-system_effect\">second system syndrome<\/a>; and rewrites are <em>rarely<\/em>\u2014not never, but rarely\u2014clean wins.<\/p>\n","pubDate":"Tue, 14 Aug 2018 19:45:00 -0400","guid":"tag:v4.chriskrycho.com,2018-08-14:\/2018\/stable-libraries.html","category":["software development","open source software","libraries","true myth","javascript"]},{"title":"Client-Side Ideas for Server-Side Apps","link":"http:\/\/v4.chriskrycho.com\/2018\/client-side-ideas-for-server-side-apps.html","description":"<p><i class=\"editorial\">A quick note: I drafted this back in June, but forgot to actually publish it!<\/i><\/p>\n<p>I\u2019ve been working on the design of a particular website I maintain (not this one; keep your eyes open), and besides the fact that I have learned a <em>lot<\/em> about web design in general in the years since I originally built that site, I discovered that I desperately want to use a component-drive model for developing sites on the client.<\/p>\n<p>In my day job, I\u2019m used to breaking down my application into discrete components with their own responsibilities. I\u2019ve gotten spoiled by the component-driven model that dominates the front-end web development world now. (My tool of choice is usually Ember, but you\u2019d get the same with React or Vue or whatever else.) And on the server development side, I\u2019m desperately missing those.<\/p>\n<p>I\u2019m using <a href=\"https:\/\/getpelican.com\">Pelican<\/a> for this particular site because that\u2019s what it\u2019s been built on for the past few years and I have no desire to change it at the moment. And that means using <a href=\"http:\/\/jinja.pocoo.org\">Jinja2<\/a> for templating. And Jinja2 has no notion of <em>components<\/em>. Partials, yes\u2014with all the implicit context you have to carry around in your head. It has a few different ways you can sort of hack your way to something sort of vaguely component-like using some of its <a href=\"http:\/\/jinja.pocoo.org\/docs\/2.10\/templates\/#block-assignments\">fancy features<\/a>. But without any kind of \u201cargument\u201d or \u201creturn value\u201d\/yielding (<em>a la<\/em> the ideas I discussed in <a href=\"https:\/\/v4.chriskrycho.com\/2018\/higher-order-components-in-emberjs.html\" title=\"Higher-Order Components in Ember.js\">this post<\/a>). All of the solutions available in <em>any<\/em> of these server-side frameworks for breaking up pages are <em>partial<\/em>-style: which means they\u2019re basically just dumb string includes!<\/p>\n<p>There\u2019s nothing like the way I solve this problem in an Ember app every single day: <em>components<\/em>. There\u2019s no particular reason that the same component-based approach that has flourished on the client <em>can\u2019t<\/em> be done on the client side. It just\u2026 hasn\u2019t, mostly. Which is kind of weird.<\/p>\n<p>Until this week, projects like <a href=\"https:\/\/github.com\/gatsbyjs\/gatsby\">Gatsby<\/a> in the React world made no sense to me at all. It seemed like using a sledgehammer to kill a spider. But after this week, I\u2019m suddenly <em>very<\/em> interested in it\u2014and I might in fact experiment with some server-side component-driven approaches to this at some point in the future\u2014because a couple of days mucking with Jinja2 has me desperately wishing for a good old Ember or React component.<\/p>\n<hr \/>\n<p>As an aside: people talk about client-side development being overly complicated. I know some of what they mean, but the truth is that my experience hacking on this over the last week has actually served to remind me of just how <em>great<\/em> the tooling is in this world.<\/p>\n<p>It\u2019s true that there\u2019s more complexity in many ways to building things with Ember or React or whatever other <abbr>JS<\/abbr>-powered client-side framework than with plain-old <abbr>HTML<\/abbr>. It\u2019s more complex even than with something like Jinja2 or Liquid or whatever other server-side templating language you use. There\u2019s good reason for that complexity, though: it comes with <em>more power<\/em> and <em>more expressiveness<\/em>. And the thing many critiquing the front-end seem to miss is that once you are used to having that power and expressiveness, it\u2019s <em>really<\/em> painful to go back to not having it.<\/p>\n","pubDate":"Thu, 07 Jun 2018 16:00:00 -0400","guid":"tag:v4.chriskrycho.com,2018-06-07:\/2018\/client-side-ideas-for-server-side-apps.html","category":["emberjs","javascript","web design"]},{"title":"#EmberJS2018, Part 4","link":"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-4.html","description":"<p>Following <a href=\"https:\/\/blog.rust-lang.org\/2018\/01\/03\/new-years-rust-a-call-for-community-blogposts.html\">the example<\/a> of the Rust community, the <a href=\"https:\/\/emberjs.com\">Ember.js<\/a> team has <a href=\"https:\/\/emberjs.com\/blog\/2018\/05\/02\/ember-2018-roadmap-call-for-posts.html\" title=\"Ember&#39;s 2018 Roadmap: A Call for Blog Posts\">called for blog posts<\/a> as the first step in setting the 2018 roadmap (which will formally happen through the normal <a href=\"https:\/\/github.com\/emberjs\/rfcs\"><abbr title=\"Request for Comments\">RFC<\/abbr> process<\/a>). This is my contribution.<\/p>\n<p>There are three major themes I think should characterize the Ember.js community and project for the rest of 2018:<\/p>\n<ol type=\"1\">\n<li><a href=\"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-1.html\"><strong>Finishing What We\u2019ve Started<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-2.html\"><strong>Doubling Down on Documentation<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-3.html\"><strong>Defaulting to Public for Discussions<\/strong><\/a><\/li>\n<li><strong>Embracing the Ecosystem<\/strong> (this post)<\/li>\n<\/ol>\n<hr \/>\n<p>Over the last few weeks, I\u2019ve talked about a few big ideas that I think the Ember.js community should go after in 2018 which will help the framework excel over the next few years. This last one (like Part 3 before it) is more a <em>culture shift<\/em> than a matter of <em>things to build<\/em>.<\/p>\n<p>We need to shift from a posture of defensiveness about Ember.js to one of embracing the ecosystem, and embracing our role in the ecosystem.<\/p>\n<p>It\u2019s easy to end up in an us-vs.-them mentality when looking at different libraries and frameworks. It\u2019s doubly easy to go there when you often hear \u201cIsn\u2019t Ember dead?\u201d or variations on that theme. We should avoid that way of thinking anyway. And there are three big pieces to this: <em>contributing outwards<\/em>, <em>smoothing the paths into Ember<\/em> from other ecosystems, and <em>embracing the rest of the ecosystem<\/em>.<\/p>\n<section id=\"contributing-outwards\" class=\"level3\">\n<h3>Contributing outwards<\/h3>\n<p>There is genuinely great stuff happening all over the place in the front-end, and many of the things we love about working with Ember today have come directly out of e.g.\u00a0React\u2014hello, \u201cdata-down-actions-up\u201d! The same is true in reverse: Ember has contributed many important ideas to the broader front-end ecosystem, from its early emphasis on rigorously linking URLs and application state to helping pioneer and popularize the use of good command line tooling, to more recent emphasis on <em>compilation<\/em> as a way of solving certain classes of problems.<\/p>\n<p>So as we build all of these things, one of the best things to do\u2014and, I believe, one of the ways we help Ember grow!\u2014is think about how our work can benefit the larger ecosystem. When you build a library, you should consider whether there are parts of it that <em>don\u2019t<\/em> have to be Ember specific. For example, a colleague and I recently built out the foundation of a solution for well-rationalized form-handling.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> We build it in two pieces, though: a core library in TypeScript that will work as well in Vue or React as in Ember, and an Ember component library that consumes that core functionality.<\/p>\n<p>The more we can take that tack in <em>general<\/em>, the better. It\u2019s the first piece of making the gap between people\u2019s experience in other parts of the front-end ecosystem and the Ember part smaller. Ember will seem much more interesting if people find themselves <em>often<\/em> getting value out of things we\u2019ve built.<\/p>\n<\/section>\n<section id=\"smoothing-the-paths-in\" class=\"level3\">\n<h3>Smoothing the paths in<\/h3>\n<p>The flip side of this is figuring out ways to make it easier for people coming <em>into<\/em> Ember.js to map patterns from their existing experience onto the framework\u2019s tools and patterns. The simple reality is that there are far, far more developers familiar with React, Angular, and Vue than with modern Ember.js. Ember genuinely has a lot to offer there, but we need to make it easier for people to see that value and to recognize how it\u2019s a lot like the good parts of what they already know!<\/p>\n<p>This is primarily a communications effort; it means changes to the docs and to the homepage, but also to what we do in blog posts and tutorials and talks as a community!<\/p>\n<p>At the highest level, I cannot recommend strongly enough the model suggested by Chris Garrett in <a href=\"https:\/\/medium.com\/@pzuraq\/emberjs-2018-ember-as-a-component-service-framework-2e49492734f1\">his #EmberJS2018 post<\/a>: treat Ember.js (both in the docs and also in our presentations and communications about it) as a <em>component-service<\/em> framework. This not only maps more easily to patterns people know from other communities, it has the really important effect of demystifying a lot of the \u201cmagic\u201d that seems perplexing in the framework, especially around Ember Data\u2014which is, after all, just a service you can inject!<\/p>\n<p>When we write blog posts, we can accomplish a lot of this simply by being aware of the rest of the ecosystem and making analogies there. You can see an example of how I\u2019ve started trying to do this in my recent blog post on <a href=\"http:\/\/v4.chriskrycho.com\/2018\/higher-order-components-in-emberjs.html\">higher-order components in Ember.js<\/a>. It was just one little line:<\/p>\n<blockquote>\n<p>In React, the [higher-order components] pattern as a whole is often known as the <code>renderProps<\/code> pattern, for the way you most often accomplish it. It\u2019s all the same idea, though!<\/p>\n<\/blockquote>\n<p>That\u2019s not a lot of extra work, but it means that if someone searches for \u201crenderProps Ember.js\u201d there now exists a blog post which will help someone map there existing knowledge over! I wasn\u2019t writing a \u201chow to do React renderProps in Ember\u201d post\u2014but I still smoothed the path in just a little bit. We should be doing that everywhere we can. It\u2019s usually not a lot of effort to make those kinds of moves in talks or blog posts, but the yield is high: Ember stops being some super weird foreign entity and starts looking like a variation on a theme.<\/p>\n<p>There is also a much larger effort we <em>do<\/em> need to undertake to make that story clearer on the home page and in the documentation\u2014an effort that I know is already very much in consideration from chatting with the really amazing crew in <code>#-team-learning<\/code> on Slack. In the <strong>how you can help<\/strong> bucket: seriously please go into that channel and start chipping away at small tasks! There\u2019s (<a href=\"https:\/\/m.youtube.com\/watch?v=Abu2BNixXak\" title=\"\u201cBecoming a Contributor\u201d, my Rust Belt Rust 2017 talk\">always!<\/a>) way more work to be done than hands to do it.<\/p>\n<p>I think this also means prioritizing technical work that eases this. The sooner we can land the Glimmer component model, the better. The sooner we can hash out a more cogent story on routes and controllers and components, the better. The sooner we can make \u201cnpm-install-your-way-to-Ember\u201d an actually viable strategy, the better. Because each of those things makes Ember dramatically more accessible to people working in other ecosystems today; each lowers the barrier to entry in some substantial way; and the combination of them all makes it far more viable for someone to <em>try<\/em> Ember in an existing application.<\/p>\n<\/section>\n<section id=\"embracing-the-rest-of-the-ecosystem\" class=\"level3\">\n<h3>Embracing the rest of the ecosystem<\/h3>\n<p>The final piece of this is actively embracing the best parts of the rest of the ecosystem.<\/p>\n<p>We as a community need to avoid defensiveness and recognize that there\u2019s a <em>lot<\/em> of good in the rest of the front-end space. I understand how it can be easy to feel defensive. Being dismissed, having people be surprised that the project even still exists, etc. gets really old after a while. But however reasonable that defensiveness is, it\u2019s ultimately counterproductive. It makes us hold onto things we don\u2019t need to hold onto, and it makes us ignore things that might benefit us, and as a result it can make us <em>needlessly weird<\/em> technically.<\/p>\n<p><em>Needless weirdness<\/em> is an important idea I\u2019d love for us to keep in mind. Any time you\u2019re willing to move more slowly, to let the \u201cnew shiny\u201d bake for a while to see whether it\u2019s genuinely worth investing in, you\u2019re going to seem weird. Likewise when you strongly embrace stability, in a broader ecosystem which hasn\u2019t. Likewise when you value convention over configuration, in a broader ecosystem which hasn\u2019t. But it\u2019s important to be able to distinguish between <em>needful<\/em> and <em>needless<\/em> weirdness.<\/p>\n<p>We should have regular conversations as a community\u2014through <abbr title=\"request for comments\">RFC<\/abbr>s, through forum threads, through blog post arguments, etc.\u2014about what\u2019s <em>needful<\/em> weirdness, and what has become <em>needless<\/em> weirdness. (Because which weird things are needful change over time!) We should gleefully embrace the needful weirdness. But we should equally gleefully drop the needless weirdness.<\/p>\n<p>What makes Ember special is, by and large, <em>not<\/em> the specific technical implementations we\u2019ve landed on.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> What makes Ember valuable is having a coherent top-to-bottom story and a rich community with a commitment to aggressively seeking out shared solutions, and an even deeper commitment to providing good migration paths forward when we change things.<\/p>\n<p>But here\u2019s the thing: those values are increasingly (if slowly) being embraced <em>outside<\/em> the Ember ecosystem as well. Ember can contribute and even lead in many ways here\u2014but only if we start actively embracing the good of other parts of the front-end ecosystem.<\/p>\n<p>For example: I\u2019ve heard more times than I can count over the last few years that our use of Broccoli.js is really important for Ember, and the reality is\u2026 that isn\u2019t true. We could have built on top of just about <em>any<\/em> solution, and it would have been <em>fine<\/em>. Broccoli <em>does<\/em> have some advantages; it also has some real disadvantages (one of which is that we\u2019re the only ones using it!), and we should forthrightly acknowledge those. By the same token, if Webpack is working well for many people, let\u2019s neither trash it in discussion nor ignore it in implementation. Instead, let\u2019s make it easy for people to integrate Webpack into the Ember world.<\/p>\n<p>That doesn\u2019t oblige us to chuck out our existing build tooling! It just means making our own build pipelines robust enough to interoperate well with other packaging systems. And that\u2019s precisely what the Ember <abbr>CLI<\/abbr> team has been doing! This needs to be our pattern across the board going forward.<\/p>\n<p>It\u2019s truly well and good to have made a call a few years ago, and to be going out of our way to mitigate the costs of churn. At the same time, we need to communicate\u2014to a degree that probably feels like <em>over<\/em>communicating to the people who already understand all these decisions!\u2014so that both the original rationales and the current status are accessible to all the people who <em>weren\u2019t<\/em> there when the decisions were made.<\/p>\n<p>Insofar as it\u2019s true that Broccoli and Webpack solve different problems, <em>explaining<\/em> how Broccoli and Webpack actually solve meaningfully different problems \u2014or at least, <em>excel<\/em> at solving different problems\u2014is one of the most important things we can do as well. Props to Chris Thoburn (<a href=\"https:\/\/twitter.com\/runspired\">@runspired<\/a>) for doing this in a few different contexts recently, but we need a lot more of it\u2014because it\u2019s one example I think most people both inside and outside the Ember community have just kind of scratched their heads at for a long time (me included).<\/p>\n<p>Again: I take the Broccoli\/Webpack example simply because it\u2019s an obvious one. The broader point is that we need to find ways to embrace the shared solutions which emerge not only in the Ember community but in the front-end ecosystem as a whole, even as we also do the hard work to make our own shared solutions useful to the rest of the front-end ecosystem. That two-way exchange will benefit us, and smooth the paths in for newcomers, and benefit the rest of the ecosystem, too\u2014and that\u2019s a huge win. Because in a very real sense, we front-end developers are all in this together.<\/p>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>Keep your eyes open; you\u2019ll see a blog post announcing that along with a full set of documentation for it sometime in the next month or so!<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>To be clear: many, though certainly not all, of those specific implementations I like, but that\u2019s beside the point.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Tue, 29 May 2018 07:45:00 -0400","guid":"tag:v4.chriskrycho.com,2018-05-29:\/2018\/emberjs2018-part-4.html","category":["emberjs","javascript","typescript","emberjs2018"]},{"title":"Higher-Order Components in Ember.js","link":"http:\/\/v4.chriskrycho.com\/2018\/higher-order-components-in-emberjs.html","description":"<p>One of the most powerful patterns in programming is the idea of <em>higher-order functions<\/em>: functions which can take other functions as arguments or return them as their return values. If you\u2019ve spent much time at all working in JavaScript, you\u2019ve certainly encountered these\u2014whether you\u2019re using <code>Array.map<\/code> to transform the values in an array, or passing a function as an argument to an event handler.<\/p>\n<p>The same pattern is incredibly useful in building components, and most modern front-end frameworks support it\u2014including Ember.js! (In React, the pattern as a whole is often known as the <code>renderProps<\/code> pattern, for the way you most often accomplish it. It\u2019s all the same idea, though!)<\/p>\n<p>In this little post, I\u2019ll show you how to build a small \u201chigher-order component\u201d in Ember.js, hopefully demystifying that term a little bit a long the way. (If you just want to see how the pieces fit together, you can see the finished app <a href=\"https:\/\/github.com\/chriskrycho\/ember-hoc-example\">in this repo<\/a>.)<\/p>\n<aside>\n<p>I\u2019m going to be using classes and decorators throughout. Both are very much ready-to-go in Ember, and I commend them to you! I\u2019m also going to be using some of the new <a href=\"https:\/\/emberjs.com\/blog\/2018\/04\/13\/ember-3-1-released.html#toc_introducing-optional-features-3-of-4\">optional features<\/a> available in Ember 3.1+ to use template-only components!<\/p>\n<p>Note that one of the most important consequences of this is that arguments have to be referenced as <code>@theArgumentName<\/code> rather than just <code>theArgumentName<\/code> in templates. The reason is precisely that there is no backing JavaScript component. In old-school Ember.js components, <code>{{theArgumentName}}<\/code> is implicitly turned into <code>{{this.argumentName}}<\/code>, which does a lookup on the backing component. In Glimmer-style components\u2014of which these are the first part\u2014arguments live on a designated <code>args<\/code> property and are accessible in templates via <code>@theArgumentName<\/code> instead.<\/p>\n<\/aside>\n<section id=\"higher-order-components-what-are-they\" class=\"level2\">\n<h2>Higher-Order Components, What Are They<\/h2>\n<p>Just like with a \u201chigher-order function,\u201d all we mean when we talk about a \u201chigher-order component\u201d is a component which takes other components as arguments, returns other components itself (in Ember\u2019s case via <code>yield<\/code> in a template), or both.<\/p>\n<p>The thing we\u2019re actually going to build here is a \u201cmodal\u201d which accepts an optional button as an arguments, and which yields out a component for dividing the modal into sections visually so you can pass your own content in and have it look just right. This is closely based on a component my colleagues and I at Olo built recently, just with some of our specific details stripped away to get at the actually important bits. Here\u2019s what it looks like in practice:<\/p>\n<figure>\n<img src=\"https:\/\/f001.backblazeb2.com\/file\/chriskrycho-com\/images\/hoc-rendered.png\" alt=\"a modal with sectioned text and a close button\" \/><figcaption>a modal with sectioned text and a close button<\/figcaption>\n<\/figure>\n<p>The goal for the button arguments is to let the modal be able to render the button the caller passes in, while not being concerned with the <em>functionality<\/em> of the button. Otherwise, we\u2019d have to tie the \u201cAPI\u201d of the modal to the details of button behavior, bind more actions into it, etc.<\/p>\n<p>The goal for the yielded sectioning component is for whatever is rendering the modal itself to be able to pass content in and get it chunked up however the modal decides is appropriate\u2014the modal can display its own styles, etc.\u2014without having to worry about the details of applying classes or sectioning up the content itself.<\/p>\n<p>In short, we want to <em>separate our concerns<\/em>: the modal knows how to lay out its contents and where to put buttons, but it doesn\u2019t want to have to know <em>anything<\/em> about what the buttons do. The most complicated interaction in the world could be going on, and the modal won\u2019t have to care. Likewise, things <em>using<\/em> the modal can pass content and buttons into it, and let the modal manage its own layout and so on without having to be concerned with the details of that. So what does that look like in practice?<\/p>\n<p>The approach I use here builds on the \u201ccontextual components\u201d pattern in Ember.js. The main new idea is that the <em>context<\/em> includes components!<\/p>\n<\/section>\n<section id=\"implementing-it\" class=\"level2\">\n<h2>Implementing It<\/h2>\n<p>We have three components here:<\/p>\n<ul>\n<li>a button<\/li>\n<li>a modal<\/li>\n<li>a modal section<\/li>\n<\/ul>\n<p>Since Ember.js still (for now!) requires component names to be at least two words separated by a dash, we\u2019ll just call these <code>x-button<\/code>, <code>x-modal<\/code>, and <code>x-modal-section<\/code>.<\/p>\n<section id=\"x-button\" class=\"level3\">\n<h3><code>x-button<\/code><\/h3>\n<p>The button component, we\u2019ll keep pretty simple: it\u2019s just a button element with a given label and an action bound to it:<\/p>\n<pre class=\"handlebars\"><code>&lt;button class={{@buttonClass}} type=&#39;button&#39; {{action @onClick}}&gt;\n  {{@label}}\n&lt;\/button&gt;<\/code><\/pre>\n<\/section>\n<section id=\"x-modal\" class=\"level3\">\n<h3><code>x-modal<\/code><\/h3>\n<p>The <code>x-modal<\/code> has the meat of the implementation.<\/p>\n<pre class=\"handlebars\"><code>&lt;div class=&#39;modal-backdrop&#39;&gt;&lt;\/div&gt;\n&lt;div class=&#39;modal&#39;&gt;\n  &lt;div class=&#39;modal-content&#39;&gt;\n    {{yield (hash section=(component &#39;x-modal-section&#39;))}}\n  &lt;\/div&gt;\n\n  {{#if @button}}\n    {{component @button buttonClass=&#39;modal-button&#39;}}\n  {{\/if}}\n&lt;\/div&gt;<\/code><\/pre>\n<p>The two things two notice here are the <code>yield<\/code> and the <code>component<\/code>.<\/p>\n<p>The <code>yield<\/code> statement yields a <a href=\"https:\/\/www.emberjs.com\/api\/ember\/3.1\/classes\/Ember.Templates.helpers\"><code>hash<\/code><\/a> with one property: <code>section<\/code>. Yielding a hash is a convenient pattern in general. Here, we\u2019re doing it to make the <abbr>API<\/abbr> nicer for users of this component. It means that if we name the yielded value <code>|modal|<\/code> when we invoke this, we\u2019ll be able to write <code>modal.section<\/code> to name this particular yielded item. (You\u2019ll see exactly this below.)<\/p>\n<p>We use the <code>component<\/code> helper twice: once as the value of the <code>section<\/code> key in the yielded hash, and once for the <code>button<\/code> below. In both cases, the helper does the same thing: invokes a component! While the most common way to render a component is with its name, inline\u2014like <code>{{x-modal}}<\/code>\u2014you can always render it with the <code>component<\/code> helper and the name as a string: <code>{{component 'x-modal'}}<\/code>. This lets you render different components dynamically!<\/p>\n<p>Let\u2019s remember our initial analogy: the same way you can pass different functions to a higher-order function like <code>Array.prototype.map<\/code>, you can pass different components to a higher-order component like our <code>x-modal<\/code> here. And just like you can <em>return<\/em> a function from a higher-order function, we can <em>yield<\/em> a component from a higher-order component. Just like higher-order functions, the function passed in or returned just has to have the right shape.<\/p>\n<p>For example, the argument to <code>Array.prototype.map<\/code> needs to be a function which performs an operation on a single item in the array (and maybe also the index) and hands back the result of that operation. Similarly, the <code>button<\/code> argument to our <code>x-modal<\/code> needs to accept a <code>buttonClass<\/code> component so that the modal can apply some styling to it. The same thing holds for the component being yielded back out: it has an <abbr>API<\/abbr> you should use to invoke it, just like any other.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p>\n<p>All of this gets at something really important: you can think of components as just being <em>pure functions<\/em>: they take some input in the form of arguments, and give you the output of what they <em>render<\/em> and what they <em>yield<\/em>\u2014and they always give you the same rendered <abbr>HTML<\/abbr> and the same yielded values for the same inputs. They\u2019re just functions!<\/p>\n<\/section>\n<section id=\"x-modal-section\" class=\"level3\">\n<h3><code>x-modal-section<\/code><\/h3>\n<p>The <code>x-modal-section<\/code> component is the simplest of all of these: it has no behavior, just some styling to actually chunk up the content:<\/p>\n<pre class=\"handlebars\"><code>&lt;div class=&#39;modal-section&#39;&gt;\n  {{yield}}\n&lt;\/div&gt;<\/code><\/pre>\n<\/section>\n<section id=\"application-controller-and-template\" class=\"level3\">\n<h3>Application controller and template<\/h3>\n<p>Now, let\u2019s use in the context of the application template, where we can see how the pieces all fit together. First, let\u2019s see the application controller backing it\u2014nothing unusual here, just a simple toggle to show or hide the modal.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a><\/p>\n<pre class=\"ts\"><code>import Controller from &quot;@ember\/controller&quot;;\nimport { action } from &quot;@ember-decorators\/object&quot;;\n\nexport default class Application extends Controller {\n  constructor() {\n    super(...arguments);\n    this.showModal = false;\n  }\n\n  @action\n  showIt() {\n    this.set(&quot;showModal&quot;, true);\n  }\n\n  @action\n  hideIt() {\n    this.set(&quot;showModal&quot;, false);\n  }\n}<\/code><\/pre>\n<p>Now for the interesting bit\u2014the template where we invoke <code>x-modal<\/code> and use its higher-order-component functionality:<\/p>\n<pre class=\"handlebars\"><code>{{#if showModal}}\n  {{#x-modal\n      button=(component &#39;x-button&#39;\n        label=&#39;Close modal!&#39;\n        onClick=(action &#39;hideIt&#39;)\n      )\n      as |modal|\n  }}\n    {{#modal.section}}\n      Here is some content!\n    {{\/modal.section}}\n\n    {{#modal.section}}\n      Here is some other content.\n    {{\/modal.section}}\n\n    {{#modal.section}}\n      &lt;p&gt;The content can have its own sections, as you&#39;d expect!&lt;\/p&gt;\n      &lt;p&gt;Nothing crazy going on here. Just a normal template!&lt;\/p&gt;\n    {{\/modal.section}}\n  {{\/x-modal}}\n{{\/if}}\n\n&lt;button class=&#39;button&#39; {{action &#39;showIt&#39;}}&gt;Show modal&lt;\/button&gt;\n\n&lt;!-- some other content on the page --&gt;<\/code><\/pre>\n<p>We invoke the block form of <code>x-modal<\/code> just like we would any block component, and we get back the thing it yields with <code>as |modal|<\/code>. However, one of the arguments we pass to it is a component. But <code>modal<\/code> is a <code>hash<\/code> (an object!) with a property named <code>section<\/code>, which is the <code>x-modal-section<\/code> component.<\/p>\n<p>Again, you can think of this like calling a function with one function as an argument and getting another function back as its return value\u2014that returned function being something we could call over and over again once we had it.<\/p>\n<p>Here, we \u201ccall the function\u201d\u2014invoke the <code>x-modal<\/code> component\u2014with <code>component 'x-button'<\/code> as its argument, and the returned <code>modal.section<\/code> is a component we can invoke like a normal component.<a href=\"#fn3\" class=\"footnote-ref\" id=\"fnref3\" role=\"doc-noteref\"><sup>3<\/sup><\/a> We could even pass it into some <em>other<\/em> component itself if we so desired.<\/p>\n<p>And that\u2019s really all there is to it!<\/p>\n<\/section>\n<\/section>\n<section id=\"summary\" class=\"level2\">\n<h2>Summary<\/h2>\n<p>\u201cHigher-order components\u201d aren\u2019t necessarily something you need all the time, but they\u2019re really convenient and very powerful when you <em>do<\/em> need them. They\u2019re also a lot less complicated than the name might seem! Components are just things you can pass around in the context of a component template\u2014they\u2019re the <em>functions<\/em> of Handlebars.<a href=\"#fn4\" class=\"footnote-ref\" id=\"fnref4\" role=\"doc-noteref\"><sup>4<\/sup><\/a><\/p>\n<p>Splitting things into components like this does increase complexity, and in particular it can increase the mental overhead of keeping track of how the pieces fit together. However, they also let us cleanly separate different pieces of functionality from each other. Doing it this way means that our modal can be concerned about <em>positioning<\/em> a button without needing to expose an <abbr>API<\/abbr> for all of the button\u2019s own mechanics for handling clicks and performing whatever actions necessary. That makes our modal <em>and<\/em> our button way more reusable across our application. The button can be used <em>wherever<\/em> a button is useful, and the modal doesn\u2019t need to know or care anything about it. Likewise, the button has no need to know anything about the context where it\u2019s being used; from the button component\u2019s perspective, it just gets wired up to some actions as usual. The same thing goes for the modal sections: they let us abstract over how the DOM is laid out, what classes are applied to it, and so on\u2014they chunk up the modal, but the modal itself maintains responsibility for how that chunking up happens. And the caller doesn\u2019t even <em>have<\/em> to use that; it\u2019s just a tool that\u2019s available for that purpose.<\/p>\n<p>To sum it all up, I\u2019ll just reiterate my earlier description: components are just like pure functions: the same inputs give you the same outputs\u2014and, just like functions, those inputs and outputs can be other functions, that is, other components.<\/p>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>If you want a good way to document the things a component <code>yield<\/code>s, check out <a href=\"https:\/\/ember-learn.github.io\/ember-cli-addon-docs\/latest\/docs\/api\/components\/docs-demo\">ember-cli-addon-docs<\/a>, which can read an <code>@yield<\/code> JSDoc annotation.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>And it could just as well be a component; the top-level controller template is just where we put our main app functionality.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn3\" role=\"doc-endnote\"><p>We could also simplify this since we\u2019re only returning one component, and if we had the full Glimmer component story, this could look <em>very<\/em> nice:<\/p>\n<pre class=\"ts\"><code>&lt;Modal @button={{component &#39;Button&#39;}} as |Section|&gt;\n  &lt;Section&gt;\n    Some content!\n  &lt;\/Section&gt;\n  &lt;Section&gt;\n    Some more content!\n  &lt;\/Section&gt;\n\n  &lt;Section&gt;\n    &lt;p&gt;The content can have its own sections, as you&#39;d expect!&lt;\/p&gt;\n    &lt;p&gt;Nothing crazy going on here. Just a normal template!&lt;\/p&gt;\n  &lt;\/Section&gt;\n&lt;\/Modal&gt;<\/code><\/pre>\n<a href=\"#fnref3\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/li>\n<li id=\"fn4\" role=\"doc-endnote\"><p>If you\u2019re inclined to \u201cwell actually\u201d me about <em>helpers<\/em> being the real functions of Handlebars templates: in the Glimmer <abbr>VM<\/abbr> world, helpers are just a kind of component.<a href=\"#fnref4\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Sat, 26 May 2018 14:00:00 -0400","guid":"tag:v4.chriskrycho.com,2018-05-26:\/2018\/higher-order-components-in-emberjs.html","category":["emberjs","javascript","typescript"]},{"title":"#EmberJS2018, Part 3","link":"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-3.html","description":"<p>Following <a href=\"https:\/\/blog.rust-lang.org\/2018\/01\/03\/new-years-rust-a-call-for-community-blogposts.html\">the example<\/a> of the Rust community, the <a href=\"https:\/\/emberjs.com\">Ember.js<\/a> team has <a href=\"https:\/\/emberjs.com\/blog\/2018\/05\/02\/ember-2018-roadmap-call-for-posts.html\" title=\"Ember&#39;s 2018 Roadmap: A Call for Blog Posts\">called for blog posts<\/a> as the first step in setting the 2018 roadmap (which will formally happen through the normal <a href=\"https:\/\/github.com\/emberjs\/rfcs\"><abbr title=\"Request for Comments\">RFC<\/abbr> process<\/a>). This is my contribution.<\/p>\n<p>There are three major themes I think should characterize the Ember.js community and project for the rest of 2018:<\/p>\n<ol type=\"1\">\n<li><a href=\"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-1.html\"><strong>Finishing What We\u2019ve Started<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-2.html\"><strong>Doubling Down on Documentation<\/strong><\/a><\/li>\n<li><strong>Defaulting to Public for Discussions<\/strong> (this post)<\/li>\n<li><a href=\"https:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-4.html\"><strong>Embracing the Ecosystem<\/strong><\/a><\/li>\n<\/ol>\n<hr \/>\n<p>One of the small changes I think would substantially improve the Ember.js ecosystem is: <strong>defaulting to public for discussions<\/strong> among the core team. Indeed: for any open-source project with community involvement like Ember.js has, that should be the default. Not the <em>only<\/em> option, just the default option.<\/p>\n<p>There is plenty of value in having private channels for discussion in contexts like this. Sometimes you have to deal with something awkward or socially difficult. Sometimes you have already taken the community\u2019s input and just have to come to a decision about what to do on something. Private channels are useful.<\/p>\n<p>But: they shouldn\u2019t be the default. They should be what you turn to when you\u2019re in one of those particular kinds of situations which require it. The default should be public discussion and interaction.<\/p>\n<p>Over the last year, the maintainer-ship (and therefore decision-making) of ember-cli-typescript and the surrounding TypeScript ecosystem has grown from being pretty much just me to being a small group of four of us: Derek Wickern, Dan Freeman, James Davis, and me. We have the \u201cfinal say,\u201d so to speak, on the things we\u2019re doing with the addon and the typings and so on. (What that actually means in practice is mostly just we all try to shoulder the burden of staying on top of pull requests.) And we have a private channel for discussions as a \u201ccore team\u201d for projects in the <a href=\"https:\/\/github.com\/typed-ember\">typed-ember<\/a> organization.<\/p>\n<p>But: it\u2019s not the default. It\u2019s what we turn to when we\u2019re in one of those particular kinds of situations which require it. The default is public discussion and interaction.<\/p>\n<p>And this isn\u2019t just an unspoken norm or something. As a team, we all explicitly agreed that we default to public. Pretty much the only times we chat in our private channel is if we\u2019re figuring out how to diffuse an awkward situation kindly, or if we\u2019re adding someone else to the team. Otherwise, we try to have all our discussions in the GitHub issues for the projects or the <code>#topic-typescript<\/code> room in the Ember Community Slack.<\/p>\n<p>This has a few major effects, as I see it:<\/p>\n<ul>\n<li><p>No one should feel left out or in the dark about what we\u2019re up to. Even if we\u2019re hashing out crazy-seeming ideas for how to move stuff forward, it\u2019s all there for everyone to see. This includes neat things like Dan Freeman\u2019s proof-of-concept on <a href=\"https:\/\/twitter.com\/__dfreeman\/status\/994410180661170177\">type-checked templates<\/a>, or our mad sprint (as a team!) to get some core improvements landed before I gave a workshop at EmberConf, or anything else we\u2019re going after.<\/p><\/li>\n<li><p>We\u2019re obviously available for input on things as people have questions, because we\u2019re interacting with <em>each other<\/em> in those public forums. And if we\u2019d like to start moving some of the oft-repeated questions over to the <a href=\"https:\/\/discuss.emberjs.com\">Ember Discourse<\/a> or to <a href=\"https:\/\/stackoverflow.com\/questions\/tagged\/ember.js\">Stack Overflow<\/a>, it\u2019s still really helpful for people who <em>are<\/em> on the Slack to see that we\u2019re there and available for help.<\/p><\/li>\n<li><p>We get to see the regular pain points others run into. That often turns into issues, priorities, etc. for us as a group. The slowly growing issue <a href=\"https:\/\/github.com\/typed-ember\/ember-cli-typescript\/issues\/170\">tracking things we need to document<\/a> is essentially a direct product of that constant cycle of interaction.<\/p><\/li>\n<li><p>We get the benefit of input from others! If we\u2019ve missed something, or simply failed to think of something, others in the community often haven\u2019t. One prime example of this: the \u201cregistry\u201d strategy we use for making things like Ember Data store, adapter, etc. lookups work came out of conversations with a community member (<a href=\"https:\/\/github.com\/maerten\">Maarten Veenstra<\/a>) which happened many months before we were in a spot where we could land that kind of thing\u2014and initially I was pretty skeptical of it, but they were totally right, and it\u2019s now core to how Ember\u2019s typings work!<\/p><\/li>\n<\/ul>\n<p>I recommend\u2014very strongly\u2014that the Ember.js core team adopt the same strategy. Teams <em>do<\/em> need private channels sometimes. But they shouldn\u2019t be the default. They should be for those particular circumstances which <em>require<\/em> it.<\/p>\n<p>The biggest things I think could come out of this are:<\/p>\n<ul>\n<li><p>A greater confidence from within the Ember.js community about what the core team is up to and where we\u2019re going. Technical leadership seems to me to be about 10% technical brilliance and 90% clear communication. We have loads of technical brilliance; we need more communication!<\/p><\/li>\n<li><p>More confidence in the trajectory of Ember.js from <em>outside<\/em> its existing community. Seeing that there is active leadership is essential for people to have confidence that choosing Ember.js is a good choice both today and for the medium-to-long-term.<\/p><\/li>\n<\/ul>\n<p>And we need both of those\u2014a lot\u2014for Ember.js to continue to grow and thrive in the years ahead!<\/p>\n","pubDate":"Wed, 23 May 2018 07:30:00 -0400","guid":"tag:v4.chriskrycho.com,2018-05-23:\/2018\/emberjs2018-part-3.html","category":["emberjs","emberjs2018","javascript","leadership"]},{"title":"#EmberJS2018, Part 2","link":"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-2.html","description":"<p>Following <a href=\"https:\/\/blog.rust-lang.org\/2018\/01\/03\/new-years-rust-a-call-for-community-blogposts.html\">the example<\/a> of the Rust community, the <a href=\"https:\/\/emberjs.com\">Ember.js<\/a> team has <a href=\"https:\/\/emberjs.com\/blog\/2018\/05\/02\/ember-2018-roadmap-call-for-posts.html\" title=\"Ember&#39;s 2018 Roadmap: A Call for Blog Posts\">called for blog posts<\/a> as the first step in setting the 2018 roadmap (which will formally happen through the normal <a href=\"https:\/\/github.com\/emberjs\/rfcs\"><abbr title=\"Request for Comments\">RFC<\/abbr> process<\/a>). This is my contribution.<\/p>\n<p>There are three major themes I think should characterize the Ember.js community and project for the rest of 2018:<\/p>\n<ol type=\"1\">\n<li><a href=\"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-1.html\"><strong>Finishing What We\u2019ve Started<\/strong><\/a><\/li>\n<li><strong>Doubling Down on Documentation<\/strong> (this post)<\/li>\n<li><a href=\"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-3.html\"><strong>Defaulting to Public for Discussions<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-4.html\"><strong>Embracing the Ecosystem<\/strong><\/a><\/li>\n<\/ol>\n<hr \/>\n<section id=\"part-2-double-down-on-docs\" class=\"level2\">\n<h2>Part 2: Double down on docs<\/h2>\n<p>The best project in the world is useless without documentation. As such, my <em>second<\/em> major goal for Ember.js this year is to see our documentation story improve dramatically across a number of fronts. This is not just the kind of thing that\u2019s important in principle or because we care about doing the right thing, though those alone <em>are<\/em> sufficient motivation. It\u2019s <em>also<\/em> absolutely necessary for Ember to grow and thrive in the ways it deserves to in the years ahead.<\/p>\n<p>To be clear: Ember\u2019s story around documentation is <em>pretty good<\/em> and it continues to improve all the time. A few years ago, the base documentation was a mess and even figuring out where to start was hard. Today, Ember.js itself has great guides along with versioned-and-searchable <abbr title=\"application programming interface\">API<\/abbr> documentation. The gaps now are in the <em>surrounding ecosystem<\/em> and in the <em>framework internals<\/em>. That\u2019s huge progress! But if we want Ember to excel, we need to go after both of these with gusto.<\/p>\n<section id=\"the-surrounding-ecosystem\" class=\"level3\">\n<h3>The surrounding ecosystem<\/h3>\n<p>Ember Data, Ember Engines, and perhaps most important Ember <abbr title=\"command line interface\">CLI<\/abbr> and its core dependency Broccoli all <em>desperately<\/em> need documentation work just at the \u201chow do you even use these things level.\u201d<\/p>\n<ul>\n<li><p><strong>Broccoli.js<\/strong> in particular is core to pretty much everything in Ember\u2019s ecosystem, and its docs today are in roughly the state Webpack\u2019s were back in its sad 1.0 days. We should take a page out of our own history (and Webpack\u2019s for that matter!) and make it easy for people to use Broccoli in whatever ways their apps need, and that mostly means documenting it!<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> Oli Griffith\u2019s recent <a href=\"http:\/\/www.oligriffiths.com\/broccolijs\/\">blog post series<\/a> is an incredibly valuable first step in that direction. But we need really solid documentation for <a href=\"http:\/\/broccolijs.com\">Broccoli itself<\/a>, and also for the equally important <a href=\"https:\/\/www.npmjs.com\/search?q=keywords:broccoli-plugin\">plugin ecosystem<\/a> which is the primary way people interact with it.<\/p><\/li>\n<li><p>The docs for <strong>Ember <abbr>CLI<\/abbr><\/strong> itself are <em>decent<\/em>, but they\u2019re quite out of date and are about to be a lot more so because of the previously-mentioned packager bits. We need accurate and up-to-date guides and <abbr>API<\/abbr> docs for the <abbr>CLI<\/abbr>, and we also need clarity about the seams between Ember <abbr>CLI<\/abbr> and Broccoli\u2014something I\u2019ve only begun to become clear on after a year of hacking on <a href=\"https:\/\/github.com\/typed-ember\/ember-cli-typescript\">ember-cli-typescript<\/a>! This includes a number of kinds of documentation:<\/p>\n<ul>\n<li>up-to-date guides<\/li>\n<li>complete <abbr>API<\/abbr> documentation<\/li>\n<li>a \u201ccookbook\u201d of common patterns to use<\/li>\n<\/ul><\/li>\n<li><p>The <strong>Ember Data<\/strong> docs need to be split into two parts: one for <em>users<\/em> of Ember Data, and one for people building Ember Data integrations and addons. Right now, all the docs are targeted squarely at implementors of Ember Data addons. This means that one of the pieces of the Ember ecosystem that\u2019s in widest use (and is <em>most<\/em> distinct from the rest of the JS ecosystem!) is really, really hard to learn. This is the part of the framework I still struggle the most with, despite having worked full time on an Ember app for over two years now.<\/p><\/li>\n<li><p><strong>Ember Engines<\/strong> are really need for manually breaking up your app into discrete sections which can be worked on independently and even loaded dynamically as you need them, and they provide a different level of abstraction than route-splitting and other similar approaches. (Not necessarily better or worse, but different.) Unfortunately, most of the documentation hasn\u2019t been touched in over a year. That means if you <em>want<\/em> to use Ember Engines, almost all of the information is in an example here and a Slack conversation there. We need to turn that sort of \u201ctribal knowledge\u201d into actual docs!<\/p><\/li>\n<\/ul>\n<p>To be clear, the Ember docs team is doing great work and is already going after a lot of these areas; but there\u2019s an enormous amount of ground to cover. They could use your help! Because if Ember is going to flourish in the year(s) ahead, we need good docs. And users are the people best-placed in all the world to help write docs.<\/p>\n<p>So <strong>how you can help:<\/strong><\/p>\n<ul>\n<li><p>Open issues about things you don\u2019t understand.<\/p><\/li>\n<li><p>If you see an error in the documentation, open a pull request to fix it.<\/p><\/li>\n<li><p>Volunteer to proofread or edit as new materials are produced. Yes, seriously: proofreading is <em>incredibly<\/em> valuable.<\/p><\/li>\n<li><p>Volunteer to write documentation of things you <em>do<\/em> understand where you see gaps.<\/p><\/li>\n<\/ul>\n<\/section>\n<section id=\"framework-internals\" class=\"level3\">\n<h3>Framework internals<\/h3>\n<p>Every time I have started poking into Ember\u2019s own codebase\u2014to ship a fix for some small bug, or simply to understand the behavior of my own application\u2014I have found myself stymied by a really serious issue. <em>Almost nothing is documented.<\/em> This is true of Ember proper, of Ember Data, of Ember <abbr>CLI<\/abbr>, of Broccoli\u2019s internals\u2026 Everything I named above as being in need of <em>user<\/em>-facing documentation also desperately needs <em>developer<\/em>-facing documentation.<\/p>\n<p>A lot of this happens naturally in projects developed organically by small teams. I\u2019ve seen it in my own current job: the <em>vast<\/em> majority of our codebase is without any formal documentation, because it didn\u2019t <em>require<\/em> it when we were a much smaller organization working on a much smaller codebase. But no project\u2014whether private or open-source\u2014can grow or thrive unless it becomes possible for new contributors to come in, understand the system as it exists, and start making changes effectively. \u201cTribal knowledge\u201d is <em>not<\/em> a bad thing in some contexts, but it does not scale.<\/p>\n<p>The Ember.js ecosystem needs developer documentation of several sorts, then:<\/p>\n<ul>\n<li><p><strong>Architecture documents:<\/strong> what are the pieces of the framework or library in question, and how do they fit together? This is often the hardest piece to maintain, simply because it changes organically over time, and unlike the next couple examples it doesn\u2019t have an inherent attachment to the code. However, it\u2019s also the piece that\u2019s absolutely the most important, because it\u2019s what gives anyone trying to dive in and contribute the orientation they need to be effective.<\/p><\/li>\n<li><p><strong>\u201cWhy\u201d comments:<\/strong> The internals of the core libraries very often have good reasons for doing things even in apparently odd ways. However, the reasons for those are <em>very<\/em> rarely written down anywhere. This is <em>precisely<\/em> what comments are for! If some implementation actually <em>can\u2019t<\/em> be simplified in the way it looks like it can, write it down right there in a comment! This will save both you and other developers lots of wasted time with false starts and useless pull requests and so on.<\/p><\/li>\n<li><p><strong>Documentation of private <abbr>API<\/abbr>:<\/strong> Much of the public-facing <abbr>API<\/abbr> for Ember is fairly clear (modulo caveats around completeness and accuracy). However, most internal <abbr>API<\/abbr> is essentially entirely undocumented. This makes it <em>extremely<\/em> difficult for someone to know how to use the internal <abbr>API<\/abbr>s when working on internal code!<\/p><\/li>\n<\/ul>\n<p>All of these things came home to me pretty sharply as I started poking at the Glimmer VM project to see where and how I can pull together my knowledge of both TypeScript and Rust to drive some of those efforts forward. The core team folks I\u2019ve interacted with have all been <em>extremely<\/em> helpful\u2014and that\u2019s always been true all along the way!\u2014but they\u2019re also busy, and taking the time to write down something <em>once<\/em> ends up being a major \u201cforce multiplier\u201d. You can explain the same thing to multiple different people via multiple different conversations, or you can write it down <em>once<\/em> and make it a resource that anyone can use to start working effectively in the system!<\/p>\n<p><strong>How you can help:<\/strong><\/p>\n<ul>\n<li><p>If you\u2019re a current Ember developer in any part of the ecosystem: <em>start writing down what you know.<\/em> If a question comes up more than once, put it in a document somewhere. If nothing else, then you can link to it instead of typing it up one more time in Slack!<\/p><\/li>\n<li><p>If you\u2019re just getting started on developing core Ember functionality: <em>write down what you learn.<\/em> If you\u2019re working through some section of the codebase, don\u2019t understand it, and then come to understand it by way of asking questions, add documentation for that! You\u2019ll help the next person coming along behind you!<\/p><\/li>\n<\/ul>\n<hr \/>\n<p>In short: please write more things down! We need user-facing and developer-facing documentation; they need to be different and distinct from each other; and we need the whole range in both. That\u2019s an <em>enormous<\/em> amount of work, and it\u2019s very different from programming (and therefore harder for many of us).<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> But it\u2019s also work that will pay equally enormous dividends in enabling the Ember community to grow in both the <em>number<\/em> and the <em>effectiveness<\/em> of its contributors\u2014and that\u2019s something we very much need!<\/p>\n<\/section>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>Most of Webpack\u2019s bad reputation is long-since undeserved: it <em>was<\/em> poorly documented\u2026 a few years ago. So was Ember!<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>I\u2019ll let you draw your own conclusions about my own relationship to writing given the absurd number of words I put out on this site.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Fri, 18 May 2018 22:00:00 -0400","guid":"tag:v4.chriskrycho.com,2018-05-18:\/2018\/emberjs2018-part-2.html","category":["emberjs","javascript","typescript","emberjs2018"]},{"title":"#EmberJS2018, Part 1","link":"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-1.html","description":"<p>Following <a href=\"https:\/\/blog.rust-lang.org\/2018\/01\/03\/new-years-rust-a-call-for-community-blogposts.html\">the example<\/a> of the Rust community, the <a href=\"https:\/\/emberjs.com\">Ember.js<\/a> team has <a href=\"https:\/\/emberjs.com\/blog\/2018\/05\/02\/ember-2018-roadmap-call-for-posts.html\" title=\"Ember&#39;s 2018 Roadmap: A Call for Blog Posts\">called for blog posts<\/a> as the first step in setting the 2018 roadmap (which will formally happen through the normal <a href=\"https:\/\/github.com\/emberjs\/rfcs\"><abbr title=\"Request for Comments\">RFC<\/abbr> process<\/a>). This is my contribution.<\/p>\n<p>There are three major themes I think should characterize the Ember.js community and project for the rest of 2018:<\/p>\n<ol type=\"1\">\n<li><strong>Finishing What We\u2019ve Started<\/strong> (this post)<\/li>\n<li><a href=\"https:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-2.html\"><strong>Doubling Down on Docs<\/strong><\/a><\/li>\n<li><a href=\"http:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-3.html\"><strong>Defaulting to Public for Discussions<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/v4.chriskrycho.com\/2018\/emberjs2018-part-4.html\"><strong>Embracing the Ecosystem<\/strong><\/a><\/li>\n<\/ol>\n<hr \/>\n<section id=\"finishing-what-weve-started\" class=\"level2\">\n<h2>Finishing What We\u2019ve Started<\/h2>\n<p>What I want, more than any new feature anyone could come up with, is for this to be the year Ember.js commits to <em>finishing what we have started<\/em>. The last few years have seen the Ember team do a lot of really important exploratory work, including projects like <a href=\"https:\/\/glimmerjs.com\">Glimmer.js<\/a>; and we have landed some of the initiatives we have started. But I think it\u2019s fair to say that focus has not been our strong suit. It\u2019s time for a year of <em>shipping<\/em>.<\/p>\n<p>We need to land all the things we have in flight, and as much as possible avoid the temptation (much though I feel it myself!) to go haring off after interesting new ideas. As such, literally everything I list below is an effort <em>already in progress<\/em>. It\u2019s just a matter of making concerted efforts as a community to land them.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p>\n<p>And that way of putting it is important: we have to make concerted efforts <em>as a community<\/em> to land these things. Very, very few people are paid to work on Ember.js full time\u2014far too few to accomplish all of this! If these things matter to you and your company, find a way to carve out time for it. Even if it\u2019s just a few hours a week, even if it\u2019s \u201cjust\u201d (and there\u2019s no \u201cjust\u201d about these!) helping out with triage of open issues or answering questions in Slack or Discourse or Stack Overflow, even if it doesn\u2019t <em>feel<\/em> like a lot\u2026 it adds up.<\/p>\n<p>To be very clear, before I go any further: none of this is a knock on everything that the Ember core team and community have done in the last couple years. A lot of things that have landed along the way\u2014dropping in the Glimmer rendering engine midway through the 2.x series, landing ES5 getters just weeks ago in Ember 3.1, and so on\u2014are genuinely great! <em>All<\/em> that I mean is, a year where we land and polish everything would make everything that much more awesome (and make Ember that much more competitive a choice in the client-side framework world).<\/p>\n<p>So: what do we need to ship this year?<\/p>\n<section id=\"land-glimmer-components-in-ember.js-proper\" class=\"level3\">\n<h3>Land Glimmer <code>&lt;Component&gt;<\/code>s in Ember.js proper<\/h3>\n<p>We\u2019ve taken the first steps toward this already via a number of <abbr title=\"Request for Comments\">RFC<\/abbr>s that were written late last year and merged since. We need to finish the implementation for these. That means getting the <a href=\"https:\/\/github.com\/emberjs\/ember.js\/issues\/16301\">Glimmer Components in Ember<\/a> quest across the finish line.<\/p>\n<p>The whole story here will make Ember <em>feel<\/em> much more modern in a variety of ways, as well as enabling some great performance and programming model wins: Immutable component arguments! Auto-tracked class properties! <code>&lt;AngleBracketComponent&gt;<\/code> invocation! Clear semantic distinctions between arguments and local context! So many good things. We just need to land it! <a href=\"https:\/\/github.com\/emberjs\/ember.js\/issues\/16301\">The quest<\/a> needs to be moving forward, not stagnant.<\/p>\n<p><strong>How you can help:<\/strong><\/p>\n<ul>\n<li>Show up and volunteer to go after pieces of the quest. There are people willing to mentor you through the work that needs to be done!<\/li>\n<li>Test it as it lands! You don\u2019t have to commit to <em>shipping<\/em> things in your app to <em>test<\/em> them in your app.<\/li>\n<\/ul>\n<\/section>\n<section id=\"land-a-lot-of-ember-cli-efforts\" class=\"level3\">\n<h3>Land a <em>lot<\/em> of Ember CLI efforts<\/h3>\n<p>There are a great many Ember CLI efforts in flight. Every last one of them should be on stable and in use before the end of the year.<\/p>\n<section id=\"module-unification\" class=\"level4\">\n<h4>Module Unification<\/h4>\n<p>The <a href=\"https:\/\/github.com\/dgeb\/rfcs\/blob\/module-unification\/text\/0000-module-unification.md\">Module Unification <abbr title=\"Request for Comments\">RFC<\/abbr><\/a> was opened in May 2016 and merged October 2016. There has been a lot of progress made, but we need to <em>ship it<\/em>\u2014from where I stand, it\u2019d be nice if it landed less than 2 years after we approved it! And we\u2019re <a href=\"https:\/\/github.com\/emberjs\/ember.js\/issues\/16373\">getting pretty close<\/a>; you can actually use the Module Unification blueprint in an Ember application today. Some stuff doesn\u2019t work <em>quite<\/em> right yet, but it\u2019s getting close.<\/p>\n<p><strong>How you can help:<\/strong> try it out! Spin up new apps with the module unification blueprint flag, and try running the migrator codemod, and report back on what breaks.<\/p>\n<\/section>\n<section id=\"broccoli-1.0\" class=\"level4\">\n<h4>Broccoli 1.0<\/h4>\n<p>We\u2019re <em>super<\/em> close on this one\u2014Oli Griffiths has done some heroic work on this since EmberConf\u2014but we need to finish it. Ember CLI, for historical reasons, has been using a fork of Broccoli.js for quite some time. This divergence has caused all manner of trouble, including compatibility issues between Broccoli plugins and an inability to take advantage of the best things that have landed in Broccoli since the fork happened.<\/p>\n<p>Perhaps the single most important example of that is that Broccoli 1.0 supports the use of the system <code>tmp<\/code> directory. That single change will improve the performance of Ember CLI <em>dramatically<\/em>, especially on Windows. It will also flat-out eliminate a number of bugs and odd behaviors that appear when trying to integrate Ember CLI with other file watching tools (e.g.\u00a0TypeScript\u2019s <code>--watch<\/code> invocation).<\/p>\n<p><strong>How you can help:<\/strong> once the Ember CLI team says it\u2019s ready for testing, test your app and addons with it! Make sure that everything works as it should\u2014specifically, that you\u2019re not making any assumptions that depend on either the forked <abbr>API<\/abbr> or the location of the <code>tmp<\/code> directory used for intermediate build steps.<\/p>\n<\/section>\n<section id=\"the-new-packager-setup-with-tree-shaking-and-app-splitting\" class=\"level4\">\n<h4>The new <code>Packager<\/code> setup, with tree-shaking and app-splitting<\/h4>\n<p>One of the current major pain points with Ember\u2019s build pipeline is that it\u2019s hard to extend, and not really documented at all. (I\u2019ll have a <em>lot<\/em> more to say on the question of documentation in the next post!) However, work is in progress to change that, too!<\/p>\n<p>The accepted-and-actively-being-worked-on <a href=\"https:\/\/github.com\/ember-cli\/rfcs\/blob\/master\/active\/0051-packaging.md\">Packaging Ember CLI <abbr title=\"Request for Comments\">RFC<\/abbr><\/a> aims to fix both of these. Quoting from it:<\/p>\n<blockquote>\n<p>The current application build process merges and concatenates input broccoli trees. This behaviour is not well documented and is a tribal knowledge. While the simplicity of this approach is nice, it doesn\u2019t allow for extension. We can refactor our build process and provide more flexibility when desired.<\/p>\n<\/blockquote>\n<p>A few of the things we can expect to be possible once that effort lands:<\/p>\n<ul>\n<li>tree-shaking \u2013 we can lean on Rollup.js to get <em>only<\/em> the code we actually need, cutting shipped file size dramatically<\/li>\n<li>app-splitting \u2013\u00a0lots of different strategies to explore, including route-based or \u201csection\u201d-based, etc.<\/li>\n<li>static-build-asset-splitting \u2013\u00a0no reason to cache-bust your <em>dependencies<\/em> every time the app releases!<\/li>\n<li>distinct app builds \u2013 you could ship one build of your app for browsers which support ES Modules and one for browsers which don\u2019t (heeeeey, IE11) \u2013 letting you minimize the payload size for the ones that do<\/li>\n<\/ul>\n<p><strong>How you can help:<\/strong><\/p>\n<ul>\n<li>If you know Ember CLI internals: pop into #-dev-ember-cli and ask how you can help land the features<\/li>\n<li>If you don\u2019t know Ember CLI internals: also pop into #-dev-ember-cli, but ask instead how you can <em>test<\/em> the changes<\/li>\n<li>Help document those internals (see the next post in this series)<\/li>\n<\/ul>\n<\/section>\n<\/section>\n<section id=\"install-your-way-to-ember\" class=\"level3\">\n<h3>Install-your-way-to-Ember<\/h3>\n<p>We need to finish splitting apart the Ember source from its current state of still being fairly monolith and get it turned into a true set of packages. The new Modules API which landed last year was a huge step toward this and made the experience on the developer side <em>look<\/em> like this should be possible\u2014but that\u2019s still a shim around the actual non-modularized Ember core code. The process of splitting it apart <em>is happening<\/em>, but we need to finish it.<\/p>\n<p>The promise here is huge: Ember will be able to be the kind of thing you can progressively add to your existing applications and slowly convert them, rather than something that comes along all as a large bundle. It\u2019s technically possible to do this today, but you cannot drop in <em>just the view layer<\/em>, for example, and that\u2019s a huge value for people who want to try out the programming model or add it for just one feature in an existing application.<\/p>\n<p>Making it possible for people to install Glimmer components, then the service layer, then the router, and so on as they need it will make adoption easier for people who are curious about the framework. But it will also be a huge boon to those of us already using Ember and wanting to migrate existing applications (often a tangled mix of server-side rendering and massive jQuery spaghetti files!) to Ember progressively. I\u2019ve had multiple scenarios come up at my own job in just the last month where this would have been hugely useful.<\/p>\n<p><strong>How you can help:<\/strong> make it known that you\u2019re willing to help work on breaking apart Ember into its constituent pieces, and as that effort lands (hopefully over the rest of this year!) test it in your own apps and addons, and find the pain points in the install-your-way-to-the-framework process.<\/p>\n<\/section>\n<section id=\"make-typescript-great-everywhere\" class=\"level3\">\n<h3>Make TypeScript <em>great<\/em> everywhere<\/h3>\n<p>This one is near and dear to my heart\u2026 and it also really falls in no small part to me and the rest of the group working on ember-cli-typescript and type definitions for the Ember ecosystem!<\/p>\n<p>There are two big wins we can land this year:<\/p>\n<ol type=\"1\">\n<li>Built-in support in Ember.js itself.<\/li>\n<li>Solid type definitions for the rest of the Ember.js ecosystem<\/li>\n<\/ol>\n<p>If you don\u2019t like TypeScript, don\u2019t panic! The upshot here will actually be a better experience for <em>all<\/em> users of Ember.js.<\/p>\n<section id=\"built-in-support-in-ember.js-itself\" class=\"level4\">\n<h4>1. Built-in support in Ember.js itself<\/h4>\n<p>One of my goals for this summer<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> is to finish an <abbr title=\"Request for Comments\">RFC<\/abbr> making TypeScript a first-class citizen of the Ember.js ecosystem. To clarify what this will and won\u2019t entail (assuming it\u2019s accepted, assuming I ever manage to finish writing it!):<\/p>\n<ul>\n<li><p>Ember will <em>always<\/em> be JS-first, and it will <em>never<\/em> require type metadata reflected to runtime, unlike e.g.\u00a0Angular. No one will ever have a <em>worse<\/em> experience because they prefer JS to TS. The idea will be to make TypeScript an <em>equally<\/em> good experience, and to include it for consideration when thinking about design choices for new features.<\/p><\/li>\n<li><p>Ember users, both JS and TS, will get the <em>benefits<\/em> of having good types available right out of the box: many editors and IDEs can use TypeScript type definitions to enable better docs, autocompletion, etc.\u2014and we may even be able to leverage it for <a href=\"https:\/\/twitter.com\/__dfreeman\/status\/994410180661170177\">better validation of Handlebars templates<\/a>!<\/p><\/li>\n<li><p>We\u2019ll have (because we\u2019ll have to have!) a story on what we support in terms of backwards compatibility and SemVer for TypeScript and Ember and the type definitions. Necessarily, it has been the Wild West for the first year of concentrated effort here, trying to get our type definitions from \u201cbarely exist and not useful\u201d to \u201cfull coverage and 99% right.\u201d But as TypeScript becomes more widely used, we have to have a stability story, and we very soon will.<\/p><\/li>\n<\/ul>\n<p>There\u2019s also ongoing work to convert Ember\u2019s own internals to TypeScript, and landing that will help guarantee that the type definitions for Ember are actually <em>correct<\/em>, which in turn will make the experience for everyone better. (Bad type definitions are worse than <em>no<\/em> type definitions!)<\/p>\n<p><strong>How you can help:<\/strong> engage in the <abbr title=\"Request for Comments\">RFC<\/abbr> process once we get it started, and if you are up for it show up to help convert the Ember internals to TypeScript as well.<\/p>\n<\/section>\n<section id=\"solid-type-definitions-for-the-rest-of-the-ember.js-ecosystem\" class=\"level4\">\n<h4>2. Solid type definitions for the rest of the Ember.js ecosystem<\/h4>\n<p>Closely related to making TypeScript a first-class citizen for Ember.js itself is getting the pieces in place for the rest of the ecosystem as well. That means we need type definitions for addons\u2014a <em>lot<\/em> of them! The ember-cli-typescript team will (hopefully late this month or in early June) be launching a quest issue to get type definitions for the whole Ember ecosystem in place\u2014by helping convert addons to TS if their authors desire it, or by adding type definitions to the addons if they\u2019re up for it, or by getting them up on DefinitelyTyped if they\u2019re totally disinterested. (And, as I\u2019ll note again in that quest issue, it\u2019s totally fine for people <em>not<\/em> to be interested: there <em>is<\/em> a maintenance burden there!) The goal, again, is that when you\u2019re using <em>any<\/em> part of the Ember ecosystem it\u2019ll be easy to get all the benefits of TypeScript\u2014and indeed that in many cases you\u2019ll get a fair number of those benefits as a JS user.<\/p>\n<p><strong>How you can help:<\/strong> participate in the quest issue once it\u2019s live! We\u2019ll help mentor you through the process of converting addons to TypeScript, writing type definitions and getting them well-validated, and so on!<\/p>\n<hr \/>\n<p>That\u2019s a lot to do. More than enough all by itself, and a lot of moving parts. As such, I\u2019ll reiterate what I said at the start: we don\u2019t need new features this year. <strong>It\u2019s time for a year of <em>shipping<\/em>.<\/strong><\/p>\n<\/section>\n<\/section>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>To put it in the terms the Rust community used for their similar push at the end of 2017, and which we have often used to describe the ongoing efforts in Rust to land the \u201cRust 2018 edition\u201d: this is an \u201cimpl period\u201d\u2014a play on the Rust <code>impl<\/code> keyword, used to describe the <em>implementation<\/em> of the behavior associated with a given data type. You can think of this as the same: it\u2019s the implementation of the good ideas we have.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>Confession: it was a goal for the spring but I found myself utterly exhausted after EmberConf\u2026 and had a full month with <em>another<\/em> major talk given for internal purposes afterwards. I\u2019m worn out.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Fri, 11 May 2018 09:30:00 -0400","guid":"tag:v4.chriskrycho.com,2018-05-11:\/2018\/emberjs2018-part-1.html","category":["emberjs","javascript","typescript","emberjs2018"]},{"title":"Announcing ember-cli-typescript 1.1.0","link":"http:\/\/v4.chriskrycho.com\/2018\/announcing-ember-cli-typescript-110.html","description":"<p>I\u2019m delighted to announce the release of <a href=\"https:\/\/github.com\/typed-ember\/ember-cli-typescript\/releases\/tag\/v1.1.0\">ember-cli-typescript 1.1.0<\/a>. This first minor release since 1.0 includes the following shiny and awesome new features:<\/p>\n<ul>\n<li><a href=\"#generators\">Generators<\/a><\/li>\n<li><a href=\"#developing-addons\">Support for developing addons in TypeScript<\/a><\/li>\n<li><a href=\"#incremental-compilation\">Incremental compilation (a.k.a. fast rebuilds in <code>ember serve<\/code> mode)<\/a><\/li>\n<\/ul>\n<section id=\"generators\" class=\"level2\">\n<h2>Generators<\/h2>\n<p>We\u2019ve now added support for generating <em>all<\/em> standard Ember items as TypeScript files instead of JavaScript files. So now when you run <code>ember generate component user-profile<\/code> for example, you\u2019ll get <code>user-profile.ts<\/code>, <code>user-profile-test.ts<\/code>, and <code>user-profile.hbs<\/code>. For most files, this is just a nicety\u2014just two files you don\u2019t have to rename!\u2014but in the case of services, controllers, and Ember Data models, adapters, and serializers it will actually make a really big difference in your experience of using TypeScript in your app or addon.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p>\n<p>Those generators are <em>mostly<\/em> identical with ones in Ember and Ember Data, just with <code>.ts<\/code> instead of <code>.js<\/code> for the extension. The only changes we have made are: (a) we\u2019ve tweaked them to use classes where possible, and (b) we have customized the controller, service, and Ember Data model, adapter, and serializer generators so you get the most mileage out of TypeScript for the least effort we can manage today. So when you do <code>ember generate service session<\/code>, this is what you\u2019ll see:<\/p>\n<pre class=\"ts\"><code>import Service from &quot;@ember\/service&quot;;\n\nexport default class Session extends Service.extend({\n  \/\/ anything which *must* be merged on the prototype\n}) {\n  \/\/ normal class definition\n}\n\n\/\/ DO NOT DELETE: this is how TypeScript knows how to look up your services.\ndeclare module &quot;ember&quot; {\n  interface ServiceRegistry {\n    session: Session;\n  }\n}<\/code><\/pre>\n<p>Courtesy of these generators, you can now write <em>almost<\/em> exactly what you\u2019d write in vanilla Ember and get full support for autocompletion of properties and methods on the <code>Session<\/code> service, as well as type-checking for how you use those. Service and controller injections just require you to explicitly name the service or controller being injected:<\/p>\n<pre class=\"ts\"><code>import Component from &quot;@ember\/component&quot;;\nimport { inject as service } from &quot;@ember\/service&quot;;\n\nexport default class UserProfile extends Component {\n  session = service(&quot;session&quot;);\n  \/\/ note the string ^ naming the service explicitly\n}<\/code><\/pre>\n<p>So, for example, if your <code>session<\/code> service had a <code>login<\/code> method on it:<\/p>\n<pre class=\"ts\"><code>import Service from &quot;@ember\/service&quot;;\nimport RSVP from &quot;rsvp&quot;;\n\nexport default class Session extends Service {\n  login(email: string, password: string): RSVP.Promise&lt;string&gt; {\n    \/\/ some API call to log in\n  }\n}\n\n\/\/ DO NOT DELETE: this is how TypeScript knows how to look up your services.\ndeclare module &quot;ember&quot; {\n  interface ServiceRegistry {\n    session: Session;\n  }\n}<\/code><\/pre>\n<p>Then anywhere you injected and used it, you\u2019ll get auto-complete suggestions and type checking:<\/p>\n<figure>\n<img src=\"https:\/\/f001.backblazeb2.com\/file\/chriskrycho-com\/images\/ts-autocomplete.png\" alt=\"autocompletion\" \/><figcaption>autocompletion<\/figcaption>\n<\/figure>\n<figure>\n<img src=\"https:\/\/f001.backblazeb2.com\/file\/chriskrycho-com\/images\/ts-type-checking.png\" alt=\"type-checking\" \/><figcaption>type-checking<\/figcaption>\n<\/figure>\n<p>(You\u2019ll see the same kinds of things in other editors, from Vim to IntelliJ IDEA. Visual Studio Code is just my current editor of choice.)<\/p>\n<\/section>\n<section id=\"addon-development\" class=\"level2\">\n<h2>Addon development<\/h2>\n<p>As <a href=\"http:\/\/v4.chriskrycho.com\/2017\/announcing-ember-cli-typescript-100.html#the-roadmap\">promised with the 1.0 release<\/a>, 1.1 (though arriving much later than I hoped it would) includes support for developing addons with TypeScript.<\/p>\n<p>Strictly speaking, of course, you could <em>always<\/em> develop addons using TypeScript, but there were two problems with it: (1) dependency management and (2) manual work required to deal with the dependency management problems.<\/p>\n<section id=\"dependency-management\" class=\"level3\">\n<h3>1. Dependency management<\/h3>\n<p>In the normal Ember CLI workflow, TypeScript had to be a <code>dependency<\/code>\u2014not a <code>devDependency<\/code>\u2014of the addon, because the normal pattern with Ember CLI is to ship the uncompiled files and have the consumer compile them all together at build time.<\/p>\n<p>This makes a certain amount of sense for Babel given the Ember community\u2019s shared reliance on Babel: it\u2019s just assumed to be part of every app build. In that case, it gives consumers control over their compilation target. If an app only needs to target evergreen browsers, it can do that and ship a smaller payload, because an addon won\u2019t have pre-compiled in things like generator support, etc.<\/p>\n<p>In the case of TypeScript, however, this makes a lot less sense: many (probably <em>most<\/em>) consumers of addons written in TypeScript will still be normal JavaScript consumers. We did not want to burden normal consumers with a TypeScript compile step. We <em>also<\/em> didn\u2019t want to burden any consumers with the reality that TypeScript is a <em>large<\/em> install. TypeScript 2.6.2 is 32MB on disk for me. Even with some degree of deduplication by npm or yarn, if addons used a variety of versions of TypeScript for development\u2014as they surely would!\u2014the install cost for consumers would quickly spiral into a nasty spot. And again: that\u2019s bad enough for someone who <em>wants<\/em> to use TypeScript in their app; it\u2019s far worse for someone who just wants to consume the compiled JavaScript.<\/p>\n<\/section>\n<section id=\"manual-workarounds\" class=\"level3\">\n<h3>2. Manual workarounds<\/h3>\n<p>You could work around all of that by building the JavaScript (and TypeScript definitions) yourself. But as part of that, you had to do all the work of making sure both the JavaScript files and the type definitions you generated ended up in the right place for distribution and consumption. That was always possible, but it was also always going to be a lot of work. In practice, as far as I know, <em>no one has done this<\/em>.<\/p>\n<\/section>\n<section id=\"solution\" class=\"level3\">\n<h3>Solution<\/h3>\n<p>We now support TypeScript as a <code>devDependency<\/code> and also manage the work of generating JavaScript and type definitions for you. All you have to do is install ember-cli-typescript into an addon, and then when you do your build step, we\u2019ll automatically do the work (on prepublish) of generating TypeScript <code>.d.ts<\/code> files and JavaScript source for you.<\/p>\n<p>Consumers of your addon, therefore, will (a) not know or care that the addon is written in TypeScript if they just want to consume it as normal JavaScript<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> or (b) will get the benefits of your having written the library in TypeScript without paying the penalty of having to have multiple versions of the TypeScript compiler downloaded to their own app.<\/p>\n<p>One important caveat: we do <em>not<\/em> support TypeScript in an addon\u2019s <code>app<\/code> directory. However, for most addons, we don\u2019t think this should be a problem. It\u2019s rare for addons to put actual implementation in the <code>app<\/code> directory; instead it has simply become conventional for the <code>app<\/code> directory simply to have re-exports for convenient access to the functionality supplied by the addon.<\/p>\n<p>Also note that you can supply type definitions for your addon <em>without<\/em> developing the addon itself in TypeScript.<a href=\"#fn3\" class=\"footnote-ref\" id=\"fnref3\" role=\"doc-noteref\"><sup>3<\/sup><\/a> You do <em>not<\/em> need ember-cli-typescript installed for that. You only need the addon if you actually want to take advantage of the opportunities TypeScript affords for developing your own addon.<\/p>\n<\/section>\n<\/section>\n<section id=\"incremental-compilation\" class=\"level2\">\n<h2>Incremental compilation<\/h2>\n<p>Last but not least, we\u2019ve managed\u2014mostly through the hard work of both Dan Freeman (<a href=\"https:\/\/github.com\/dfreeman\">@dfreeman<\/a>) and Derek Wickern (<a href=\"https:\/\/github.com\/dwickern\">@dwickern<\/a>\u2014to get support for TypeScript\u2019s <code>--watch<\/code> mode integrated.<a href=\"#fn4\" class=\"footnote-ref\" id=\"fnref4\" role=\"doc-noteref\"><sup>4<\/sup><\/a> What this means in practice is: <em>way<\/em> faster iteration as you work.<\/p>\n<p>Previously, every time you triggered <em>any<\/em> change in your app (even if it didn\u2019t involve any TypeScript files at all), the TypeScript compiler would recompile <em>all<\/em> the TypeScript files in your application. We didn\u2019t initially have a good way to make TypeScript and Broccoli (and therefore Ember CLI) communicate clearly about what had changed. Now, courtesy of Dan and Derek\u2019s hard work (and my cheerleading, testing, and fixing a few corner pieces along the way), we do! So when you change a <code>.hbs<\/code> file or a <code>.js<\/code> file\u2026 the TypeScript compiler won\u2019t do anything. And when you change a TypeScript file, the TypeScript compiler will <em>only<\/em> recompile that file.<\/p>\n<p>On my own app (~35,000 lines of TypeScript across ~700 files), that\u2019s the difference between rebuilds involving TypeScript taking 15\u201320 seconds and their taking 1\u20132 seconds. Literally an order of magnitude faster! Over the course of a day of development, that saves a <em>huge<\/em> amount of time.<\/p>\n<p>The way we did it also solved an incredibly annoying problem we had in the previous pass: <em>any<\/em> change to your app was triggering <code>tsc<\/code> to rebuild the entire TypeScript tree of your app, even if you didn\u2019t so much as look at <code>.ts<\/code> file. This was particularly annoying when combined with the long rebuild times: change a CSS file and wait for your TypeScript files to rebuild? Ugh. But not anymore!<\/p>\n<\/section>\n<section id=\"credit-and-thanks\" class=\"level2\">\n<h2>Credit and Thanks<\/h2>\n<p>Massive credit goes to Dan Freeman (<a href=\"https:\/\/github.com\/dfreeman\">@dfreeman<\/a>) and Derek Wickern (<a href=\"https:\/\/github.com\/dwickern\">@dwickern<\/a>), who did most of the heavy lifting on the internals for this release, and together unlocked both incremental compilation and addon support. Derek also did the lion\u2019s share of the work on writing the types for Ember and Ember Data.<\/p>\n<p>Thanks to Maarten Veenstra (<a href=\"https:\/\/github.com\/maerten\">@maerten<\/a>) for the original inspiration (and a spike last summer) for using a type registry, and to Mike North (<a href=\"https:\/\/github.com\/maerten\">@mike-north<\/a>) for some discussion and planning around the idea late in 2017. I may have implemented them, but the ideas came from the community!<\/p>\n<p>Thanks to Frank Tan (<a href=\"https:\/\/github.com\/tansongyang\">@tansongyang<\/a>) for doing a lot of the work on porting the generators from the Ember and Ember Data repositories to ember-cli-typescript, as well as converting them to TypeScript and to use the new formats. He also contributed the type definitions for the new (<a href=\"https:\/\/github.com\/emberjs\/rfcs\/pull\/232\/\">RFC #232<\/a>) QUnit testing API.<\/p>\n<p>Thanks to everyone who contributed to ember-cli-typescript or the Ember typings in any way since we released 1.0.0:<\/p>\n<ul>\n<li><p>ember-cli-typescript contributors (note that I intentionally include here everyone who opened issues on the repository: that is <em>not<\/em> a small thing and has helped us immensely):<\/p>\n<ul>\n<li>Bryan Crotaz (<a href=\"https:\/\/github.com\/BryanCrotaz\">@BryanCrotaz<\/a>)<\/li>\n<li>Daniel Gratzl (<a href=\"https:\/\/github.com\/danielgratzl\">@danielgratzl<\/a>)<\/li>\n<li>Guangda Zhang (<a href=\"https:\/\/github.com\/inkless\">@inkless<\/a>)<\/li>\n<li><a href=\"https:\/\/github.com\/guangda-prosperworks\">@guangda-prosperworks<\/a><\/li>\n<li>Krati Ahuja (<a href=\"https:\/\/github.com\/kratiahuja\">@kratiahuja<\/a>)<\/li>\n<li>Martin Feckie (<a href=\"https:\/\/github.com\/mfeckie\">@mfeckie<\/a>)<\/li>\n<li>Nikos Katsikanis (<a href=\"https:\/\/github.com\/QuantumInformation\">@QuantumInformation<\/a>)<\/li>\n<li>Per Lundberg (<a href=\"https:\/\/github.com\/perlun\">@perlun<\/a>)<\/li>\n<li>Prabhakar Poudel (<a href=\"https:\/\/github.com\/prabhakar-poudel\">@Prabhakar-Poudel<\/a>)<\/li>\n<li>Ryan LaBouve (<a href=\"https:\/\/github.com\/ryanlabouve\">@ryanlabouve<\/a>)<\/li>\n<li>Simon Ihmig (<a href=\"https:\/\/github.com\/simonihmig\">@simonihmig<\/a>)<\/li>\n<li>Theron Cross (<a href=\"https:\/\/github.com\/theroncross\">@theroncross<\/a>)<\/li>\n<li>Thomas Gossman (<a href=\"https:\/\/github.com\/gossi\">@gossi<\/a>)<\/li>\n<li>Vince Cipriani (<a href=\"https:\/\/github.com\/vcipriani\">@vcipriani<\/a>)<\/li>\n<\/ul><\/li>\n<li><p>Ember typings contributors:<\/p>\n<ul>\n<li>Adnan Chowdhury (<a href=\"https:\/\/github.com\/bttf\">@bttf<\/a>)<\/li>\n<li>Derek Wickern (<a href=\"https:\/\/github.com\/dwickern\">@dwickern<\/a>)<\/li>\n<li>Frank Tan (<a href=\"https:\/\/github.com\/tansongyang\">@tansongyang<\/a>)<\/li>\n<li>Guangda Zhang (<a href=\"https:\/\/github.com\/inkless\">@inkless<\/a>)<\/li>\n<li>Ignacio Bona Piedrabuena (<a href=\"https:\/\/github.com\/igbopie\">@igbopie<\/a>)<\/li>\n<li>Leonard Thieu <a href=\"https:\/\/github.com\/leonard-thieu\">@leonard-thieu<\/a><\/li>\n<li>Logan Tegman <a href=\"https:\/\/github.com\/ltegman\">@ltegman<\/a><\/li>\n<li>Martin Feckie (<a href=\"https:\/\/github.com\/mfeckie\">@mfeckie<\/a>)<\/li>\n<li>Mike North (<a href=\"https:\/\/github.com\/maerten\">@mike-north<\/a>)<\/li>\n<li>Nathan Jacobson (<a href=\"https:\/\/github.com\/natecj\">@natecj<\/a>)<\/li>\n<li>Per Lundberg (<a href=\"https:\/\/github.com\/perlun\">@perlun<\/a>)<\/li>\n<li>Robin Ward (<a href=\"https:\/\/github.com\/eviltrout\">@eviltrout<\/a>)<\/li>\n<\/ul><\/li>\n<\/ul>\n<p>Thanks to Rob Jackson (<a href=\"https:\/\/github.com\/rwjblue\">@rwjblue<\/a>) and Tobias Bieniek (<a href=\"https:\/\/github.com\/Turbo87\">@Turbo87<\/a> on GitHub, @tbieniek in the Ember Slack) for answering tons of questions and putting up with regular pestering about Ember CLI.<\/p>\n<p>And last but not least, thanks to everyone who\u2019s popped into #topic-typescript on the Ember Community Slack with questions, comments, problem reports, and the occasional word of encouragement. It really does help.<\/p>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>For details on how this all works, see <a href=\"http:\/\/v4.chriskrycho.com\/2018\/typing-your-ember-update-part-4.html\">TypeScript and Ember.js Update: Part 4<\/a>, where I discuss these changes in detail.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>although they may actually get some benefits in a number of modern editors, since e.g.\u00a0VS Code and the JetBrains IDEs will leverage types if they exist!<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn3\" role=\"doc-endnote\"><p>More on that in a post to be released in the next couple weeks\u2014one I promised <em>long<\/em> ago, but which we\u2019re now in a place to actually do: a plan and a roadmap for typing the whole Ember ecosystem!<a href=\"#fnref3\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn4\" role=\"doc-endnote\"><p>And of course, right as we finally landed our support for it, by hacking around the <code>--watch<\/code> invocation in a lot of really weird ways, Microsoft shipped API-level support for it. We hope to switch to using that under the hood, but that shouldn\u2019t make any difference at all to you as a consumer of the addon, except that if\/when we land it at some point, you\u2019ll just have a nicer experience.<a href=\"#fnref4\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Mon, 12 Feb 2018 07:00:00 -0500","guid":"tag:v4.chriskrycho.com,2018-02-12:\/2018\/announcing-ember-cli-typescript-110.html","category":["emberjs","typescript","javascript","typing-your-ember"]},{"title":"I Want JSON Decoders","link":"http:\/\/v4.chriskrycho.com\/2017\/i-want-json-decoders.html","description":"<p><i class=editorial>This post was originally published at <a href=\"https:\/\/www.dailydrip.com\/blog\/i-want-json-decoders.html\">DailyDrip.com<\/a>. They\u2019re doing really great work over there, so I encourage you to check out their content and consider subscribing!<\/i><\/p>\n<hr\/>\n<p>The other day, I got a report about the Ember.js app I\u2019m working on: when a customer applied a coupon in the basket, they\u2019d see an indication that the coupon was applied, but the basket total would still display as if it hadn\u2019t been updated. Orders were <em>placed<\/em> correctly, but they wouldn\u2019t render right. I dug around for a bit, and then discovered that it was one of the (many) places where <code>undefined<\/code> was biting us.<\/p>\n<p>How did this happen? It turned out it was a perfect storm: a confusingly-designed <abbr>API<\/abbr> combined with a reasonable (but in this case, very unhelpful) assumption in our data layer. When the total on a given basket dropped to zero, our <abbr>API<\/abbr> simply didn\u2019t send back a value on the payload at all. Instead of <code>{ total: 0, ... }<\/code>, there was just, well, <code>{ ... }<\/code> \u2013\u00a0no <code>total<\/code> field at all. Meanwhile, our data layer was designed to let a server send back only the fields which <em>required<\/em> updating. That way, you can send back partial records to indicate only what has changed, instead of having to send back the whole of what might be a very large record, or a very large collection of records.<\/p>\n<p>The combination was terrible, though: because the server didn\u2019t send back the <code>total<\/code> field at all when it dropped to <code>0<\/code>, the client never updated the total it displayed to the user: as far as it was concerned, the server was saying \u201cno change here!\u201d<\/p>\n<p>The first and most obvious solution here, of course, is the one we implemented: we had the <abbr>API<\/abbr> always send back a value, even if that value was <code>0<\/code>. But it seems like there should be a better way.<\/p>\n<p>Lots of languages have fairly nice facilities for parsing JavaScript. Several languages even have tools for automatically constructing local, strongly-typed data structures from the structure of a <abbr>JSON<\/abbr> response on an <abbr>API<\/abbr>. F\u266f\u2019s <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/fsharp\/tutorials\/type-providers\/\">type providers<\/a> are like this and <em>really fancy<\/em> in the way they\u2019ll automatically derive the type for you so you don\u2019t even have to write it out as you would in everything from Haskell to C#. But for the most part in JavaScript, you have at most a way to map data to a local record in your data store \u2013\u00a0certainly none of those type safe guarantees. In TypeScript, you can write the types you receive out carefully \u2013 though, as I discovered in this case, probably not carefully <em>enough<\/em> unless you model <em>everything<\/em> as an optional field, and then you\u2019re back to checking for <code>null<\/code> or <code>undefined<\/code> everywhere, and <em>why isn\u2019t this already a solved problem?<\/em><\/p>\n<p>And it turns out, it <em>is<\/em> a solved problem \u2013 or at least, it is in Elm, <a href=\"https:\/\/guide.elm-lang.org\/interop\/json.html\">via<\/a> those <a href=\"https:\/\/guide.elm-lang.org\/interop\/json.html\"><abbr>JSON<\/abbr> Decoders<\/a>. I don\u2019t get to write Elm at work right now (or any time in the foreseeable future) \u2013 but if I can\u2019t write Elm, I can at least try to steal a bunch of its great ideas and push them back into my TypeScript.<\/p>\n<p>So\u2026 what exactly are <abbr>JSON<\/abbr> Decoders and how would they have solved this problem? (And why, if you\u2019re already familiar a little with Elm and possibly feeling frustrated with decoding, are they actually worth it?)<\/p>\n<p>A <abbr>JSON<\/abbr> Decoder is just a way of guaranteeing that once you\u2019re inside the boundary of your program, you <em>always<\/em> have a valid instance of the data type you\u2019ve decoded it into, <em>or<\/em> an error which tells you why you <em>don\u2019t<\/em> have a valid instance of the data. They\u2019re composable, so you can stack them together and take smaller decoders to build bigger ones, so if you have a complex <abbr>JSON<\/abbr> structure, you can define repeated substructures in it, or decoders for dissimilar sibling items in it, and use them to put together a grand decoder for your whole final structure. The decoders use the <a href=\"http:\/\/package.elm-lang.org\/packages\/elm-lang\/core\/5.1.1\/Result\"><code>Result<\/code><\/a> type, and they hand back either <code>Ok<\/code> with the decoded value or <code>Err<\/code> with the reason for the failure \u2013 and if <em>any<\/em> piece of a decoded type doesn\u2019t match with what you\u2019ve specified, you\u2019ll end up with an <code>Err<\/code>.<\/p>\n<p>Now, initially that might sound like a recipe for disaster \u2013 <abbr>JSON<\/abbr> payloads can be formed in weird ways all the time! \u2013 but in fact it encourages you to think through the various ways your payloads can be formed and to account for them. <em>Sometimes<\/em>, if the payload doesn\u2019t have what you expect, that really does mean something is wrong either in your request or in the server-side implementation. In that case, getting an <code>Err<\/code> is <em>exactly<\/em> what you want. Other times, the server might be perfectly legitimate in sending back a variety of shapes in its response, and your responsibility is to decide how to decode it to make sense in your app. Remember, the problem I had was that I received a payload which didn\u2019t have the data. With Elm\u2019s decoders, I would have had three choices:<\/p>\n<ol type=\"1\">\n<li>I could have treated this as an error, and passed that along to be dealt with in some way.<\/li>\n<li>I could have normalized it as a 0-value payload.<\/li>\n<li>I could have treated it <em>explicitly<\/em> as a no-op, maintaining whatever previous state I had in the data store, i.e.\u00a0the implicit behavior of my actual data store.<\/li>\n<\/ol>\n<p>What I <em>couldn\u2019t<\/em> do, though, is do any one of those <em>accidentally<\/em>. I could still support incomplete payloads (via option 3), but I\u2019d be explicitly opting into that, and there would be an obvious place where that was the case. This would be particularly helpful in a scenario where I wasn\u2019t also in charge of the <abbr>API<\/abbr>: if I couldn\u2019t just go change it so the <abbr>API<\/abbr> itself had a more sensible behavior, I could enforce whichever desired behavior on my own end. More than that, with something modeled on the Elm <abbr>JSON<\/abbr> Decoders, I would <em>have<\/em> to: there would be no implicit consumption of raw <abbr>JSON<\/abbr>.<\/p>\n<p>The first time I played with the Elm <abbr>JSON<\/abbr> Decoder approach, I thought it was a lot of work. I was used to just doing <code>JSON.parse()<\/code> in JS or <code>json.loads()<\/code> in Python. Now I needed to define a whole series of decode steps explicitly for every field in a response? Good grief! But it grew on me. More than that, I now actively miss it in my apps; I\u2019d have been really happy not to have to spend a morning hunting down this particular bug.<\/p>\n<p>Sometimes that explicitness can seem like quite a lot of boilerplate, and indeed it is: there\u2019s a reason the Elm <a href=\"https:\/\/github.com\/NoRedInk\/elm-decode-pipeline\">elm-decode-pipeline<\/a> project exists. But even given the <em>initial<\/em> nicety of something like F\u266f type providers, I think the Elm approach has a slight edge in the long-term for <em>maintainability<\/em> specifically. It\u2019s one thing to be able to just get to work right away and have a type definition you know to conform to a given <abbr>API<\/abbr> response. It\u2019s something else entirely to be able to <em>know<\/em> that you\u2019ve accounted for all the varieties of responses you might get (and without throwing an exception for failed <abbr>JSON<\/abbr> decoding at that!).<\/p>\n<p>Given all of this, I\u2019ve started mentally teasing out what such a <abbr>JSON<\/abbr> decoding library for Ember.js might look like in TypeScript. It\u2019s a long way off, but it\u2019s the kind of thing that I <em>really<\/em> want to experiment with, and that I think would make for a big win for the maintainability of our apps. Keep your eyes peeled, because I suspect this is another thing JS will steal from Elm, and that\u2019s <em>great<\/em> in my book.<\/p>\n","pubDate":"Mon, 25 Dec 2017 19:20:00 -0500","guid":"tag:v4.chriskrycho.com,2017-12-25:\/2017\/i-want-json-decoders.html","category":["JavaScript","Elm","TypeScript","web development","software development"]},{"title":"\u201cCollection-Last Auto-Curried Functions\u201d","link":"http:\/\/v4.chriskrycho.com\/2017\/collection-last-auto-curried-functions.html","description":"<p>I\u2019ve been using <a href=\"https:\/\/lodash.com\">lodash<\/a> for a while at work, and I love having it in our toolbox. But, as I increasingly embrace <em>composition of smaller functions<\/em> as a helpful approach to building up the final version of an overall transformation of some piece of data, I\u2019ve increasingly wanted to be using <a href=\"https:\/\/github.com\/lodash\/lodash\/wiki\/FP-Guide\">lodash-fp<\/a> instead\u2014those \u201cauto-curried\u2026 data-last methods\u201d are <em>nice<\/em>.<\/p>\n<p>I could belabor the difference with words, but a code sample will do better. Here\u2019s how I would write the same basic transformation in both Lodash and lodash-fp.<\/p>\n<pre class=\"javascript\"><code>\/\/ Lodash\nconst breakfasts = [&#39;pancakes&#39;, &#39;waffles&#39;, &#39;french toast&#39;]\n\nconst uniqueLetters = _.flow([\n  bs =&gt; _.map(bs, words),\n  _.flatten,\n  bs =&gt; _.map(bs, b =&gt; split(b, &#39;&#39;)),\n  _.flatten,\n  _.uniq,\n  ls =&gt; _.sortBy(ls, id),\n])\n\nconsole.log(uniqueLetters(breakfasts))<\/code><\/pre>\n<p>That gets the job done, but wouldn\u2019t it be nice if we didn\u2019t have to have all those anonymous functions (lambdas) throughout?<\/p>\n<pre class=\"javascript\"><code>\/\/ lodash-fp\nconst uniqueLettersFp = _.flow([\n  _.map(words),\n  _.flatten,\n  _.map(split(&#39;&#39;)),\n  _.flatten,\n  _.uniq,\n  _.sortBy(id),\n])\n\nconst breakfasts = [&#39;pancakes&#39;, &#39;waffles&#39;, &#39;french toast&#39;]\n\nconsole.log(uniqueLettersFp(breakfasts))<\/code><\/pre>\n<p>Suddenly the intent is much clearer with the noise introduced by the lambdas gone. You get this because the lodash-fp functions are:<\/p>\n<ul>\n<li><strong>auto-curried:<\/strong> that is, even though <code>_.split<\/code> takes the splitter and then a string, you can just write <code>_.split('')<\/code> and get back a function which takes a string as an argument.<\/li>\n<li><strong>data-last:<\/strong> because <code>_.split<\/code> takes the string to split <em>last<\/em>, it can be passed into an auto-curried function.<\/li>\n<\/ul>\n<p>You need <em>both<\/em> to get that nice clean call to <code>_.flow<\/code>. But once you have both, it\u2019s really, really hard ever to go back, because it\u2019s so much nicer for building pipelines of functions.<\/p>\n<p>\u2026I need to see if I can help <a href=\"https:\/\/github.com\/mike-north\/ember-lodash\/issues\/21\">do the work<\/a> to make lodash-fp available in Ember.js.<\/p>\n","pubDate":"Sat, 24 Jun 2017 17:35:00 -0400","guid":"tag:v4.chriskrycho.com,2017-06-24:\/2017\/collection-last-auto-curried-functions.html","category":["javascript","functional programming"]},{"title":"Why Elm Instead of TypeScript?","link":"http:\/\/v4.chriskrycho.com\/2017\/why-elm-instead-of-typescript.html","description":"<p>A few weeks ago, an acquaintance asked in a Slack channel we\u2019re both in:<\/p>\n<blockquote>\n<p>Can I ask a noob type Elm \/ JS question?<\/p>\n<p>Why Elm instead of Typescript? The dev stack and functional programming?<\/p>\n<\/blockquote>\n<p>I responded as follows, with only light tweaks to clarify a couple things (and I\u2019ll be reusing some of this material as the basis of an internal tech talk I\u2019m giving on the same subject at Olo in a few weeks):<\/p>\n<p>A couple things Elm gives you:<\/p>\n<ol type=\"1\">\n<li><p>It\u2019s not tied to JS directly, which means it\u2019s free to just do what is the best fit for the language rather than needing to be able to express all the quirks and oddities of JS. That\u2019s the single biggest thing I find all the time with TS (which I use every day and do quite like): as good as it is, and as both powerful and expressive as its type system is, at the end of the day it\u2019s\u2026 still a superset of JavaScript, and that can mean some really nice things, but it also means a lot of <em>weird<\/em> things.<\/p><\/li>\n<li><p>Elm\u2019s type system is <em>sound<\/em>; TypeScript\u2019s is not. At a practical level, that means that if an Elm program type-checks (and thus compiles), you can be <em>sure<\/em> \u2013 not mostly sure, 100% sure \u2013 that it is free of things like <code>undefined is not a function<\/code>. TypeScript does not (and by design cannot) give you that guarantee. And when I say \u201cby design,\u201d I mean that its designers believed from the outset that soundness was in tension with developer productivity, so they intentionally left a number of \u201csoundness holes\u201d in the type system\u2014there\u2019s still a lot of opportunity for <code>undefined is not a function<\/code>, sad to say. You can make it <em>less<\/em> than in JS\u2026 but not none. (That\u2019s even still true in the TypeScript 2.x series, though the various soundness flags they added in 2.0 and the <code>--strict<\/code> option <a href=\"https:\/\/blogs.msdn.microsoft.com\/typescript\/2017\/04\/10\/announcing-typescript-2-3-rc\/\">coming in 2.3<\/a> do get you closer.) In Elm, you can make it truly <em>none<\/em>. It\u2019s just a sort of known fact at this point that Elm codebases tend to <em>have zero runtime errors<\/em>.<\/p><\/li>\n<li><p>Elm\u2019s language design is a huge win.<\/p>\n<ol type=\"1\">\n<li><p>Elm is a <em>pure functional language<\/em>. Because non-pure things are offloaded to the Elm runtime, every single function <em>you<\/em> write is pure. Same input means the same output.<\/p><\/li>\n<li><p>Elm supports first-class currying and partial application. This makes it much, much easier to do the kind of functional-building-block approach that is natural in FP and which is <em>attractive<\/em> in (but a lot more work in) JS or TS. Example code to show what I mean\u2014<\/p>\n<p>Javascript:<\/p>\n<pre class=\"js\"><code>const add = (a, b) =&gt; a + b;\nconst add2 = (c) =&gt; add(2, c);\nconst five = add2(3);<\/code><\/pre>\n<p>Elm:<\/p>\n<pre class=\"elm\"><code>add a b = a + b\nadd2 = add 2\nfive = add2 3<\/code><\/pre><\/li>\n<li><p>The combination of the above means that you can refactor and <em>always be sure you get everything<\/em>, which is truly magical. And the compiler errors are the best in the world (and that\u2019s no exaggeration).<\/p><\/li>\n<\/ol><\/li>\n<\/ol>\n<p>The way I\u2019d summarize it is to say that Elm makes it easy to do the right thing and hard or impossible to do the wrong thing. TypeScript makes it possible to do the right thing, and gives you a couple switches you can flip to make it harder to do the wrong things, but will ultimately let you do anything.<\/p>\n","pubDate":"Sun, 23 Apr 2017 17:20:00 -0400","guid":"tag:v4.chriskrycho.com,2017-04-23:\/2017\/why-elm-instead-of-typescript.html","category":["Elm","JavaScript","TypeScript","programming languages","functional programming"]},{"title":"Functions, Objects, and Destructuring in JavaScript","link":"http:\/\/v4.chriskrycho.com\/2017\/functions-objects-and-destructuring-in-javascript.html","description":"<p><i class=editorial>A colleague just getting his feet wet with JavaScript, and coming from a background with much more C# than JavaScript, sent me a question on Slack the other day, and I realized the answer I\u2019d written up was more generally helpful, so here you go!<\/i><\/p>\n<p>I\u2019m including the context of original question because I want to call out something really important: there are no dumb questions. When you\u2019re just coming up to speed on <em>any<\/em> technology, stuff is going to be confusing. That goes double when making the jump as far as between something like C# and something like modern JS.<\/p>\n<blockquote>\n<p>Hey this may be a really dumb question<\/p>\n<p>but I\u2019m a JavaScript n00b, and I have no idea what\u2019s going on here<\/p>\n<p>I\u2019m not used to this syntax<\/p>\n<p>I have this program:<\/p>\n<pre class=\"js\"><code>function ab() {\n   function fa() { console.log(&quot;A&quot;); };\n   function fb() { console.log(&quot;B&quot;); };\n   return {fa, fb};\n};\n\nlet {fa, fb} = ab();\n\nfa();\nfb();<\/code><\/pre>\n<p>and it outputs<\/p>\n<pre><code>A\nB<\/code><\/pre>\n<p>(as expected)<\/p>\n<p>What I don\u2019t understand is the syntax for the <code>let<\/code> part (or maybe even the return from <code>ab()<\/code>)<\/p>\n<ol type=\"A\">\n<li><p>What is <code>ab()<\/code> actually returning? An object with 2 function pointers?<\/p><\/li>\n<li><p>What can\u2019t I do a <code>let {a, b} = ab()<\/code> and then call <code>a()<\/code> and <code>b()<\/code>? I get syntax errors that <code>a<\/code> and <code>b<\/code> aren\u2019t defined<\/p><\/li>\n<\/ol>\n<p><em>edit to show code that doesn\u2019t work (definition of ab() remains the same):<\/em><\/p>\n<pre class=\"js\"><code>let {a, b} = ab();\n\na(); \/\/ will throw an error here\nb();<\/code><\/pre>\n<p>I don\u2019t understand why the names for <code>fa<\/code> and <code>fb<\/code> have to be the same across all scopes\/closures (? am I using those terms correctly? JavaScript is an odd dance partner at times)<\/p>\n<\/blockquote>\n<hr \/>\n<p>First, your (A) is <em>basically<\/em> correct, but the phrase \u201cfunction pointers\u201d is one you should banish from your mind entirely in this context. In JavaScript, functions are just items like any other. From the language\u2019s perspective, there\u2019s no difference between these things other than what you can do with them:<\/p>\n<pre class=\"js\"><code>let foo = &quot;a string&quot;;\nfunction quux(blah) { console.log(&quot;blah is &quot; + blah); }\nlet bar = quux;<\/code><\/pre>\n<p>Both <code>foo<\/code> and <code>bar<\/code> are just variables. (<code>quux<\/code> is a variable, too, but it behaves a little differently; I\u2019ll cover that in a minute.) They have different types, and therefore different things you can do on them. <code>foo<\/code> has the <code>length<\/code> property and a bunch of string-specific methods attached. <code>bar<\/code> is callable. But both of them are just <em>things<\/em> in the same way, and at the same level in the program.<\/p>\n<p>So in your original <code>function ab() { ... }<\/code>, what you\u2019re doing is declaring two functions, <code>fa<\/code> and <code>fb<\/code>, and returning them attached to an object.<\/p>\n<p>For various reasons which aren\u2019t especially interesting, functions can have <em>names<\/em>\u2026<\/p>\n<pre class=\"js\"><code>function fa() { ... }<\/code><\/pre>\n<p>\u2026and can be <em>assigned to other variables<\/em>\u2026<\/p>\n<pre class=\"js\"><code>let trulyISayToYou = function waffles() { console.log(&quot;are so tasty&quot;); };<\/code><\/pre>\n<p>\u2026and in fact you can define the functions <em>themselves<\/em> anonymously, that is, without any name attached to the function declaration itself: combine those:<\/p>\n<pre class=\"js\"><code>let lookMa = function() { console.log(&quot;no function name!&quot;); };<\/code><\/pre>\n<p>Doing <code>function ab() { ... }<\/code> simultaneously <em>declares<\/em> the function and <em>hoists<\/em> it, that is, it makes it available in that entire scope, regardless of where it is defined. So you can do this, even though it\u2019s kind of insane most of the time and you shouldn\u2019t:<\/p>\n<pre class=\"js\"><code>quux();\nfunction quux() { console.log(&#39;SRSLY?&#39;); }<\/code><\/pre>\n<hr \/>\n<p>Now, about returning <code>fa<\/code> and <code>fb<\/code> from the function.<\/p>\n<p>First, note that you normally define objects in a long form, like so:<\/p>\n<pre class=\"js\"><code>let someObject = {\n  a: true,\n  b: &#39;some string&#39;\n};\n\nconsole.log(someObject.a);  \/\/ prints true\nconsole.log(someObject.b);  \/\/ prints &quot;some string&quot;<\/code><\/pre>\n<p>However, very, <em>very<\/em> often, you find yourself doing something like this:<\/p>\n<pre class=\"js\"><code>\/\/ do some work to define what `a` and `b` should be, then...\nlet someObject = {\n  a: a,\n  b: b\n};<\/code><\/pre>\n<p>Because this is such a common pattern, the 2015 version of JS introduced a \u201cshorthand,\u201d which lets you just write that last assignment like this:<\/p>\n<pre class=\"js\"><code>let someObject = {\n  a,\n  b\n};<\/code><\/pre>\n<p>And of course, for convenience we often write that on one line:<\/p>\n<pre class=\"js\"><code>let someObject = { a, b };<\/code><\/pre>\n<p>Then you can combine that with the fact that you declared two items (functions, but again: that <em>really<\/em> doesn\u2019t matter, they could be anything) with the names <code>fa<\/code> and <code>fb<\/code>, and what you\u2019re doing is returning an object containing those two items in it: <code>return {fa, fb}<\/code> is equivalent to this:<\/p>\n<pre class=\"js\"><code>let theFunctions = {\n  fa: fa,\n  fb: fb, \n};\nreturn theFunctions;<\/code><\/pre>\n<hr \/>\n<p>What about the <code>let<\/code> assignment?<\/p>\n<p>JS has three kinds of name bindings: <code>var<\/code>, <code>let<\/code>, and <code>const<\/code>. <code>var<\/code> bindings act like <code>function<\/code>: the names you use get \u201choisted\u201d. So:<\/p>\n<pre class=\"js\"><code>console.log(neverDefined);  \/\/ throws an error\nconsole.log(definedLater);  \/\/ prints undefined\nvar definedLater = &quot;what&quot;;\nconsole.log(definedLater);  \/\/ prints &quot;what&quot;<\/code><\/pre>\n<p><code>let<\/code> and <code>const<\/code> behave much more like you\u2019d expect: they\u2019re only valid <em>after<\/em> they\u2019re defined, and they\u2019re scoped to the blocks they appear in. (<code>var<\/code> will escape things like <code>if<\/code> blocks, too. It\u2019s crazy-pants.) The difference between <code>let<\/code> and <code>const<\/code> is that they create <em>mutable<\/em> or <em>immutable<\/em> <em>bindings<\/em> to a name.<\/p>\n<p>So <code>let a = true;<\/code> is just creating a name, <code>a<\/code>, and binding the value <code>true<\/code> to it. Likewise, with <code>const b = false;<\/code> it\u2019s creating a name, <code>b<\/code>, and binding the value <code>false<\/code> to it. And those <em>won\u2019t<\/em> be hosted. Now, having done <code>let a = true;<\/code> we could on the next line write <code>a = false;<\/code> and that\u2019s fine: <code>let<\/code> bindings are mutable; they can change. We\u2019ll get an error if we try to do <code>b = true;<\/code> though, because <code>const<\/code> bindings are <em>not<\/em> mutable.<\/p>\n<p>One thing to beware of with that: things like objects and arrays, being reference types, are not themselves created as immutable when you use <code>const<\/code>. Rather, the specific <em>instance<\/em> is immutably bound to the name. So:<\/p>\n<pre class=\"js\"><code>const foo = { a: true };\nfoo.b = &#39;I can add properties!&#39;;  \/\/ okay\ndelete foo.a;  \/\/ okay\nfoo = { c: &quot;assign a new object&quot; };  \/\/ will error<\/code><\/pre>\n<p>You can change the internals of the item bound to the name, but not assign a new item to the name. For value types (numbers, booleans, etc.), that makes them behave like <em>constants<\/em> in other languages. You have to use something like <code>Object.freeze<\/code> to get actually constant object types.<\/p>\n<p>That was a long digression to explain what you\u2019re seeing in a general sense with <code>let<\/code>.<\/p>\n<hr \/>\n<p>Finally, let\u2019s come back around and talk about that assignment and why you need the names <code>fa<\/code> and <code>fb<\/code>.<\/p>\n<p>As noted, <code>ab()<\/code> returns an object with two items attached, <code>fa<\/code> and <code>fb<\/code>. (And again: functions are <em>just<\/em> items in JS.) So you could also write that like this:<\/p>\n<pre class=\"js\"><code>let theFunctions = ab();  \/\/ theFunctions is now the object returned\ntheFunctions.fa();  \/\/ and it has the `fa` item on it\ntheFunctions.fb();  \/\/ and the `fb` item, too<\/code><\/pre>\n<p>Of course, if your original <code>ab()<\/code> function had returned other properties, they\u2019d be accessible there, too, in just the same way (though they wouldn\u2019t be callable if they weren\u2019t functions).<\/p>\n<p>Again, this is a super common pattern: you want to immediately do something with the values returned on an object by some function, and you don\u2019t necessarily want to type out the name of the object every time. So ES2015 introduced <em>destructuring<\/em> to help with this problem. I\u2019ll do it without the function in the way to show how it works at the simplest level first.<\/p>\n<pre class=\"js\"><code>let someObject = {\n  foo: &#39;what is a foo anyway&#39;,\n  bar: &#39;hey, a place to drink *or* a thing to hit people with&#39;,\n  quux: &#39;is this like a duck&#39;\n};\n\nconsole.log(someObject.foo);  \/\/ etc.<\/code><\/pre>\n<p>Now, if we wanted to get at <code>foo<\/code>, <code>bar<\/code>, and <code>quux<\/code>, we could always do that with <code>someObject.quux<\/code> and so on. But, especially if we have some large object floating around, we often just want a couple properties from it\u2014say, in this case, <code>foo<\/code> and <code>quux<\/code>. We could do that like this:<\/p>\n<pre class=\"js\"><code>let foo = someObject.foo;\nlet quux = someObject.quux;<\/code><\/pre>\n<p>And of course those new names <em>don\u2019t<\/em> have to match:<\/p>\n<pre class=\"js\"><code>let whatever = someObject.foo;\nlet weLike = someObject.quux;<\/code><\/pre>\n<p>However, because wanting to snag just a couple items off of objects like this is so common, the shorthand is available. In the case of the shorthand for <em>destructuring<\/em>, just like the case of the shorthand for object creation, the names have to match: otherwise, it wouldn\u2019t know what to match them with.<\/p>\n<pre class=\"js\"><code>let { foo, quux } = someObject;<\/code><\/pre>\n<p>So, going back to your original example: <code>ab()<\/code> returns an object which has the items <code>fa<\/code> and <code>fb<\/code> on it. You\u2019re using the destructuring assignment there to get just <code>fa<\/code> and <code>fb<\/code>. There\u2019s no reason they <em>have<\/em> to be those names in the outer scope, other than that you\u2019re using the destructuring assignment. You could also do this:<\/p>\n<pre class=\"js\"><code>let theFunctions = ab();\nlet oneOfThem = theFunctions.fa;\nlet theOtherOne = theFunctions.fb;\noneOfThem();  \/\/ does what fa() does\ntheOtherOne();  \/\/ does what fb() does<\/code><\/pre>\n<hr \/>\n<p>I <em>think<\/em> that covers everything your questions brought up; but please feel free to ask more!<\/p>\n<p>The most important thing to take away is that even though yes, those are pointers to functions under the hood, in JS that\u2019s <em>absolutely<\/em> no different than the fact that there are pointers to objects and arrays under the hood. Functions are just more items you can do things with. You can put them on objects, you can return them directly, you can take them as arguments, etc.<\/p>\n<p>Hopefully that\u2019s helpful!<\/p>\n<hr \/>\n<p>Bonus content: in ES2015 and later, you can also define anonymous functions like this:<\/p>\n<pre class=\"js\"><code>let someFunction = (someArg) =&gt; { console.log(someArg); };<\/code><\/pre>\n<p>This has some interesting side effects about the value of <code>this<\/code> in the body of the function you declare\u2026 but that\u2019s for another time.<\/p>\n","pubDate":"Mon, 27 Mar 2017 18:00:00 -0400","guid":"tag:v4.chriskrycho.com,2017-03-27:\/2017\/functions-objects-and-destructuring-in-javascript.html","category":"javascript"},{"title":"TypeScript keyof Follow-Up","link":"http:\/\/v4.chriskrycho.com\/2017\/typescript-keyof-follow-up.html","description":"<p>I recently wrote up some neat things you can do with <a href=\"http:\/\/v4.chriskrycho.com\/2016\/keyof-and-mapped-types-in-typescript-21.html\"><code>keyof<\/code> and mapped types<\/a> in TypeScript 2.1. In playing further with those bits, I ran into some interesting variations on the approach I outlined there, so here we are.<\/p>\n<p>In the previous post, I concluded with an example that looked like this:<\/p>\n<pre class=\"typescript\"><code>type UnionKeyToValue&lt;U extends string&gt; = {\n  [K in U]: K\n};\n\ntype State\n  = &#39;Pending&#39;\n  | &#39;Started&#39;\n  | &#39;Completed&#39;;\n\n\/\/ Use `State` as the type parameter to `UnionKeyToValue`.\nconst STATE: UnionKeyToValue&lt;State&gt; = {\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n}<\/code><\/pre>\n<p>That <code>UnionKeyToValue&lt;State&gt;<\/code> type constraint requires us to fill out the <code>STATE<\/code> object as expected. The whole point of this exercise was to give us the benefit of code completion with that STATE type so we could use it and not be worried about the kinds of typos that too-often bite us with stringly-typed arguments in JavaScript.<\/p>\n<p>It turns out we don\u2019t <em>need<\/em> that to get completion, though. All editors which use the TypeScript language service will give us the same degree of completion if we start typing a string and then trigger completion:<\/p>\n<figure>\n<img src=\"https:\/\/f001.backblazeb2.com\/file\/chriskrycho-com\/images\/more-ts.gif\" title=\"screen capture of string completion in VS Code\" alt=\"string completion with TypeScript 2.1\" \/><figcaption>string completion with TypeScript 2.1<\/figcaption>\n<\/figure>\n<p>Granted that you have to know this is a string (though the JetBrains <abbr title=\"integrated development environment\">IDE<\/abbr>s will actually go a step further and suggest the right thing <em>without<\/em> needing the string key). But that\u2019s roughly equivalent to knowing you need to import the object literal constant to get the completion that way. Six one, half dozen the other, I think.<\/p>\n<p>This makes it something of a wash with the original approach, as long as you\u2019re dealing in a pure-TypeScript environment. The big advantage that the original approach still has, of course, is that it also plays nicely with a mixed TypeScript and JavaScript environment. If you\u2019re just progressively adding TypeScript to an existing JavaScript codebase, that\u2019s possibly reason enough to stick with it.<\/p>\n<p><strong>Edit<\/strong>: an additional reason to prefer my original solution:<\/p>\n<blockquote class=\"twitter-tweet\" data-lang=\"en\">\n<p lang=\"en\" dir=\"ltr\">\n<a href=\"https:\/\/twitter.com\/chriskrycho\">@chriskrycho<\/a> <a href=\"https:\/\/twitter.com\/typescriptlang\">@typescriptlang<\/a> I think a benefit of your previous solution is that you can rename keys and all their usages.\n<\/p>\n\u2014 Timm (@timmpreetz) <a href=\"https:\/\/twitter.com\/timmpreetz\/status\/816672215924097024\">January 4, 2017<\/a>\n<\/blockquote>\n<script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n","pubDate":"Tue, 03 Jan 2017 20:35:00 -0500","guid":"tag:v4.chriskrycho.com,2017-01-03:\/2017\/typescript-keyof-follow-up.html","category":["programming languages","software development","typescript","javascript"]},{"title":"The Itch","link":"http:\/\/v4.chriskrycho.com\/2016\/the-itch.html","description":"<p>It took me until just a few weeks ago to put my finger on why typed functional programming, as a style and approach, has appealed to me so much as I started picking it up over the last year. For all its novelty, typed FP feels\u2014over and over again\u2014<em>familiar<\/em>. Strange to say, but it\u2019s true.<\/p>\n<p>This came home to me again when reading a <a href=\"https:\/\/medium.com\/@dtinth\/what-is-a-functor-dcf510b098b6#.e887yz63p\">short post on functors<\/a>\u2014i.e., <em>mappable<\/em> types. I\u2019ve written a lot of JavaScript in the last few years, and it has been a source of constant frustration to me that <code>Array<\/code> implements the <code>map<\/code> method, but <code>Object<\/code> does not. Countless times, I have wanted to take an object shaped like <code>{ count: &lt;number&gt; }<\/code> and transform that <code>count<\/code>. I\u2019m not alone in that. There\u2019s a reason that libraries like <a href=\"http:\/\/underscorejs.org\">Underscore<\/a>, <a href=\"https:\/\/lodash.com\">Lodash<\/a>, and <a href=\"http:\/\/ramdajs.com\">Ramda<\/a> all supply utilities to allow you to map over objects. There are also good reasons why it <em>isn\u2019t<\/em> implemented for on <code>Object.prototype<\/code>: the reality is that coming up with a predictable <em>and<\/em> useful API for <em>all<\/em> <code>Object<\/code> instances is difficult at best: Objects are used for everything from dictionaries to records and strange combinations of the two. But still: there\u2019s something there.<\/p>\n<p>And reading this post on functors, it struck me what that \u201csomething\u201d is: object types are, in principle, functors. Maybe it doesn\u2019t make sense to have a single <code>map<\/code> implementation for every <code>Object<\/code> instance out there. But they\u2019re perfectly mappable. I didn\u2019t have a word for this before tonight, but now I do. Over and over again, this is my experience with functional programming.<\/p>\n<p>There\u2019s this familiar feeling of frustration I\u2019m slowly coming to recognize\u2014a mental sensation which is a little like the intellectual equivalent of an itch in a spot you can\u2019t quite reach. You\u2019re reaching for an abstraction to express an idea, but you don\u2019t even know that there <em>is<\/em> an abstraction for it. You want to map over objects, and you don\u2019t know why that seems so reasonable, but it does. And then someone explains functors to you. It scratches the itch.<\/p>\n<p>Another example. Since I started programming eight and a half years ago, I\u2019ve worked seriously with Fortran, C, C++ PHP, Python, and JavaScript. In each of those languages (and especially in the C-descended languages), I have found myself reaching for enums or things like them as a way of trying to represent types and states in my system in a more comprehensive way. I figured out that you should <a href=\"http:\/\/wiki.c2.com\/?UseEnumsNotBooleans\">use enums not booleans<\/a> a long time before I found the advice on the internet. I was encoding error types as enum values instead of just using <code>int<\/code>s almost as soon as I started, because it was obvious to me that <code>ErrorCode someFunction() { ... }<\/code> was far more meaningful than <code>int someFunction() { ... }<\/code> (even if the context of C meant that the latter often implied the former, and even if it was trivial to coerce one to the other).<\/p>\n<p>Then I read <a href=\"https:\/\/gumroad.com\/l\/maybe-haskell\/\"><em>Maybe Haskell<\/em><\/a>, a book I\u2019ve mentioned often on this blog because it was so revelatory for me. This is what I had been reaching for all those years\u2014and then some. Handing data around with the constraints? Yes, please! I had played with unions, enums, structs with enums inside them, anything to try to get some type-level clarity and guarantees about what my code was doing. Haskell showed me the way; and since then Rust and Elm and F# have reinforced it many times over. <a href=\"https:\/\/guide.elm-lang.org\/types\/union_types.html\">Tagged unions<\/a> are a joy. They let me say what I mean\u2014finally.<\/p>\n<p>I can still feel that itch. It\u2019s shifted a little, but it\u2019s still there: reaching for higher abstractions to let me tell the machine more clearly what I intend. Half a dozen times this year, I\u2019ve realized: <em>Here<\/em> is where dependent types would be useful. They\u2019re far beyond me, but close enough now I can see. I\u2019m sure a year from now, I\u2019ll have find some tools to scratch <em>these<\/em> itches, only to discover a few more.<\/p>\n","pubDate":"Mon, 19 Dec 2016 21:45:00 -0500","guid":"tag:v4.chriskrycho.com,2016-12-19:\/2016\/the-itch.html","category":["software development","functional programming","Rust","JavaScript"]},{"title":"keyof and Mapped Types In TypeScript 2.1","link":"http:\/\/v4.chriskrycho.com\/2016\/keyof-and-mapped-types-in-typescript-21.html","description":"<p>In the last few months, I\u2019ve been playing with both <a href=\"https:\/\/flowtype.org\">Flow<\/a> and <a href=\"http:\/\/www.typescriptlang.org\">TypeScript<\/a> as tools for increasing the quality and reliability of the JavaScript I write at Olo. Both of these are syntax that sits on top of normal JavaScript to add type analysis\u2014basically, a form of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Gradual_typing\">gradual typing<\/a> for JS.<\/p>\n<p>Although TypeScript\u2019s tooling has been better all along<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> I initially preferred Flow\u2019s type system quite a bit: it has historically been much more focused on <a href=\"http:\/\/stackoverflow.com\/questions\/21437015\/soundness-and-completeness-of-systems\">soundness<\/a>, especially around the <em>many<\/em> problems caused by <code>null<\/code> and <code>undefined<\/code>, than TypeScript. And it had earlier support for <a href=\"https:\/\/flowtype.org\/docs\/disjoint-unions.html\">tagged unions<\/a>, a tool I\u2019ve come to find invaluable since picking them up from my time with Rust.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> But the 2.0 and 2.1 releases of TypeScript have changed the game substantially, and it\u2019s now a <em>very<\/em> compelling language in its own right\u2014not to mention a great tool for writing better JavaScript. So I thought I\u2019d highlight how you can get a lot of the benefits you would get from the type systems of languages like Elm with some of those new TypeScript features: the <em><code>keyof<\/code> operator<\/em> and <em>mapped types<\/em>.<\/p>\n<hr \/>\n<p><i>Some readers may note that what I\u2019m doing here is a <em>lot<\/em> of wrangling to cajole TypeScript into giving me the kinds of things you get for free in an ML-descended language. Yep. The point is that you <em>can<\/em> wrangle it into doing this.<\/i><\/p>\n<hr \/>\n<section id=\"plain-old-javascript\" class=\"level3\">\n<h3>Plain old JavaScript<\/h3>\n<p>Let\u2019s say we want to write a little state machine in terms of a function to go from one state to the next, like this:<\/p>\n<pre class=\"javascript\"><code>function nextState(state) {\n  switch(state) {\n    case &#39;Pending&#39;: return &#39;Started&#39;;\n    case &#39;Started&#39;: return &#39;Completed&#39;;\n    case &#39;Completed&#39;: return &#39;Completed&#39;;\n    default: throw new Error(`Bad state: ${state}`);\n  }\n}<\/code><\/pre>\n<p>This will work, and it\u2019ll even throw an error if you hand it the wrong thing. But you\u2019ll find out at runtime if you accidentally typed <code>nextState('Pednign')<\/code> instead of <code>nextState('Pending')<\/code>\u2014something I\u2019ve done more than once in the past. You\u2019d have a similar problem if you\u2019d accidentally written <code>case 'Strated'<\/code> instead of <code>case 'Started'<\/code>.<\/p>\n<p>There are many contexts like this one in JavaScript\u2014perhaps the most obvious being <a href=\"http:\/\/redux.js.org\/docs\/basics\/Actions.html\">Redux actions<\/a>, but I get a lot of mileage out of the pattern in Ember, as well. In these contexts, I find it\u2019s convenient to define types that are kind of like pseudo-enums or pseudo-simple-unions, like so:<a href=\"#fn3\" class=\"footnote-ref\" id=\"fnref3\" role=\"doc-noteref\"><sup>3<\/sup><\/a><\/p>\n<pre class=\"javascript\"><code>const STATE = {\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n};<\/code><\/pre>\n<p>Once you\u2019ve defined an object this way, instead of using strings directly in functions that take it as an argument, like <code>nextState('Started')<\/code>, you can use the object property: <code>nextState(STATE.Started)<\/code>. You can rewrite the function body to use the object definition instead as well:<\/p>\n<pre class=\"javascript\"><code>function nextState(state) {\n  switch(state) {\n    case STATE.Pending: return STATE.Started;\n    case STATE.Started: return STATE.Completed;\n    case STATE.Completed: return STATE.Completed;\n    default: throw new Error(`Bad state: ${state}`);\n  }\n}<\/code><\/pre>\n<p>Using the object and its keys instead gets you something like a namespaced constant. As a result, you can get more help with things like code completion from your editor, along with warnings or errors from your linter if you make a typo. You\u2019ll also get <em>slightly<\/em> more meaningful error messages if you type the wrong thing. For example, if you type <code>STATE.Strated<\/code> instead of <code>STATE.Started<\/code>, any good editor will give you an error\u2014especially if you\u2019re using a linter. At Olo, we use <a href=\"http:\/\/eslint.org\">ESLint<\/a>, and we have it <a href=\"https:\/\/github.com\/ember-cli\/ember-cli-eslint\/\">set up<\/a> so that this kind of typo\/linter error fails our test suite (and we never merge changes that don\u2019t pass our test suite!).<\/p>\n<p>This is about as good a setup as you can get in plain-old JavaScript. As long as you\u2019re disciplined and always use the object, you get some real benefits from using this pattern. But you <em>always<\/em> have to be disciplined. If someone who is unfamiliar with this pattern types <code>nextState('whifflebats')<\/code> somewhere, well, we\u2019re back to blowing up at runtime. Hopefully your test suite catches that.<\/p>\n<\/section>\n<section id=\"typescript-to-the-rescue\" class=\"level3\">\n<h3>TypeScript to the rescue<\/h3>\n<p>TypeScript gives us the ability to <em>guarantee<\/em> that the contract is met (that we\u2019re not passing the wrong value in). As of the latest release, it also lets us guarantee the <code>STATES<\/code> object to be set up the way we expect. And last but not least, we get some actual productivity boosts when writing the code, not just when debugging it.<\/p>\n<p>Let\u2019s say we decided to constrain our <code>nextState<\/code> function so that it had to both take and return some kind of <code>State<\/code>, representing one of the states we defined above. We\u2019ll leave a <code>TODO<\/code> here indicating that we need to figure out how to write the type of <code>State<\/code>, but the function definition would look like this:<\/p>\n<pre class=\"typescript\"><code>\/\/ TODO: figure out how to define `State`\nfunction nextState(state: State): State {\n  \/\/ the same body...\n}<\/code><\/pre>\n<p>TypeScript has had <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/advanced-types.html#union-types\">union types<\/a> since the <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/release-notes\/typescript-1-4.html\">1.4 release<\/a> so they might seem like an obvious choice, and indeed we could write easily a type definition for the strings in <code>STATES<\/code> as a union:<\/p>\n<pre class=\"typescript\"><code>type State = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;<\/code><\/pre>\n<p>Unfortunately, you can\u2019t write something like <code>State.Pending<\/code> somewhere; you have to write the plain string <code>'Pending'<\/code> instead. You still get some of the linting benefits you got with the approach outlined above via TypeScript\u2019s actual type-checking, but you don\u2019t get <em>any<\/em> help with autocompletion. Can we get the benefits of both?<\/p>\n<p>Yes! (This would be a weird blog post if I just got this far and said, \u201cNope, sucks to be us; go use Elm instead.\u201d)<\/p>\n<p>As of the 2.1 release, TypeScript lets you define types in terms of keys, so you can write a type like this:<a href=\"#fn4\" class=\"footnote-ref\" id=\"fnref4\" role=\"doc-noteref\"><sup>4<\/sup><\/a><\/p>\n<pre class=\"typescript\"><code>const STATE = {\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n};\n\ntype StateFromKeys = keyof typeof STATE;<\/code><\/pre>\n<p>Then you can use that type any place you need to constrain the type of a variable, or a return, or whatever:<\/p>\n<pre class=\"typescript\"><code>const goodState: StateFromKeys = STATE.Pending;\n\n\/\/ error: type &#39;&quot;Blah&quot;&#39; is not assignable to type &#39;State&#39;\nconst badState: StateFromKeys = &#39;Blah&#39;;\n\ninterface StateMachine {\n  (state: StateFromKeys): StateFromKeys;\n}\n\nconst nextState: StateMachine = (state) =&gt; {\n  \/\/ ...\n}<\/code><\/pre>\n<p>The upside to this is that now you can guarantee that anywhere you\u2019re supposed to be passing one of those strings, you <em>are<\/em> passing one of those strings. If you pass in <code>'Compelte'<\/code>, you\u2019ll get an actual error\u2014just like if we had used the union definition above. At a minimum, that will be helpful feedback in your editor. Maximally, depending on how you have your project configured, it may not even generate any JavaScript output.<a href=\"#fn5\" class=\"footnote-ref\" id=\"fnref5\" role=\"doc-noteref\"><sup>5<\/sup><\/a> So that\u2019s a significant step forward beyond what we had even with the best linting rules in pure JavaScript.<\/p>\n<\/section>\n<section id=\"going-in-circles\" class=\"level3\">\n<h3>Going in circles<\/h3>\n<p>But wait, we can do more! TypeScript 2.1 <em>also<\/em> came with a neat ability to define \u201cmapped types,\u201d which map one object type to another. They have a few <a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/release-notes\/typescript-2-1.html#mapped-types\">interesting examples<\/a> which are worth reading. What\u2019s interesting to us here is that you can write a type like this:<\/p>\n<pre class=\"typescript\"><code>type StateAsMap = {\n  [K in keyof typeof STATE]: K\n}<\/code><\/pre>\n<p>And of course, you can simplify that using the type we defined above, since <code>StateFromKeys<\/code> was just <code>keyof typeof STATE<\/code>:<\/p>\n<pre class=\"typescript\"><code>type StateAsMap = {\n  [K in StateFromKeys]: K\n}<\/code><\/pre>\n<p>We\u2019ve now defined an object type whose <em>key<\/em> has to be one of the items in the <code>State<\/code> type.<\/p>\n<p>Now, by itself, this isn\u2019t all that useful. Above, we defined that as the keys on the <code>STATE<\/code> object, but if we tried to use that in conjunction with this new type definition, we\u2019d just end up with a recursive type definition: <code>StateFromKeys<\/code> defined as the keys of <code>STATE<\/code>, <code>StateAsMap<\/code> defined in terms of the elements of <code>StateFromKeys<\/code>, and then <code>STATE<\/code> defined as a <code>StateAsMap<\/code>\u2026<\/p>\n<pre class=\"typescript\"><code>const STATE: StateAsMap = {\n  Pending: &#39;Pending&#39;,\n  Active: &#39;Active&#39;,\n  Completed: &#39;Completed&#39;,\n}\n\ntype StateFromKeys = keyof typeof STATE;\n\ntype StateAsMap = {\n  [K in StateFromKeys]: K\n}<\/code><\/pre>\n<p>You end up with multiple compiler errors here, because of the circular references. This approach won\u2019t work. If we take a step back, though, we can work through this (and actually end up someplace better).<\/p>\n<\/section>\n<section id=\"join-forces\" class=\"level3\">\n<h3>Join forces!<\/h3>\n<p>First, let\u2019s start by defining the mapping generically. After all, the idea here was to be able to use this concept all over the place\u2014e.g.\u00a0for <em>any<\/em> Redux action, not just one specific one. We don\u2019t need this particular <code>State<\/code>; we just need a constrained set of strings (or numbers) to be used as the key of an object:<\/p>\n<pre class=\"typescript\"><code>type MapKeyAsValue&lt;Key extends string&gt; = {\n  [K in Key]: K\n};<\/code><\/pre>\n<p>In principle, if we didn\u2019t have to worry about the circular references, we could use that to constrain our definition of the original <code>STATE<\/code> itself:<\/p>\n<pre class=\"typescript\"><code>const STATE: MapKeyAsValue&lt;State&gt; = {\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n};<\/code><\/pre>\n<p>So how to get around the problem of circular type definitions? Well, it turns out that the <code>K<\/code> values in these <code>StateObjectKeyToValue<\/code> and <code>StateUnionKeyToValue<\/code> types are equivalent:<\/p>\n<pre class=\"typescript\"><code>\/\/ Approach 1, using an object\nconst STATE = {\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n};\n\ntype StateFromKeys = keyof typeof STATE;\ntype StateObjectKeyToValue = {\n  [K in StateFromKeys]: K  \/\/ &lt;- K is just the keys!\n};\n\n\/\/ Approach 2, using unions\ntype StateUnion = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;\ntype StateUnionKeyToValue = {\n  [K in StateUnion]: K  \/\/ &lt;- K is also just the keys!\n};<\/code><\/pre>\n<p>Notice that, unlike the <code>StateObjectKeyToValue<\/code> version, <code>StateUnionKeyToValue<\/code> doesn\u2019t make any reference to the <code>STATE<\/code> object. So we can use <code>StateUnionKeyToValue<\/code> to constrain <code>STATE<\/code>, and then just use <code>StateUnion<\/code> to constrain all the places we want to <em>use<\/em> one of those states. Once we put it all together, that would look like this:<\/p>\n<pre class=\"typescript\"><code>type StateUnion = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;\n\ntype StateUnionKeyToValue = {\n  [K in StateUnion]: K\n};\n\nconst STATE: StateUnionKeyToValue = {\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n};<\/code><\/pre>\n<p>By doing this, we get two benefits. First, <code>STATE<\/code> now has to supply the key and value for <em>all<\/em> the union\u2019s variants. Second, we know that the key and value are the same, and that they map to the union\u2019s variants. These two facts mean that we can be 100% sure that wherever we define something as requiring a <code>State<\/code>, we can supply one of the items on <code>STATE<\/code> and it will be guaranteed to be correct. If we change the <code>State<\/code> union definition, everything else will need to be updated, too.<\/p>\n<p>Now we can make this generic, so it works for types besides just this one set of states\u2014so that it\u2019ll work for <em>any<\/em> union type with string keys, in fact. (That string-key constraint is important because objects in TypeScript can currently only use strings or numbers as keys; whereas union types can be all sorts of things.) Apart from that constraint on the union, though, we can basically just substitute a generic type parameter <code>U<\/code>, for \u201cunion,\u201d where we had <code>StateUnion<\/code> before.<\/p>\n<pre class=\"typescript\"><code>type UnionKeyToValue&lt;U extends string&gt; = {\n  [K in U]: K\n};<\/code><\/pre>\n<p>Then any object we say conforms to this type will take a union as its type parameter, and every key on the object must have exactly the same value as the key name:<\/p>\n<pre class=\"typescript\"><code>type State = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;\n\n\/\/ Use `State` as the type parameter to `UnionKeyToValue`.\nconst STATE: UnionKeyToValue&lt;State&gt; = {\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n}<\/code><\/pre>\n<p>If any of those don\u2019t have <em>exactly<\/em> the same value as the key name, you\u2019ll get an error. So, each of the following value assignments would fail to compile, albeit for different reasons (top to bottom: capitalization, misspelling, and missing a letter).<\/p>\n<pre class=\"typescript\"><code>const BAD_STATE: UnionKeyToValue&lt;State&gt; = {\n  Pending: &#39;pending&#39;,  \/\/ look ma, no capitals\n  Started: &#39;Strated&#39;,  \/\/ St-rated = whuh?\n  Completed: &#39;Complete&#39;,  \/\/ so tense\n};<\/code><\/pre>\n<p>You\u2019ll see a compiler error that looks something like this:<\/p>\n<blockquote>\n<div class=\"line-block\">[ts]<br \/>\nType \u2018{ Pending: \u201cpending\u201d; Started: \u201cStrated\u201d; Completed: \u201cComplete\u201d }\u2019 is not assignable to type \u2018UnionKeyToValue<State>\u2019.<br \/>\n\u00a0\u00a0Types of property \u2018Pending\u2019 are incompatible.<br \/>\n\u00a0\u00a0\u00a0\u00a0Type \u2018\u201cpending\u201d\u2019 is not assignable to type \u2018\u201cPending\u201d\u2019.<\/div>\n<\/blockquote>\n<p>Since the key and the name don\u2019t match, the compiler tells us we didn\u2019t keep the constraint we defined on what these types should look like. Similarly, if you forget an item from the union, you\u2019ll get an error. If you add an item that isn\u2019t in the original union, you\u2019ll get an error. Among other things, this means that you can be confident that if you add a value to the union, the rest of your code won\u2019t compile until you include cases for it. You get all the power and utility of using union types, <em>and<\/em> you get the utility of being able to use the object as a namespace of sorts.<a href=\"#fn6\" class=\"footnote-ref\" id=\"fnref6\" role=\"doc-noteref\"><sup>6<\/sup><\/a><\/p>\n<p>And the TypeScript language service\u2014which you can use from a <em>lot<\/em> of editors, including VS Code, Atom, Sublime Text, and the JetBrains IDEs\u2014will actually give you the correct completion when you start definition a type. So imagine we were defining some other union type elsewhere in our program to handle events. Now we can use the same <code>UnionKeyToValue<\/code> type to construct this type, with immediate, <em>correct<\/em> feedback from the TypeScript language service:<\/p>\n<figure>\n<video autoplay=autoplay muted=muted playsinline=playsinline loop=loop>\n<source type='video\/mp4' src='https:\/\/f001.backblazeb2.com\/file\/chriskrycho-com\/images\/completion.mp4'>\n<\/video>\n<figcaption>\nTypeScript live code completion of the mapped type\n<\/figcaption>\n<\/figure>\n<p>By inverting our original approach of using <code>keyof<\/code> (itself powerful and worth using in quite a few circumstances) and instead using the new mapped types, we get a <em>ton<\/em> of mileage in terms of productivity when using these types\u2014errors prevented, and speed of writing the code in the first place increased as well.<\/p>\n<p>Yes, it\u2019s a little verbose and it does require duplicating the strings whenever you define one of these types.<a href=\"#fn7\" class=\"footnote-ref\" id=\"fnref7\" role=\"doc-noteref\"><sup>7<\/sup><\/a> But, and this is what I find most important: there is only one <em>source<\/em> for those string keys, the union type, and it is definitive. If you change that central union type, everything else that references it, including the namespace-like object, will fail to compile until you make the same change there.<\/p>\n<figure>\n<video autoplay=autoplay muted=muted playsinline=playsinline loop=loop>\n<source type='video\/mp4' src='https:\/\/f001.backblazeb2.com\/file\/chriskrycho-com\/images\/change-union.mp4'>\n<\/video>\n<figcaption>\nUpdating a union\n<\/figcaption>\n<\/figure>\n<p>So it\u2019s a lot more work than it would be in, say, Elm. But it\u2019s also a lot more guarantees than I\u2019d get in plain-old-JavaScript, or even TypeScript two months ago.<\/p>\n<p>I\u2019ll call that a win.<\/p>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>it\u2019s no surprise that Microsoft\u2019s developer tooling is stronger than Facebook\u2019s<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>along with all the other ML-descended languages I\u2019ve played with, including Haskell, F<sup>\u266f<\/sup>, PureScript, and Elm.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn3\" role=\"doc-endnote\"><p>Aside: to be extra safe and prevent any confusion or mucking around, you should probably call <code>Object.freeze()<\/code> on the object literal, too:<\/p>\n<pre class=\"javascript\"><code>const STATE = Object.freeze({\n  Pending: &#39;Pending&#39;,\n  Started: &#39;Started&#39;,\n  Completed: &#39;Completed&#39;,\n})<\/code><\/pre>\n<p>Both convention and linters make it unlikely you\u2019ll modify something like this directly\u2014but impossible is better than unlikely.<a href=\"#fnref3\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn4\" role=\"doc-endnote\"><p>Flow has supported this feature for some time; you can write <code>$Keys&lt;typeof STATE&gt;<\/code>\u2014but the feature is entirely undocumented.<a href=\"#fnref4\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn5\" role=\"doc-endnote\"><p>Set your <code>\"compilerOptions\"<\/code> key in your <code>tsconfig.json<\/code> to include <code>\"noEmitOnError\": true,<\/code>.<a href=\"#fnref5\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn6\" role=\"doc-endnote\"><p>For namespacing in a more general sense, you should use\u2026 <a href=\"http:\/\/www.typescriptlang.org\/docs\/handbook\/namespaces.html\">namespaces<\/a>.<a href=\"#fnref6\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn7\" role=\"doc-endnote\"><p>It would be great if we could get these benefits without the duplication\u2014maybe someday we\u2019ll have better support in JS or TS natively.<a href=\"#fnref7\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Sat, 17 Dec 2016 23:25:00 -0500","guid":"tag:v4.chriskrycho.com,2016-12-17:\/2016\/keyof-and-mapped-types-in-typescript-21.html","category":["javascript","typescript","software development","programming languages"]},{"title":"What is Functional Programming?","link":"http:\/\/v4.chriskrycho.com\/2016\/what-is-functional-programming.html","description":"<p><i class='editorial'>The following is a script I wrote for a tech talk I gave on functional programming. The recording isn\u2019t (and won\u2019t be) publicly available; but a script is often easier to reference anyway!<\/i><\/p>\n<p><i class='editorial'><strong>Edit:<\/strong> updated with corrected performance characterstics.<\/i><\/p>\n<hr \/>\n<p>Hello, everyone. Today, we are going to talk about functional programming\u2014asking what it is, and why we should care.<\/p>\n<section id=\"clearing-the-table-functional-programmings-reputation\" class=\"level2\">\n<h2>Clearing the Table: Functional Programming\u2019s Reputation<\/h2>\n<p>Functional programming has something of a reputation: on the one hand, as incredible difficult, dense, full of mathematical jargon, applicable only to certain fields like machine learning or massive data analysis; on the other hand, as a kind of panacea that solves all of your problems. The reality, I think, is a little bit of both.<\/p>\n<p>The world of functional programming <em>does<\/em> include a lot of jargon from the math world, and there are good reasons for that, but there is also a lot we could do to make it more approachable to people who don\u2019t have a background in, say category. Category theory is useful, of course, and I think there are times when we might want to be able to draw on it. But gladly, functional programming doesn\u2019t require you to know what an <em>applicative functor<\/em> is to be able to use it. (And, gladly, there\u2019s a lot of increasingly-solid teaching material out there about functional programming which <em>doesn\u2019t<\/em> lean on math concepts.)<\/p>\n<p>On the other side, functional programming does give us some real and serious benefits, and that\u2019s what I\u2019m going to spend the first third or so of this talk looking at. But of course, it\u2019s still just a tool, and even though it is a very helpful and very powerful tool, it can\u2019t keep us from writing bugs. Still, every tool we can add to our belt for writing correct software is a win.<\/p>\n<p>One more prefatory note before we get into the meat of this talk: unfamiliar terminology is not specific to functional programming. So, yes, when you see this list, it might seem a little out there:<\/p>\n<ul>\n<li>Functor<\/li>\n<li>Applicative<\/li>\n<li>Monoid<\/li>\n<li>Monad<\/li>\n<\/ul>\n<p>And in truth, a number of those could have better names. <em>But<\/em> we have plenty of terminology we throw around in the world of imperative, object-oriented programming. To pick just one, obvious and easy example\u2014what are the <abbr>SOLID<\/abbr> principles?<\/p>\n<ul>\n<li>Single reponsibility<\/li>\n<li>Open\/closed<\/li>\n<li>Liskov substitution<\/li>\n<li>Interface segregation<\/li>\n<li>Dependency inversion<\/li>\n<\/ul>\n<p>You may not remember what it felt like the first time you encountered <abbr>SOLID<\/abbr>, but suffice it to say: \u201cLiskov substitution principle\u201d isn\u2019t any more intuitive or obvious than \u201cMonad\u201d. You\u2019re just familiar with one of them. The same is true of \u201capplicative\u201d and \u201cVisitor pattern\u201d. And so on. Granted, again: it would be nice for some of these things to have easier names, a <em>big<\/em> part of the pain here is just unfamiliarity.<\/p>\n<p>So, with that out of the way, what <em>is<\/em> functional programming?<\/p>\n<\/section>\n<section id=\"what-is-functional-programming\" class=\"level2\">\n<h2>What is functional programming?<\/h2>\n<p>Functional programming is a style of programming that uses <em>pure functions<\/em> and <em>immutable data<\/em> for as many things as possible, and builds programs primarily out of <em>functions<\/em> rather than other abstractions. I\u2019ll define all of those terms in a moment, but first\u2026<\/p>\n<section id=\"why-do-we-care\" class=\"level3\">\n<h3>Why do we care?<\/h3>\n<p>We care, frankly, because <em>we\u2019re not that smart<\/em>. Let\u2019s think about some of the kinds of things we\u2019re doing with, say, restaurant software: clients, with locations, building baskets, composed of products with options and modifiers, which have a set of rules for what combinations are allowed both of products and of their elements as making up a basket, which turn into orders, which have associated payment schemes (sometimes a lot of them), which generate data to send to a point-of-sale as well as summaries for the customer who ordered it, and so on. There are a <em>lot<\/em> of moving pieces there. I\u2019m sure a missed some non-trivial pieces, too. And if all of that is <em>stateful<\/em>, that\u2019s a lot of state to hold in your head.<\/p>\n<p>Let me be a bit provocative for a moment. Imagine you were reading a JavaScript module and it looked like this:<\/p>\n<pre class=\"js\"><code>var foo = 12;\nvar bar = &#39;blah&#39;;\nvar quux = { waffles: &#39;always&#39; };\n\nexport function doSomething() {\n  foo = 42;\n}\n\nexport function getSomething() {\n  bar = quux;\n  quux.waffles = &#39;never&#39;;\n  return bar;\n}<\/code><\/pre>\n<p>Everyone watching would presumably say, \u201cNo that\u2019s bad, don\u2019t do that!\u201d Why? Because there is <em>global state<\/em> being changed by those functions, and there\u2019s nothing about the functions which tells you what\u2019s going on. Global variables are bad. Bad bad bad. We all know this. Why is it bad? Because you have no idea when you call <code>doSomething()<\/code> or <code>getSomething()<\/code> what kinds of side effects it might have. And if <code>doSomething()<\/code> and <code>getSomething()<\/code> affect the same data, then the order you call them in matters.<\/p>\n<p>In a previous job, I spent literally months chasing a bunch of bugs in a C codebase where all of the state was global. <em>We don\u2019t do this anymore.<\/em><\/p>\n<p>But really, what\u2019s different about this?<\/p>\n<pre class=\"js\"><code>class AThing {\n  constructor() {\n    this.foo = 12;\n    this.bar = &#39;blah&#39;;\n    this.quux = { waffles: &#39;always&#39; };\n  }\n\n  doSomething() {\n    this.foo = 42;\n  }\n\n  getSomething() {\n    this.bar = this.quux;\n    this.quux.waffles = &#39;never&#39;;\n    return this.bar;\n  }\n}<\/code><\/pre>\n<p>We have some \u201cinternal\u201d data, just like we had in the module up above. And we have some public methods which change that state. In terms of these internals, it\u2019s the same. There are differences in terms of having <em>instances<\/em> and things like that, but in terms of understanding the behavior of the system\u2014understanding the state involved\u2014it\u2019s the same. It\u2019s global, mutable state. Now it\u2019s not global like attaching something to the <code>window<\/code> object in JavaScript, and that\u2019s good, but still: at the module or class level, it\u2019s just global mutable state, with no guarantees about how anything works. And this is normal\u2014endemic, even\u2014in object-oriented code. We encapsulate our state, but we have <em>tons<\/em> of state, it\u2019s all mutable, and as far as any given class method call is concerned, it\u2019s all global to that class.<\/p>\n<p>You have no idea, when you call a given object method, what it might do. The fact that you call it with an <code>Int<\/code> and get out a <code>String<\/code> tells you almost nothing. For all you know, it\u2019s triggering a <abbr>JSON-RPC<\/abbr> call using the int as the <abbr>ID<\/abbr> for the endpoint, which in turn triggers an operation, responds with another <abbr>ID<\/abbr>, which you then use to query a database, and load a string from there, which you then set on some other member of the object instance, and then return. Should you write a method that does that? Probably not. But you can; nothing stops you.<\/p>\n<p>When you call a method, you have no idea what it will do. JavaScript, TypeScript, C<sup>\u266f<\/sup>, it doesn\u2019t matter. You have literally no idea. And that makes things <em>hard<\/em>.<\/p>\n<ul>\n<li>It often makes fixing bugs hard, because it means you have to figure out which particular <em>state<\/em> caused the issue, and find a way to reproduce that state. Which usually means calling methods in a particular order.<\/li>\n<li>It makes testing hard. Again, it often entails calling methods in a particular order. It also means you often need mocks for all those outside-world things you\u2019re trying to do.<\/li>\n<\/ul>\n<p>Functional programming is an out. An escape hatch. An acknowledgement, a recognition, that holding all of this in our heads is too much for us. No one is that smart. And our software, even at its best, is hard to hold in our heads, hard to make sure that our changes don\u2019t break something seemingly unrelated, hard to see how the pieces fit together\u2014hard, in a phrase you\u2019ll often hear from functional programming fans, hard to reason about.<\/p>\n<p>So, how do we solve these problems? With functional programming!<\/p>\n<\/section>\n<section id=\"what-is-functional-programming-1\" class=\"level3\">\n<h3>What <em>is<\/em> functional programming?<\/h3>\n<p>Functional programming is basically combining four bigs ideas:<\/p>\n<ol type=\"1\">\n<li>First class functions<\/li>\n<li>Higher-order functions<\/li>\n<li>Pure functions<\/li>\n<li>Immutable data<\/li>\n<\/ol>\n<p>The combination of these things leads us to a <em>very<\/em> different style of programming than traditional <abbr>OOP<\/abbr>. Let\u2019s define them.<\/p>\n<section id=\"first-class-functions-and-higher-order-functions\" class=\"level4\">\n<h4>First class functions and higher-order functions<\/h4>\n<p>We\u2019ll start by looking at the things that are probably most familiar to you if you\u2019re a JavaScript developer (even if you haven\u2019t necessarily heard the names): first-class functions and higher-order functions.<\/p>\n<p>When we talk about <em>first class functions,<\/em> we mean that functions are just data\u2014they\u2019re first-class items in the language just like any other type. As such, a function is just another thing you can hand around as an argument to other functions. There\u2019s no distinction between a function and a number or a string or some complex data structure. This is essential because, when you combine it with higher-order functions, it allows for incredible <em>simplicity<\/em> and incredible <em>reusability<\/em>.<\/p>\n<p>Higher-order functions, in turn, are functions which take other functions as parameters or return them as their values. We\u2019ll see this in detail in a worked example in a few, but for right now, let\u2019s just use a really simple example that will be familiar to anyone who\u2019s done much JavaScript: using <code>map<\/code>.<\/p>\n<p>If we have a collection like an array and we want to transform every piece of data in it, we could of course do it with a for loop, and with iterable types we could use <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Statements\/for...of\"><code>for ... of<\/code><\/a>. But with <code>map<\/code>, we can just leave the implementation details of <em>how<\/em> the items in the array are iterated through, and instead worry about what we want to change. We can do that because <code>map<\/code> takes functions as arguments.<\/p>\n<pre class=\"js\"><code>const initialValues = [1, 2, 3];\nconst doubledValues = initialValues.map(value =&gt; value * 2);<\/code><\/pre>\n<p>We did it there with a function explicitly, but we could just as easily extract the function like this:<\/p>\n<pre class=\"js\"><code>const double = value =&gt; value * 2;\nconst initialValues = [1, 2, 3];\nconst doubledValues = initialValues.map(double);<\/code><\/pre>\n<p>This is possible because <em>functions are just data<\/em>\u2014they\u2019re first-class members of the language\u2014and therefore <em>functions can be arguments or return values<\/em>\u2014the language supports higher-order functions.<\/p>\n<\/section>\n<section id=\"pure-functions\" class=\"level4\">\n<h4>Pure functions<\/h4>\n<p>What about <em>pure functions<\/em>? Pure functions are functions with <em>no effects<\/em>. The input directly translates to the output, every time. The examples we looked at just a moment ago with <code>map<\/code> are all pure functions (and it\u2019s a really weird antipattern to use effectful functions with <code>map<\/code>! Don\u2019t do that! Use <code>forEach<\/code> if you must have an effect). Here are a few more super simple examples:<\/p>\n<pre class=\"js\"><code>const add = (a, b) =&gt; a + b;\nconst toString = (number) =&gt; `The value is ${number}`;\nconst toLength = (list) =&gt; list.length;<\/code><\/pre>\n<p>Here are some examples of straightforward functions which are <em>not<\/em> pure:<\/p>\n<pre class=\"js\"><code>const logDataFromEndpoint = (endpoint) =&gt; {\n  fetch(endpoint).then(response =&gt; {\n    console.log(response);\n  });\n};\n\nlet foo = 42;\nconst setFoo = (newValue) =&gt; {\n  foo = newValue;\n};\n\nconst getFoo = () =&gt; foo;<\/code><\/pre>\n<p>So a pure function is one whose output is <em>solely<\/em> determined by its input That means no talking to a database, no making <abbr>API<\/abbr> calls, no reading from or writing to disk.<\/p>\n<p>And of course, you can\u2019t do anything meaningful with <em>just<\/em> pure functions. We need user input, and we need to put the results of our computation somewhere. So the goal isn\u2019t to write <em>only<\/em> pure functions. It\u2019s to write <em>mostly<\/em> pure functions and to <em>isolate<\/em> all impure functions.<\/p>\n<p>What this gets us is two things:<\/p>\n<ol type=\"1\">\n<li>A much smaller list of things to worry about when we\u2019re looking at a given function.<\/li>\n<li>The ability to <em>compose<\/em> functions together more easily.<\/li>\n<\/ol>\n<p>We have fewer things to keep in our heads when we look at any given pure function, because we don\u2019t have to worry at all about whether something it touches has been changed by another function or not. We have inputs. We transform them into outputs. That\u2019s it. Compare these two things in practice.<\/p>\n<p>Here\u2019s a traditional <abbr>OOP<\/abbr> approach:<\/p>\n<pre class=\"js\"><code>class Order {\n  constructor() {\n    this.subTotal = 0.0;\n    this.taxRate = 0.01;\n  }\n\n  getTotal() {\n    return this.subTotal * (1 + this.taxRate);\n  }\n}\n\nconst order = new Order();\norder.subTotal = 42.00;\n\nconst total = order.getTotal();<\/code><\/pre>\n<p>Note that the total is always dependent on what has happened in the object. If we write <code>order.subTotal = 43<\/code>, <code>order.total<\/code> will change. So if we want to test how <code>total<\/code> behaves, or if there\u2019s a bug in it, we need to make sure we\u2019ve made all the appropriate transformations to the object ahead of time. That\u2019s no big deal here; the <code>total<\/code> getter is incredibly simple (and in fact, we\u2019d normally just write it with a property getter). But still, we have to construct an order and make sure all the relevant properties are set to get the right value out of <code>getTotal()<\/code>. Things outside the method call itself affect what we get back. We have no way to test <code>getTotal()<\/code> by itself, and no way to debug it if there\u2019s a bug without first doing some object setup.<\/p>\n<p>Now, here\u2019s a functional approach.<\/p>\n<pre class=\"js\"><code>const order = {\n  subTotal: 42.0,\n  taxRate: 0.01\n}\n\nconst getTotal = (subTotal, taxRate) =&gt; subTotal * (1 + taxRate);\nconst total = getTotal(order.subTotal, order.taxRate);<\/code><\/pre>\n<p>Note that the object is <em>just data<\/em>. It\u2019s a <em>record<\/em>. And the function just takes a couple of arguments. If there needed to be a more complicated transformation internally, we could do that just as easily. Note that it also decouples the structure of the data from the actual computation (though we could pass in a record as well if we had a good reason to).<\/p>\n<p>This makes it easily testable, for free. Want to make sure different tax rates get the correct output? Just\u2026 pass in a different tax rate. You don\u2019t have to do any complicated work setting up an object instance first (which is especially important for more complex data types). It also makes it easier to chase down any bugs: the only thing you have to care about is that simple function body. There\u2019s no other state to think about, because there\u2019s no state at all here from the perspective of the function: just inputs and outputs.<\/p>\n<p>This has one other <em>really<\/em> important consequence, which goes by the name <strong>referential transparency<\/strong>. All that means is that anywhere you see a pure function, you can always substitute the value it produces, or vice versa. This is quite unlike the <code>Order::getTotal()<\/code> method, where (a) it\u2019s attached to an object instance and (b) it\u2019s dependent on other things about that object. You can\u2019t just substitute it in, or freely move it around, when you\u2019re doing a refactor. <em>Maybe<\/em> you can, but you\u2019d better hope that all the other state is shuffled around with it correctly. Whereas, with the standalone <code>getTotal()<\/code> function, all you need is its arguments, and you\u2019ll always get the same thing back.<\/p>\n<p>This is just like math: if you say, <span class=\"math inline\"><em>x<\/em>\u2004=\u20045<\/span> when solving an algebraic equation, you can put <span class=\"math inline\">5<\/span> <em>anywhere you see <span class=\"math inline\"><em>x<\/em><\/span><\/em>; or, if it\u2019s useful for factoring the equation or something, you can just as easily put <span class=\"math inline\"><em>x<\/em><\/span> anywhere you see <span class=\"math inline\">5<\/span>. And in math, that\u2019s true for <span class=\"math inline\"><em>f<\/em>(<em>x<\/em>)<\/span> as well. When we use pure functions, it\u2019s true for programming, too! That makes refactoring much easier.<\/p>\n<p>As we\u2019ll see in the example I walk through in a minute, it also lets us <em>compose<\/em> functions together far more easily. If all we have are inputs and outputs, then I can take the output from one function and use it as the input to the next.<\/p>\n<\/section>\n<section id=\"immutable-data\" class=\"level4\">\n<h4>Immutable data<\/h4>\n<p>Complementing the use of mostly pure functions is to use <em>immutable data<\/em>. Instead of having objects which we mutate, we create copies of the data as we transform it.<\/p>\n<p>You\u2019re probably wondering how in the world this can work (and also how you avoid it being incredibly computationally expensive). For the most part, we can rely on two things: smart compilers and runtimes, and the fact that we often don\u2019t need to reuse the <em>exact<\/em> same data because we\u2019re transforming it. However, as we\u2019ll see below, in languages which don\u2019t have native support for immutability, it can impose a performance penalty. Gladly, there are ways to work around this!<\/p>\n<hr \/>\n<\/section>\n<\/section>\n<\/section>\n<section id=\"a-worked-example\" class=\"level2\">\n<h2>A Worked Example<\/h2>\n<p>Let\u2019s get down to a real example of these ideas. This is a \u2018code kata\u2019 I do every so often. In this particular kata, you get a list of burger orders which looks like this:<\/p>\n<pre class=\"js\"><code>[\n  { condiments: [&#39;ketchup&#39;, &#39;mustard&#39;, &#39;pickles&#39;] },\n  { condiments: [&#39;tomatoes&#39;] },\n  { condiments: [&#39;mustard&#39;, &#39;ketchup&#39;] },\n  \/\/ etc...\n]<\/code><\/pre>\n<p>You\u2019re supposed to take this list (of 10,000-some-odd burger variations!) and determine what the top ten most common orders (not just condiments, but orders) are. (The truth is, the list actually mostly looks like <code>condiments: ['ketchup']<\/code> over and over again.) So as a preliminary, you can assume that the data is being loaded like this:<\/p>\n<pre class=\"js\"><code>const getBurgers = () =&gt;\n  fetch(&#39;http:\/\/files.example.com\/burgers.json&#39;)\n    .then(request =&gt; request.json());<\/code><\/pre>\n<p>And we\u2019ll print our results (which will always end up in the same format) like this:<\/p>\n<pre class=\"js\"><code>const descAndCountToOutput = descAndCount =&gt; `${descAndCount[0]}: ${descAndCount[1]}`;<\/code><\/pre>\n<p>This is actually a perfect case to demonstrate how functional programming ideas can help us solve a problem.<\/p>\n<section id=\"imperative\" class=\"level3\">\n<h3>Imperative<\/h3>\n<p>First, let\u2019s look at what I think is a <em>relatively<\/em> reasonable imperative approach. Our basic strategy will be:<\/p>\n<ol type=\"1\">\n<li>Convert condiments to descriptions.\n<ol type=\"1\">\n<li>Convert the objects to just their lists of condiments.<\/li>\n<li>Sort those strings.<\/li>\n<li>Turn them into descriptions by joining them with a comma.<\/li>\n<\/ol><\/li>\n<li>Build up a mapping from description to count.<\/li>\n<li>Sort that by count.<\/li>\n<li>Get the top 10.<\/li>\n<li>Print out the results.<\/li>\n<\/ol>\n<pre class=\"js\"><code>getBurgers().then(burgers =&gt; {\n  let totals = {};\n\n  \/\/ 2. Build up a mapping from description to count.\n  for (let burger of burgers) {\n    \/\/ 1. Convert condiments to descriptions.\n    \/\/ 1.1. Convert the objects to just their lists of condiments.\n    const condiments = burger.condiments;\n    \/\/ 1.2. Sort those strings.\n    condiments.sort();\n    \/\/ 1.3. Turn them into descriptions by joining them with a comma.\n    const description = condiments.join(&#39;, &#39;);\n\n    \/\/ 2. Build up a mapping from description to count.\n    const previousCount = totals[description];\n    totals[description] = previousCount ? previousCount + 1 : 1;\n  }\n\n  \/\/ 3. Sort that by count.\n  const sortableCondiments = Object.entries(totals);\n  sortableCondiments.sort((a, b) =&gt; b[1] - a[1]);\n  \/\/ 4. Get the top 10.\n  const topTen = sortableCondiments.slice(0, 10);\n  \/\/ 5. Print out the results.\n  for (let descAndCount of topTen) {\n    console.log(descAndCountToOutput(descAndCount));\n  }\n});<\/code><\/pre>\n<p>That\u2019s pretty well-factored. But it\u2019s pretty wrapped up on the specific details of this problem, and there\u2019s basically nothing here I could reuse. It\u2019s also relatively hard to test. There aren\u2019t really a lot of pieces there we could break up into smaller functions if we wanted to figure out why something was broken. The way you\u2019d end up fixing a bug here is probably by dropping <code>debugger<\/code> or <code>console.log()<\/code> statements in there to see what the values are at any given spot.<\/p>\n<p>And this is where functional programming really does give us a better way.<\/p>\n<\/section>\n<section id=\"functional\" class=\"level3\">\n<h3>Functional<\/h3>\n<p>Instead of thinking about the specific details of <em>how<\/em> to get from A to B, let\u2019s think about what we start with and what we finish with, and see if we can build up a pipeline of transformations that will get us there.<\/p>\n<p>We start with a <em>list<\/em> of <em>objects<\/em> containing <em>arrays<\/em> of <em>strings<\/em>. We want to end up with a <em>list<\/em> of the <em>distinct combinations<\/em> and their <em>frequency<\/em>. How can we do this? Well, the basic idea is the same as what we did above:<\/p>\n<ol type=\"1\">\n<li>Convert condiments to descriptions.\n<ol type=\"1\">\n<li>Convert the objects to just their lists of condiments.<\/li>\n<li>Sort those strings.<\/li>\n<li>Turn them into descriptions by joining them with a comma.<\/li>\n<\/ol><\/li>\n<li>Build up a mapping from description to count.<\/li>\n<li>Sort that by count.<\/li>\n<li>Get the top 10.<\/li>\n<li>Print out the results.<\/li>\n<\/ol>\n<p>To someone acquainted with functional programming, that looks like a bunch of <code>map<\/code>s, a <code>reduce<\/code>, and some <code>sort<\/code>s. And each of those using just simple, pure functions. Let\u2019s see what that might look like. First, what are our transformations?<\/p>\n<p>The step 1 transformations are all quite straightforward:<\/p>\n<pre class=\"js\"><code>\/\/ 1. Convert condiments to descriptions.\n\/\/ 1.1. Convert the objects to just their lists of condiments.\nconst toCondiments = burger =&gt; burger.condiments ? burger.condiments : [];\n\/\/ 1.2. Sort those strings.\nconst toSortedCondiments = condiments =&gt; condiments.concat().sort();\n\/\/ 1.3. Turn them into descriptions by joining them with a comma.\nconst toDescriptions = condiments =&gt; condiments.join(&#39;, &#39;);<\/code><\/pre>\n<p>Step 2 is a little more involved: it involves building up a new data structure (<code>totals<\/code>) from an old one. This function is a <em>reducer<\/em>: it will build up <code>totals<\/code> by updating <code>totals<\/code> with each <code>description<\/code> from an array of them.<\/p>\n<pre class=\"js\"><code>\/\/ 2. Build up a mapping from description to count.\nconst toTotals = (totals, description) =&gt; {\n  const previousCount = totals[description];\n  const count = previousCount ? previousCount + 1 : 1;\n  totals[description] = count;\n  return totals;\n};\n\n\/\/ 3. Sort that by count.\nconst byCount = (a, b) =&gt; b[1] - a[1];<\/code><\/pre>\n<p>We\u2019ll see how to get just 10 in a moment; for now, let\u2019s also wrap up the output:<\/p>\n<pre class=\"js\"><code>\/\/ 5. Print it out\nconst output = value =&gt; { console.log(value); };<\/code><\/pre>\n<p>These are our base building blocks, and we\u2019ll re-use them in each of the approaches I cover below. Note that we\u2019ve now taken those same basic steps from our imperative approach and turned them into standalone, testable functions. They\u2019re small and single-purpose, which always helps. But more importantly, (with two exceptions we\u2019ll talk about in a minute) all of those transformations are <em>pure functions<\/em>, we know that we\u2019ll get the same results every time we use them. If I want to make sure that burger condiments are converted correctly, I can test <em>just that function<\/em>.<\/p>\n<pre class=\"js\"><code>describe(&#39;toCondiments&#39;, () =&gt; {\n  it(&#39;returns an empty list when there is no `condiments`&#39;, () =&gt; {\n    toCondiments({}).should.deepEqual([]);\n  });\n\n  it(&#39;returns the list of condiments when it is passed&#39;, () =&gt; {\n    const condiments = [&#39;ketchup&#39;, &#39;mustard&#39;];\n    toCondiments({ condiments }).should.deepEqual(condiments);\n  });\n})<\/code><\/pre>\n<p>This is a trivial example, of course, but it gets the point across: all we have to do to test this is pass in an object. It doesn\u2019t depend on anything else. It doesn\u2019t have <em>any knowledge<\/em> of how we\u2019re going to use it. It doesn\u2019t know that it\u2019s going to be used with data coming from an array. All it knows is that if you give it an object with a <code>condiments<\/code> property, it\u2019ll hand you back the array attached to that property.<\/p>\n<p>The result is that, with all of these functions, we don\u2019t have to deal with mocks or stubs or anything like that to be testable. Input produces output. Pure functions are great for this. Now, some of you may be thinking, \u201cThat\u2019s great, but what about <abbr>I\/O<\/abbr>, or databases, or any other time we actually interact with the world? What about talking to a point-of-sale?\u201d I actually have some tentative thoughts about a future tech talk to look at how to do that in some detail, but for today, just remember that the goal is to write as many pure functions as possible, and to isolate the rest of your code from knowing about that. And of course, that\u2019s best practice anyway! We\u2019re just codifying it. We\u2019ll see what that looks like in practice in just a minute.<\/p>\n<p>Now, while we\u2019re on the topic of pure functions, some of you with quick eyes may have noticed that two of these little functions we laid out are actually <em>not<\/em> pure: JavaScript\u2019s <code>Array.sort<\/code> method operates in-place, for performance reasons, and so does our <code>toTotals<\/code> function. So a truly pure version of the sorting function looks like this:<\/p>\n<pre class=\"js\"><code>const toSortedCondiments = condiments =&gt; condiments.concat().sort();<\/code><\/pre>\n<p>Similarly, we <em>could<\/em> define the <code>toTotals<\/code> to return a new object every time, like this:<\/p>\n<pre class=\"js\"><code>const toTotals = (totals, description) =&gt; {\n  const previousCount = totals[description];\n  const count = previousCount ? previousCount + 1 : 1;\n  const update = { [description]: count };\n  return Object.assign({}, totals, update);\n};<\/code><\/pre>\n<p>Unfortunately, given the amount of data we\u2019re dealing with, that\u2019s prohibitively expensive. We end up spending a <em>lot<\/em> of time allocating objects and garbage-collecting them. As a result, it\u2019s tens of thousands of times slower. Running it on my 4GHz iMac, the in-place version takes less than 40ms. Doing it the strictly pure way\u2014returning copies every time\u2014takes ~53s. And if you profile it, almost all of that time is spent in <code>assign<\/code> (52.95s).<\/p>\n<p>This takes us to an important point, though: it\u2019s actually not a particularly big deal to have this particular data changed in place, because we\u2019re not going to do anything <em>else<\/em> with it. And in fact, under the hood, this is exactly what pure functional languages do with these kinds of transformations\u2014precisely because it\u2019s perfectly safe to do so, because we\u2019re the only ones who have access to this data. We\u2019re generating a <em>new<\/em> data structure from the data that we were originally handed, and the next function will make its own new data structure (whether a copy or something else).<\/p>\n<p>In other words, when we\u2019re talking about a <em>pure function<\/em>, we don\u2019t really care about internal mutability (though of course, that can bite us if we\u2019re not careful). We\u2019re really concerned about <em>external<\/em> mutability. As long as the same inputs get the same outputs every time, the rest of the world doesn\u2019t have to care how we got that result.<\/p>\n<p>Now let\u2019s see how we use these functions.<\/p>\n<section id=\"pure-javascript\" class=\"level4\">\n<h4>Pure JavaScript<\/h4>\n<p>First, here\u2019s a pure-JavaScript approach, but a more functional one instead of an imperative one:<\/p>\n<pre class=\"js\"><code>getBurgers().then(burgers =&gt; {\n  const descriptionToCount = burgers\n    .map(toCondiments)\n    .map(toSortedCondiments)\n    .map(toDescriptions)\n    .reduce(toTotals, {})\n\n  const entries = Object.entries(descriptionToCount);\n\n  [...entries]\n    .sort(byCount)\n    .slice(0, 10)  \/\/ 4. Get the top 10.\n    .map(descAndCountToOutput)\n    .forEach(output);\n});<\/code><\/pre>\n<p>First, the good: our transformation is no longer all jumbled together. In fact, our code reads a lot like our original description did. Also, notice that we just have a bunch of functions operating on data: none of the functions used here have any knowledge about where the data comes from that they operate on.<\/p>\n<p>But then we also have a couple things that are a <em>little<\/em> bit clunky. The main thing that sticks out is that sudden stop in the chain in the middle.<\/p>\n<p>When we\u2019re dealing with the <code>Array<\/code> type, everything is fine, but when we convert our data into a <code>Map<\/code>, we no longer have that option, so we have to jump through some hoops to do the transformation back into the data type we need. We\u2019re stuck if the object type doesn\u2019t have the method we need. We\u2019re kind of trying to mash together the imperative and functional styles, and it\u2019s leaving us in a little bit of a weird spot.<\/p>\n<p>There\u2019s another issue here, though, and it\u2019s the way that using the method-style calling convention obscures something important. When we call <em>most<\/em> of those methods, we\u2019re doing something quite different from what most <em>methods<\/em> do. A method normally is an operation on an object. These methods\u2014most of them\u2014are operations that return <em>new<\/em> objects. So it\u2019s nice from a syntax perspective, but if we\u2019re not <em>already<\/em> familiar with the behavior of a given method, it won\u2019t be clear at all that we\u2019re actually generating a bunch of totally new data by calling those methods.<\/p>\n<p>And\u2026 two of these methods (<code>sort<\/code> and <code>forEach<\/code>) <em>are<\/em> not doing that, but are modifying an array in place instead.<\/p>\n<\/section>\n<section id=\"lodash\" class=\"level4\">\n<h4>Lodash<\/h4>\n<p>The first step away from this problem is to use a tool like <a href=\"https:\/\/lodash.com\">Lodash<\/a>.<\/p>\n<pre class=\"js\"><code>\/\/ More functional, with _:\n\/\/ We tweak how a few of these work slightly to play nicely.\nconst _toDescriptions = condiments =&gt; _.join(condiments, &#39;, &#39;);\nconst _byCount = _.property(1);\n\ngetBurgers().then(burgers =&gt; {\n  const condiments = _.map(burgers, toCondiments);\n  const sortedCondiments = _.map(condiments, toSortedCondiments);\n  const descriptions = _.map(sortedCondiments, _toDescriptions);\n  const totals = _.reduce(descriptions, toTotals, {});\n  const totalPairs = _.toPairs(totals);\n  const sortedPairs = _.sortBy(totalPairs, _byCount);\n  const sortedPairsDescending = _.reverse(sortedPairs);\n  const topTen = _.take(sortedPairsDescending, 10);\n  const forOutput = _.map(topTen, descAndCountToOutput)\n  _.forEach(forOutput, output);\n});<\/code><\/pre>\n<p>But it seems like we lost something when we moved away from the object-oriented approach. Being able to chain things, so that each item worked with the previous item, was actually pretty nice. And needing all these intermediate variables is <em>not<\/em> so nice.<\/p>\n<p>One way around this is to use Lodash\u2019s <code>_.chain<\/code> method. That would have let us write it like this:<\/p>\n<pre class=\"js\"><code>getBurgers().then(burgers =&gt; {\n  const foo = _.chain(burgers)\n    .map(toCondiments)\n    .map(toSortedCondiments)\n    .map(_toDescriptions)\n    .reduce(toTotals, {})\n    .toPairs()\n    .sortBy(_byCount)\n    .reverse()\n    .take(10)\n    .map(descAndCountToOutput)\n    .value()\n    .forEach(output);\n});<\/code><\/pre>\n<p>And that <em>is<\/em> a win. But it only works because JavaScript is <em>incredibly<\/em> dynamic and lets us change the behavior of the underlying <code>Array<\/code> type. (You\u2019d have a much harder time doing that in Java or C<sup>\u266f<\/sup>!)<\/p>\n<p>Perhaps just as importantly, it requires us to make sure that we do that <code>_.chain()<\/code> call on on anything we want to tackle this way. So, can we get the benefits of this some <em>other<\/em> way? Well, obviously the answer is <em>yes<\/em> because I wouldn\u2019t be asking otherwise.<\/p>\n<\/section>\n<section id=\"with-ramda.\" class=\"level4\">\n<h4>With Ramda.<\/h4>\n<p>But we can actually go a bit further, and end up in a spot where we don\u2019t need to modify the object prototype at all. We can just do this with a series of standalone functions which don\u2019t depend on being attached to <em>any<\/em> object. If we use the <a href=\"http:\/\/ramdajs.com\">Ramda<\/a> library,<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> we can tackle this with nothing but functions.<\/p>\n<pre class=\"js\"><code>const getTop10Burgers = R.pipe(\n  R.map(R.prop(&#39;condiments&#39;)),\n  R.map(R.sortBy(R.toString)),\n  R.map(R.join(&#39;, &#39;)),\n  R.reduce(toTotals, {}),\n  R.toPairs,\n  R.sortBy(R.prop(1)),  \/\/ will give us least to greatest\n  R.reverse,\n  R.take(10),\n  R.map(descAndCountToOutput)\n);\n\nreturn getBurgers()\n  .then(getTop10Burgers)\n  .then(R.forEach(output));<\/code><\/pre>\n<p>Notice the difference between here and even where we started with Lodash: we\u2019re no longer dependent on a specific piece of data being present. Instead, we\u2019ve created a standalone function which can operate on that data, simply by \u201cpiping\u201d together\u2014that is, <em>composing<\/em>\u2014a bunch of other, smaller functions. The output from each one is used as the input for the next.<\/p>\n<p>One of the many small niceties that falls out of this is that we can refactor this just by pulling it apart into smaller acts of compositions.<\/p>\n<p>Here\u2019s an example of how we might use that. We defined those simple transformations for the condiments as a set of three functions, which converted them from objects with <code>condiments<\/code> elements, sorted them, and joined them into a string. Now, let\u2019s build those into meaningful functions for each step:<\/p>\n<pre class=\"js\"><code>\/\/ 1. Convert condiments to descriptions.\nconst burgerRecordsToDescriptions = R.pipe(\n  R.map(R.prop(&#39;condiments&#39;)),\n  R.map(R.sortBy(R.toString)),\n  R.map(R.join(&#39;, &#39;)),\n);\n\n\/\/ 2. Build up a mapping from description to count.\nconst descriptionsToUniqueCounts = R.pipe(\n  R.reduce(toTotals, {}),\n  R.toPairs,\n);\n\n\/\/ 3. Sort that by count.\nconst uniqueCountsToSortedPairs = R.pipe(\n  R.sortBy(R.prop(1)),\n  R.reverse,\n);\n\n\/\/ For (4), to get the top 10, we&#39;ll just use `R.take(10)`.\n\/\/ We could also alias that, but it doesn&#39;t gain us much.\n\n\/\/ 5. Print it out\nconst sortedPairsToConsole = R.pipe(\n  R.map(descAndCountToOutput),\n  R.forEach(output)\n);<\/code><\/pre>\n<p>Then we can put those together into another, top-level function to do <em>exactly<\/em> our steps.<\/p>\n<pre class=\"js\"><code>const getTop10Burgers = R.pipe(\n  burgerRecordsToDescriptions,  \/\/ (1)\n  descriptionsToUniqueCounts,   \/\/ (2)\n  uniqueCountsToSortedPairs,    \/\/ (3)\n  R.take(10)                    \/\/ (4)\n);\n\ngetBurgers()\n  .then(getTop10Burgers)\n  .then(sortedPairsToConsole);  \/\/ (5)<\/code><\/pre>\n<p>Notice that, because each step is just composing together functions, \u201crefactoring\u201d is easy. And, to be sure, you have to be mindful about what comes in and out of each function. But that\u2019s true in the imperative approach, too: you always have to keep track of the state of the object you\u2019re building up, but there you\u2019re doing it in the middle of a loop, so you\u2019re keeping track of a lot <em>more<\/em> state at any given time. Functions with simple inputs and outputs give us a more explicit way of specifying the structure and state of the data at any given time. That\u2019s true even in JavaScript, but it goes double if we\u2019re in a typed language like F<sup>\u266f<\/sup>, Elm, etc., where we can specify those types for the function as a way of designing the flow of the program. (That\u2019s such a helpful way of solving problems, in fact, that I may also do a talk on type-driven design in the future!)<\/p>\n<p>Note, as well, that we\u2019ve now completely isolated our input and output from everything else. The middle there is a chain of pure functions, built out of other pure functions, which neither know nor care that the data came in from an <abbr>API<\/abbr> call, or that we\u2019re going to print it to the console when we finish.<\/p>\n<hr \/>\n<p>So this takes us back around to that first question: why do we care? At the end of the day, is this really a win over the imperative style? Is the final version, using Ramda, really better than the pure-JavaScript mostly-functional version we used at first?<\/p>\n<p>Obviously, I think the answers there are yes. The Ramda version there at the end is <em>way<\/em> better than the imperative version, and substantially better than even the first \u201cfunctional\u201d JavaScript versions we wrote.<\/p>\n<p>For me, at least, the big takeaway here is this: we just built a small but reasonable transformation of data out of a bunch of really small pieces. That has two big consequences\u2014consequences we\u2019ve talked about all along the way, but which you\u2019ve now seen in practice:<\/p>\n<ol type=\"1\">\n<li><p>Those pieces are easy to test. If something isn\u2019t working, I can easily take those pieces apart and test them individually, or test the result of any combination of them. As a result, I can test any part of that pipe chain, and I can <em>fix<\/em> pieces independent of each other. No part depends on being in the middle of a looper where transformations are done to other parts.<\/p><\/li>\n<li><p>Because they\u2019re small and do one simple things, I can recombine those pieces any way I like. And you see that in the Ramda examples in particular: most of what we\u2019re doing in those examples is not even something we wrote ourselves. They\u2019re also <em>really<\/em> basic building blocks, available in basically every standard library.<\/p><\/li>\n<\/ol>\n<p>One last thing: if you\u2019re curious about performance\u2026 you should know that it does matter for data at scale. In my tests (which are admittedly extremely unscientific; unfortunately, I couldn\u2019t get JSPerf running nicely with this particular set of variations), I found that the time it took to run these varied depending on the approach <em>and<\/em> the library. With a ~10k-record data set:<\/p>\n<ul>\n<li>The imperative version, unsurprisingly, was the fastest, taking ~16\u201317ms.<\/li>\n<li>After that, the chained lodash version and the pure-<abbr>JS<\/abbr> version were comparable, at ~32\u201336ms, or around twice as long to finish as the imperative version.<\/li>\n<li>The plain lodash version was consistently a <em>little<\/em> slower yet, at ~38\u201343ms.<\/li>\n<li>Ramda is <em>slow<\/em>: both variations consistently took over 90ms to finish.<\/li>\n<\/ul>\n<p>Those differences added up on larger data sets: dealing with ~10,000,000 records, the times ranged from ~12s for the imperative version, to ~15s for the lodash and pure-<abbr>JS<\/abbr> variants, to ~50s for the Ramda version.<\/p>\n<p>They were all pretty darn quick. Compilers, including JavaScript <abbr>JIT<\/abbr>s, are incredibly smart. Mostly you can just trust them; come back and profile before you even <em>think<\/em> about optimizing things. But you <em>should<\/em> know the performance characteristics of different libraries and consider the implications of what the language does well and what it doesn\u2019t. Ramda is likely slower because of the way it curries every function\u2014something that works well in languages with native support for it, e.g.\u00a0F<sup>\u266f<\/sup> or Elm or Haskell, but imposes a penalty in languages which don\u2019t\u2026 like JavaScript. That said, if you\u2019re not in the habit of processing tens of thousands of records, you\u2019re probably okay using any of them.<\/p>\n<\/section>\n<\/section>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>or <a href=\"https:\/\/github.com\/lodash\/lodash\/wiki\/FP-Guide\">lodash-fp<\/a>, but Ramda is a bit better documented and I just like it a little better<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Fri, 11 Nov 2016 22:30:00 -0500","guid":"tag:v4.chriskrycho.com,2016-11-11:\/2016\/what-is-functional-programming.html","category":["software development","functional programming","javascript"]},{"title":"Rust vs. React Native\u2014What?","link":"http:\/\/v4.chriskrycho.com\/2016\/rust-vs-react-native-what.html","description":"<p><i class=editorial>I was recently discussing some thoughts I\u2019ve had on building a top-notch application experience in a Slack team I belong to, and noted that I believe that a Rust core with native UIs is a <em>massively<\/em> winning strategy. A friend in the group responded that he thinks \u201cReact + JS is eating the world right now\u201d and that \u201cRust as awesome for if you want to write a JS vm, or something like that\u2026 or a compiler\u2026 anything involving lots of speed and stability.\u201d What follows is my response, lightly edited to remove details specific to that friend and to add a few further thoughts.<\/i><\/p>\n<hr \/>\n<blockquote>\n<p>Here\u2019s the thing: I don\u2019t <em>care<\/em> what\u2019s eating the world today, for three reasons:<\/p>\n<ol type=\"1\">\n<li>I just want to build the best stuff I can build, and native UIs are still massively better than React and even React Native<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> in innumerable ways. There are clear advantages to React Native + JavaScript, and times when you absolutely should take that approach. But there are also a lot of times and reasons why you shouldn\u2019t. Heck, even if you just want killer performance <em>in browsers<\/em>, our future includes things like Rust-to-WebAssembly, and that\u2019s a good thing.<\/li>\n<li>What was eating the world five years ago? Ten? Is it still eating the world today? I don\u2019t feel obliged to follow those trends (not least because, not being a consultancy, following those trends doesn\u2019t buy me anything for the things I want to do; your tradeoffs and mine look way different).<\/li>\n<li>I\u2019m actually getting really tired of just treating as acceptable or normative the performance characteristics of browsers. Browsers are awesome. But we can (and should) do a <em>lot<\/em> better in terms of user experience, and I don\u2019t see browsers catching up to what you can do with e.g.\u00a0Cocoa (Touch). Sure, that doesn\u2019t matter that much for building yet-another-storefront. (Again, there are different tradeoffs for every single app!) But why in the world are we in a spot now where one of the most popular text editors in the world is <em>slower<\/em> than any text editor of five years ago? That\u2019s not a <em>necessary<\/em> decision, and you can (and should) go after the same degree of ease-of-extensibility that Atom has had\u2014perhaps even using things like HTML and CSS for skinning!\u2014while not tying yourself to the browser and its upsides and downsides for <em>everything<\/em>. We have <em>incredibly<\/em> powerful machines, and the user experience is often getting <em>slower<\/em>. I\u2019m looking for ways to change that.<\/li>\n<\/ol>\n<p>Again, JS+React<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> may be <em>exactly<\/em> the right tradeoff for a lot of apps, and given what consultancies (like my friends\u2019s!) are doing, I think doing that with ReactNative for apps is a <em>very<\/em> good move. It makes good sense business-wise, and it makes good sense in terms of the apps you\u2019re likely to be delivering. Don\u2019t hear me for a second saying Rust is the best for <em>everything<\/em>. I think it, or something like it, is a very good choice for <em>many<\/em> things, though, and it shouldn\u2019t be dismissed simply because it\u2019s a very different world from doing Ruby or Elixir or JavaScript.<\/p>\n<\/blockquote>\n<hr \/>\n<p><i class=editorial>So much for my initial response. On reflection, I wanted to expand it a bit. So here\u2019s another few hundred words!<\/i><\/p>\n<p>Beyond this, I think there\u2019s a bit of a false dichotomy here: the idea that \u201clots of speed and stability\u201d <em>aren\u2019t<\/em> values we should be seeking more aggressively for <em>all<\/em> our apps. Fully granted that not every app needs the same <em>degree<\/em> of each of those, and moreover that there are a lot of ways to get to those goals. Still: speed and stability are <em>core<\/em> user experience values. I don\u2019t really care how you get at those goals, whether it\u2019s with Rust, or Elixir or Clojure, or, yes, React with TypeScript or <a href=\"https:\/\/flowtype.org\">Flow<\/a>. I <em>do<\/em> think that Rust is, for the moment at least, uniquely positioned to add real value in this space because it gives screaming performance but with so many niceties we\u2019re used to when writing languages like Python or Ruby and so much of the power you get in languages like OCaml or F\u266f.<a href=\"#fn3\" class=\"footnote-ref\" id=\"fnref3\" role=\"doc-noteref\"><sup>3<\/sup><\/a> But at the end of the day, I think <em>all<\/em> apps should focus much more on speed and stability than they do today. We have supercomputers in our pockets, and we\u2019re often shipping apps that are slower and more finicky.<\/p>\n<p>But I have this dream of a world where apps aren\u2019t needlessly power-hungry or memory-intensive, where every swipe and or click or scroll results in buttery-smooth responses. We won\u2019t get there by saying, \u201cYou know, Facebook is doing <em>x<\/em> so that\u2019s good enough for me.\u201d<\/p>\n<p>Of course every developer, and any given product shop or consultancy, is going to have to make decisions about which stacks it invests in. If you\u2019re primarily shipping web applications, investing in Elixir and React with React Native for your apps is a very sensible move. Most of your clients\u2019 native apps may not <em>need<\/em> the degree of polished performance you might get from writing their iOS app in Swift and their Android app in Kotlin and the core in Rust (or even C++). That tradeoff is a <em>tradeoff<\/em>.<\/p>\n<p>But let\u2019s remember that there is real value there, and that some apps <em>do<\/em> deserve that investment. We should evaluate the tradeoffs at every turn, and our core considerations should enduringly include <em>speed and stability<\/em>. Don\u2019t dismiss Rust (or Swift, or F\u266f) out of hand.<\/p>\n<p>Equally importantly, we need to stop assuming that just because something is eating the world today means it\u2019s also the future. Betting big on Flash in the mid-2000s wasn\u2019t a <em>bad<\/em> move by a long shot. But its massive popularity then wasn\u2019t a good predictor for its future. That goes double, frankly, for projects coming out of Facebook or Google or similar: big companies like that have the resources to drop everything and use a new language, or a new tool, as it suits them. If you don\u2019t believe me, look at the actual open-source records of both of those companies! What\u2019s hot today is far more relevant to a consultancy than to a product shop. And in both cases, choosing tech suitable for the job at hand is more important yet.<\/p>\n<p>My friend gets that, for what it\u2019s worth. He\u2019s making the right moves for his business as the owner of a consultancy. I just want him\u2014and lots of other people\u2014to see where languages like Rust and Swift and F\u266f might be worth considering. And speed and stability matter in a lot of places besides just compilers and VMs.<\/p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>I\u2019m aware that React-Native ultimately binds down to native widgets. It\u2019s still not quite the same.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>or, frankly, Ember or whatever else; React is great, but it is also overhyped.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn3\" role=\"doc-endnote\"><p>Swift too, and honestly for a lot of things Swift is an easier experience for not <em>that<\/em> much less performance than Rust. But as of today you <em>can\u2019t<\/em> ship core functionality in Swift for Android or Windows.<a href=\"#fnref3\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Fri, 07 Oct 2016 08:20:00 -0400","guid":"tag:v4.chriskrycho.com,2016-10-07:\/2016\/rust-vs-react-native-what.html","category":["JavaScript","Rust","Swift","F Sharp","software development"]},{"title":"Y Combinators, how do they even work?","link":"http:\/\/v4.chriskrycho.com\/2016\/y-combinators-how-do-they-even-work.html","description":"<p><i class=editorial>I was reading <a href=\"http:\/\/matt.might.net\/articles\/implementation-of-recursive-fixed-point-y-combinator-in-javascript-for-memoization\/\">a post<\/a> by <a href=\"http:\/\/matt.might.net\">Matt Might<\/a>, a computer science professor at the University of Utah, about Y Combinators, and I was having a hard time tracking with some of it just by reading. The way I normally solve this problem is to write it out\u2014and, optimally, to write it out in something roughly like <a href=\"https:\/\/wiki.haskell.org\/Literate_programming\">Literate Haskell<\/a> or <a href=\"http:\/\/coffeescript.org\/#literate\">Literate CoffeeScript<\/a>. That\u2019s exactly what you\u2019ll find below; this is basically <em>commentary<\/em> on Might\u2019s original post.<\/i><\/p>\n<p><i class=editorial>A few other prefatory notes:<\/i><\/p>\n<ol type=\"1\">\n<li><i class=editorial>Since this is commentary, I\u2019m not focusing on explaining combinators in general. For a very helpful explanation, though, both of what combinators are and why you\u2019d ever want to use them, <a href=\"http:\/\/programmers.stackexchange.com\/a\/117575\">read this<\/a>.<\/i><\/li>\n<li><i class=editorial>The Y Combinator itself isn\u2019t all that useful for ordinary programming. It <em>is<\/em> really useful as a way of thinking about how programming <em>works<\/em>, and that\u2019s why I was reading about it and trying to figure out what was going on in Might\u2019s original post.<\/i><\/li>\n<li><i class=editorial>This didn\u2019t actually all make sense to me until I also read Might\u2019s post, <a href=\"http:\/\/matt.might.net\/articles\/python-church-y-combinator\/\">\u201cEquational derivations of the Y combinator and Church encodings in Python\u201d<\/a>. Which is a crazy post. But kind of fun. <\/i><\/li>\n<\/ol>\n<hr \/>\n<p>Note for background (this was new to me today): <span class=\"math inline\"><em>\u03bb<\/em><em>v<\/em>.<em>e<\/em><\/span> is the function which maps v to e. In ECMAScript 2015 or later (hereafter just JS):<\/p>\n<pre class=\"js\"><code>const \u03bbv_e = v =&gt; e<\/code><\/pre>\n<p>The Y Combinator is a higher-order functional: it is a function which takes a functional\/higher-order function. Quoting from Might:<\/p>\n<blockquote>\n<p>The Y combinator takes a functional as input, and it returns the (unique) fixed point of that functional as its output. A functional is a function that takes a function for its input. Therefore, the fixed point of a functional is going to be a function.<\/p>\n<\/blockquote>\n<p>And a \u201cfixed point\u201d is an input to a function equal to the <em>output<\/em> of the function. (Not all functions have such.) A fixed point is where <span class=\"math inline\"><em>f<\/em>(<em>x<\/em>)\u2004=\u2004<em>x<\/em><\/span>. He uses the example <span class=\"math inline\"><em>x<\/em>\u2004=\u2004<em>x<\/em><sup>2<\/sup>\u2005\u2212\u20051<\/span>, which has two solutions, two <em>fixed points<\/em>.<\/p>\n<p>He starts out with the total recursion form\u2014also known as the \u201ccrash all the things!\u201d form\u2014of the Y-combinator. (I\u2019m using letters to denote the version of the combinator; this is Y-naive.)<\/p>\n<pre class=\"js\"><code>const Yn = (F) =&gt; F(Yn(F))  \/\/ all the recursing!<\/code><\/pre>\n<p>\u201cCrash all the things\u201d\u2026 because of one pesky little detail: it calls itself immediately, and so recurses infinitely. Which is actually kind of a problem.<\/p>\n<p>Might then asks: What if we transformed this a bit? He notes that we can <em>transform<\/em> with lambda calculus to expand what we\u2019re doing, so:<\/p>\n<figure>\n<span class=\"math inline\"><em>Y<\/em>(<em>F<\/em>)\u2004=\u2004<em>F<\/em>(<em>\u03bb<\/em><em>x<\/em>.(<em>Y<\/em>(<em>F<\/em>))(<em>x<\/em>))<\/span>\n<\/figure>\n<p>(I haven\u2019t done this kind of thing since undergraduate math work I did for physics, but as I was thinking about it, it made sense. I\u2019m used to trying to <em>remove<\/em> extraneous variables when dealing with software, but in this case we\u2019re using it as a tool for transforming the equation into a form that is <em>equivalent<\/em> but <em>expressed differently<\/em>.)<\/p>\n<p>And <span class=\"math inline\"><em>\u03bb<\/em><em>x<\/em>.(<em>Y<\/em>(<em>F<\/em>))(<em>x<\/em>)<\/span> is equivalent to the fixed point. It\u2019s the function which takes <span class=\"math inline\"><em>x<\/em><\/span> as an argument and results in <span class=\"math inline\"><em>Y<\/em>(<em>F<\/em>)(<em>x<\/em>)<\/span>; but <span class=\"math inline\"><em>Y<\/em>(<em>F<\/em>)<\/span> is just another argument, so this looks just like our original <span class=\"math inline\"><em>f<\/em>(<em>x<\/em>)\u2004=\u2004<em>x<\/em><\/span>, but with <span class=\"math inline\"><em>Y<\/em>(<em>F<\/em>)<\/span> substituted for <span class=\"math inline\"><em>f<\/em><\/span>. Can we write this in JS?<\/p>\n<p>Here\u2019s my implementation, using modern JS; note that it still recurses. (I\u2019m calling this updated Y-transformed, so <code>Yt<\/code>.)<\/p>\n<pre class=\"js\"><code>const Yt = (F) =&gt; F((x) =&gt; Yt(F)(x))<\/code><\/pre>\n<p>His version:<\/p>\n<pre class=\"js\"><code>function Y(F) { return F(function(x) { return Y(F)(x); }); }<\/code><\/pre>\n<p>Mine and his are equivalent; here\u2019s his version transformed to modern JS:<\/p>\n<pre class=\"js\"><code>const Y = (F) =&gt; F((x) =&gt; Y(F)(x))<\/code><\/pre>\n<p>Might then says:<\/p>\n<blockquote>\n<p>Using another construct called the U combinator, we can eliminate the recursive call inside the Y combinator, which, with a couple more transformations gets us to:<\/p>\n<\/blockquote>\n<p>I hated it when profs (or books!) did this when I was in college, and it frustrates me here, too. I want to <em>see<\/em> the transformation. I really wish Might didn\u2019t skip how the U combinator works or what transformations he applies, because then he jumps to this form:<\/p>\n<figure>\n<span class=\"math inline\"><em>Y<\/em>\u2004=\u2004(<em>\u03bb<\/em><em>h<\/em>.<em>\u03bb<\/em><em>F<\/em>.<em>F<\/em>(<em>\u03bb<\/em><em>x<\/em>.((<em>h<\/em>(<em>h<\/em>))(<em>F<\/em>))(<em>x<\/em>)))(<em>\u03bb<\/em><em>h<\/em>.<em>\u03bb<\/em><em>F<\/em>.<em>F<\/em>(<em>\u03bb<\/em><em>x<\/em>.((<em>h<\/em>(<em>h<\/em>))(<em>F<\/em>))(<em>x<\/em>)))<\/span>\n<\/figure>\n<p>Writing this out in JS is going to be a real bear. More to the point, I don\u2019t know how he got to it; now I need to go look up the U Combinator it seems.<\/p>\n<p>\u2026which I\u2019ve <a href=\"http:\/\/www.ucombinator.org\">now done<\/a>. So:<\/p>\n<blockquote>\n<p>In the theory of programming languages, the U combinator, <span class=\"math inline\"><em>U<\/em><\/span>, is the mathematical function that applies its argument to its argument; that is <span class=\"math inline\"><em>U<\/em>(<em>f<\/em>)\u2004=\u2004<em>f<\/em>(<em>f<\/em>)<\/span>, or equivalently, <span class=\"math inline\"><em>U<\/em>\u2004=\u2004<em>\u03bb<\/em><em>f<\/em>.<em>f<\/em>(<em>f<\/em>)<\/span>.<\/p>\n<\/blockquote>\n<ul>\n<li>That is, the U Combinator is the case where you apply a function to itself: <span class=\"math inline\"><em>U<\/em>(<em>f<\/em>)\u2004=\u2004<em>f<\/em>(<em>f<\/em>)<\/span>\u2014you can see that in the result there, where the first expression is the same as the argument handed to it (and both are functions). It\u2019s also there in the <span class=\"math inline\"><em>h<\/em>(<em>h<\/em>)<\/span> calls.<\/li>\n<li>The transformations are just transforming from a function-argument for to a lambda form, I think. The kind of thing where you go from <code>function a(b) { return c }<\/code> to <code>var a = function(b) { return c }<\/code> in JS. (Better, in <em>modern<\/em> JS, to <code>const a = (b) =&gt; c<\/code>.)<\/li>\n<\/ul>\n<p>I\u2019ll return to that in a moment. First, writing up the JS. The innermost term is (repeated) <span class=\"math inline\"><em>\u03bb<\/em><em>x<\/em>.((<em>h<\/em>(<em>h<\/em>))(<em>F<\/em>))(<em>x<\/em>)<\/span>, so we\u2019ll start by writing this out.<\/p>\n<pre class=\"js\"><code>const \u03bb_inner = (x) =&gt; (h(h)(F))(x)<\/code><\/pre>\n<p>We need the definition of <span class=\"math inline\"><em>h<\/em><\/span> next; this comes from further out, the transformation <span class=\"math inline\"><em>\u03bb<\/em><em>h<\/em>.<em>\u03bb<\/em><em>F<\/em>.<em>F<\/em>(<em>\u03bb<\/em><sub><em>i<\/em><\/sub><em>n<\/em><em>n<\/em><em>e<\/em><em>r<\/em>)<\/span> (where we\u2019re substituting the <code>\u03bb_inner<\/code> we just wrote to make this a bit easier to get our heads around).<\/p>\n<p>Remembering that each \u201c.\u201d in the equation represents a mapping, i.e.\u00a0a JS function call, we have this (writing it with function definitions starting new lines to clarify):<\/p>\n<p>Here\u2019s what I came up with as a fairly direct translation into JS:<\/p>\n<pre class=\"js\"><code>const Y = (\n  (h) =&gt;\n    (F) =&gt; F((x) =&gt; (h(h)(F))(x))  \/\/ substituting \u03bb_inner from above\n) (\n  (h) =&gt;\n    (F) =&gt; F((x) =&gt; (h(h)(F))(x))  \/\/ substituting \u03bb_inner from above\n)<\/code><\/pre>\n<p>His (note that things are aligned as they are so that it\u2019s clear which functions match up):<\/p>\n<pre class=\"js\"><code>var Y = function (F) {\n return (function (x) {\n  return F(function (y) { return (x(x))(y);});\n  })\n        (function (x) {\n  return F(function (y) { return (x(x))(y);});\n  }) ;\n} ;<\/code><\/pre>\n<p>His transformed to modern JS:<\/p>\n<pre class=\"js\"><code>const Y = (F) =&gt; (\n  (x) =&gt; F((y) =&gt; x(x)(y))\n) (\n  (x) =&gt; F((y) =&gt; x(x)(y))\n)<\/code><\/pre>\n<p>His and mine are not <em>quite<\/em> the same (though I know they\u2019re equivalent because they both work). I really wish he\u2019d explained how he got <em>this<\/em> substitution as well! More importantly, I wish he\u2019d been consistent in his notation; changing variable names is\u2026 frustrating when you\u2019re trying to follow someone\u2019s work.<\/p>\n<p><i class=editorial>When I get stuck on something like <em>this<\/em>, the way I figure it out is by writing out how the substitutions would work at each step. See below.<\/i><\/p>\n<p>In any case, now that we have the Y combinator, we can use it with <code>FactGen<\/code>, a functional which, if you pass it the factorial function, passes back the factorial function. <code>FactGen<\/code> itself isn\u2019t recursive. But with the Y Combinator, it builds a function which is <em>not<\/em> recursive; it doesn\u2019t reference itself anywhere. It just needs the right kind of \u201cfactory\u201d: a function which returns <em>another<\/em> funtion which itself <em>is<\/em> recursive. Here\u2019s a standard recursive factorial implementation (identical to the one Might supplies, though modernized):<\/p>\n<pre class=\"js\"><code>const FactGen =\n  (fact) =&gt;\n    (n) =&gt; n === 0 ? 1 : n * fact(n - 1)<\/code><\/pre>\n<p>You call that like this:<\/p>\n<pre class=\"js\"><code>Y(FactGen)(5)  \/\/ 120<\/code><\/pre>\n<p>The <code>Y(FactGen)<\/code> call gets back a function which then runs on whatever input you hand it (a fairly standard pattern with curried arguments), so you could also write it like this:<\/p>\n<pre class=\"js\"><code>const factorial = Y(FactGen)\nfactorial(5)  \/\/ 120<\/code><\/pre>\n<p>But I\u2019m still not sure how his and mine are equivalent.<\/p>\n<p>A note: wrapping things in <code>(...)<\/code> in JS defines that wrapped content as a distinct <em>expression<\/em>. As long as the type of a given expression is a function, it can be called with an argument. So <code>(function() {})()<\/code> or <code>(() =&gt; {})()<\/code> takes a no-operation function and immediately executes it.<\/p>\n<p>So in his Y combinator, the substitution goes like this:<\/p>\n<pre class=\"js\"><code>const Y = (F) =&gt; (  \/\/ F is FactGen\n  \/\/ x is the identical function passed as argument below\n  (x) =&gt;\n    \/\/ Run FactGen by taking the function below as its `fact`\n    \/\/ argument.\n    F(\n      \/\/ `y` is the argument passed to the result of Y, e.g.\n      \/\/ `fact(5)`. Recall that `x` is the function below; we\n      \/\/ call it with itself. Calling x(x) will get the actual\n      \/\/ factorial function returned by `FactGen`.\n      (y) =&gt; x(x)(y)\n    )\n\/\/ We close the *expression* which defines the outer function,\n\/\/ and call it with this next expression as an argument.\n) (\n  \/\/ and x here is the same function, passed as argument\n  (x) =&gt;\n    \/\/ Again, run `FactGen` with this function as its argument.\n    F(\n      \/\/ `y`, again, will be the integer. `x(x)` again will be\n      \/\/ the actual factorial function.\n      (y) =&gt; x(x)(y)\n    )\n)<\/code><\/pre>\n<p>This is pretty funky! But it works; the two anonymous functions call <em>each other<\/em> rather than recursing directly.<\/p>\n<p>In mine, it goes like this, instead:<\/p>\n<pre class=\"js\"><code>const Ymine = (\n  \/\/ Where in Might&#39;s example, the `x` function was where the\n  \/\/ U Combinator was applied, here (because I followed the\n  \/\/ original notation he gave) it&#39;s `h`. So it&#39;s `h` which is\n  \/\/ the same function handed back and forth as argument\n  \/\/ to itself.\n  (h) =&gt;\n    \/\/ `h` takes a functional, which takes `FactGen` as its\n    \/\/ parameter. This is similar to the outermost function in\n    \/\/ Might&#39;s version.\n    (F) =&gt;\n      \/\/ As in Might&#39;s version, we call `FactGen` here.\n      F(\n        \/\/ The form is *similar* but not identical to his,\n        \/\/ because of the extra call structure. `h(h)(F)` is the\n        \/\/ factorial function.\n        \/\/\n        \/\/ Note that then he has `y` where I have `x`; my `x`\n        \/\/ and his `y` are just the result of the computation\n        \/\/ (in this case, the integer factorial).\n        (x) =&gt; (h(h)(F))(x))\n) (\n  \/\/ This is identical to the above; it&#39;s using the U Combinator.\n  (h) =&gt; (F) =&gt; F((x) =&gt; (h(h)(F))(x))\n)<\/code><\/pre>\n<p>This is how his simplification worked: instead of generating the factorial function each time, it generated it just the once and then <em>used<\/em> it.<\/p>\n<p>I still couldn\u2019t <em>do<\/em> the simplification he did myself. It\u2019ll take more practice using and thinking about combinators and combinatorial logic before I get there, but that\u2019s okay. That\u2019s how learning works.<\/p>\n<p>And that\u2019s enough playing with combinatorials for now. (Except that I\u2019m kind of tempted to see if I can go implement the U or Y combinators\u2014or both\u2014in Rust.)<\/p>\n<hr \/>\n<p><i class=editorial>If you\u2019re curious how I worked this out\u2026 I expanded the JS representations of the final forms (<a href=\"\/\/v4.chriskrycho.com\/extra\/ycombinator.js\">here\u2019s the code<\/a>) and then stepped through the result in my JavaScript dev tools, watching how the function calls worked and what the values of each intermediate value were. It\u2019s fascinating, and well worth your time.<\/i><\/p>\n","pubDate":"Sun, 19 Jun 2016 09:20:00 -0400","guid":"tag:v4.chriskrycho.com,2016-06-19:\/2016\/y-combinators-how-do-they-even-work.html","category":["javascript","software development","programming languages"]},{"title":"Testing Ember.js Mixins (and Helpers) With a Container","link":"http:\/\/v4.chriskrycho.com\/2016\/testing-emberjs-mixins-with-a-container.html","description":"<p><i>Updated to note that the same concerns apply to helpers. You can always see the full revision history of this item <a href=\"https:\/\/github.com\/chriskrycho\/chriskrycho.com\/commits\/master\/content\/tech\/ember-js-mixins-container.md\">here<\/a>.<\/i><\/p>\n<hr \/>\n<p>Today I was working on an Ember.js <a href=\"http:\/\/emberjs.com\/api\/classes\/Ember.Mixin.html#content\">mixin<\/a> for the new mobile web application we\u2019re shipping at Olo, and I ran into an interesting problem when trying to test it.<\/p>\n<p>When you\u2019re testing mixins (or helpers), you\u2019re generally not working with the normal Ember container.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> In fact, the default test setup for mixins doesn\u2019t have <em>any<\/em> container in play. It just looks like this (assuming you ran <code>ember generate mixin bar<\/code> in an app named <code>foo<\/code>):<\/p>\n<pre class=\"js\"><code>import Ember from &#39;ember&#39;;\nimport BarMixin from &#39;foo\/mixins\/bar&#39;;\nimport { module, test } from &#39;qunit&#39;;\n\nmodule(&#39;Unit | Mixin | bar&#39;);\n\n\/\/ Replace this with your real tests.\ntest(&#39;it works&#39;, function(assert) {\n  let BarObject = Ember.Object.extend(BarMixin);\n  let subject = BarObject.create();\n  assert.ok(subject);\n});<\/code><\/pre>\n<p>Note two things:<\/p>\n<ol type=\"1\">\n<li>It uses the basic Qunit <code>module<\/code> setup, not the ember-qunit <code>moduleFor<\/code> setup.<\/li>\n<li>It assumes you\u2019re generating a new object instance for every single test.<\/li>\n<\/ol>\n<p>Both of those assumptions are fine, <em>if you don\u2019t need to interact with the container<\/em>. In many cases, that\u2019s perfectly reasonable\u2014I\u2019d go so far as to say that most mixins and helpers probably <em>shouldn\u2019t<\/em> have any dependency on the container.<\/p>\n<p>In the specific case I was working on, however, the point of the mixin was to abstract some common behavior which included all the interactions with a <a href=\"https:\/\/guides.emberjs.com\/v2.6.0\/applications\/services\/\">service<\/a>. This meant making sure the dependency injection worked in the unit test. This in turn meant dealing with the container. So let\u2019s see what was involved in that. (You can generalize this approach to any place in the Ember ecosystem where you need to test something which doesn\u2019t normally have the container set up.)<\/p>\n<p>We start by switching from the basic <code>qunit<\/code> helpers to using the <code>ember-qunit<\/code> helpers.<\/p>\n<pre class=\"js\"><code>\/\/ Replace this...\nimport { module, test } from &#39;qunit&#39;;\nmodule(&#39;Unit | Mixin | bar&#39;);\n\n\/\/ with this:\nimport { moduleFor, test } from &#39;ember-qunit&#39;;\nmoduleFor(&#39;mixin:bar&#39;, &#39;Unit | Mixin | Bar&#39;);<\/code><\/pre>\n<p>The <code>moduleFor()<\/code> helper has two things going for it\u2014one of which we <em>need<\/em>, and one of which isn\u2019t strictly <em>necessary<\/em>, but has some nice functionality. In any case, this will help when registering a container. Those two features:<\/p>\n<ol type=\"1\">\n<li>It does support the use of the container. In fact, it\u2019s declaring how this mixin relates to the container in the first argument to the helper function: <code>'mixin:foo'<\/code> is the definition of the mixin for injection into the container.<\/li>\n<li>Any functions we define on the options argument we can pass to the <code>moduleFor()<\/code> helper are available on the <code>this<\/code> of the test.<\/li>\n<\/ol>\n<p>Now, in the first version of this, I had set up a common <code>Ember.Object<\/code> which had mixed in the <code>BarMixin<\/code>, so:<\/p>\n<pre class=\"js\"><code>const BarObject = Ember.Object.extend(BarMixin);<\/code><\/pre>\n<p>Then, in each test, I created instances of this to use:<\/p>\n<pre class=\"js\"><code>test(&#39;test some feature or another&#39;, function(assert) {\n  const subject = BarObject.create();\n  \/\/ ...do stuff and test it with `assert.ok()`, etc.\n});<\/code><\/pre>\n<p>The problem was that any of those tests which required a container injection always failed. Assume we have a service named <code>quux<\/code>, and that it\u2019s injected into the mixin like this in <code>foo\/app\/mixins\/bar.js<\/code>:<\/p>\n<pre class=\"js\"><code>import Ember from &#39;ember&#39;;\n\nexport default Ember.Mixin.create({\n  quux: Ember.inject.service()\n});<\/code><\/pre>\n<p>Any test which actually tried to <em>use<\/em> <code>quux<\/code> would simply fail because of the missing container (even if you specified in the test setup that you needed the service):<\/p>\n<pre><code>test(&#39;it uses quux somehow&#39;, function(assert) {\n  const subject = BarObject.create();\n  const quux = subject.get(&#39;quux&#39;);  \/\/ throws Error\n});<\/code><\/pre>\n<p>Specifically, you will see <code>Attempting to lookup an injected property on an object without a container<\/code> if you look in your console.<\/p>\n<p>Taking advantage of the two <code>ember-qunit<\/code> features, though, we can handle all of this.<\/p>\n<pre class=\"js\"><code>import Ember from &#39;ember&#39;;\nimport { moduleFor, test } from &#39;ember-qunit&#39;;\n\nconst { getOwner } = Ember;\n\nmoduleFor(&#39;mixin:bar&#39;, &#39;Unit | Mixin | bar&#39;, {\n  \/\/ The `needs` property in the options argument tells the test\n  \/\/ framework that it needs to go find and instantiate the `quux`\n  \/\/ service. (Note that if `quux` depends on other injected\n  \/\/ services, you have to specify that here as well.)\n  needs: [&#39;service:quux&#39;],\n\n  \/\/ Again: any object we create in this options object will be\n  \/\/ available on the `this` of every `test` function below. Here,\n  \/\/ we want to get a &quot;test subject&quot; which is attached to the\n  \/\/ Ember container, so that the container is available to the\n  \/\/ test subject itself for retrieving the dependencies injected\n  \/\/ into it (and defined above in `needs`).\n  subject() {\n    BarObject = Ember.Object.extend(BarMixin);\n\n    \/\/ This whole thing works because, since we&#39;re in a\n    \/\/ `moduleFor()`, `this` has the relevant method we need to\n    \/\/ attach items to the container: `register()`.\n    this.register(&#39;test-container:bar-object&#39;, BarObject);\n\n    \/\/ `Ember.getOwner` is the public API for getting the\n    \/\/ container to do this kind of lookup. You can use it in lots\n    \/\/ of places, including but not limited to tests. Note that\n    \/\/ that because of how the dependency injection works, what we\n    \/\/ get back from the lookup is not `BarObject`, but an\n    \/\/ instance of `BarObject`. That means that we don&#39;t need to\n    \/\/ do `BarObject.create()` when we use this below; Ember\n    \/\/ already did that for us.\n    return getOwner(this).lookup(&#39;test-container:bar-object&#39;);\n  }\n});\n\ntest(&#39;the mixin+service does what it should&#39;, function(assert) {\n  \/\/ We start by running the subject function defined above. We\n  \/\/ now have an instance of an `Ember.Object` which has\n  \/\/ `BarMixin` applied.\n  const subject = this.subject();\n\n  \/\/ Now, because we used a test helper that made the container\n  \/\/ available, declared the dependencies of the mixin in `needs`,\n  \/\/ and registered the object we&#39;re dealing with here, we don&#39;t\n  \/\/ get an error anymore.\n  const quux = subject.get(&#39;quux&#39;);\n});<\/code><\/pre>\n<p>So, in summary:<\/p>\n<ol type=\"1\">\n<li>Use the <code>ember-qunit<\/code> helpers if you need the container.<\/li>\n<li>Define whatever dependencies you have in <code>needs<\/code>, just as you would in any other test.<\/li>\n<li>Register the mixin-derived object (whether <code>Ember.Object<\/code>, <code>Ember.Route<\/code>, <code>Ember.Component<\/code>, or whatever else) in a method on the options argument for <code>moduleFor()<\/code>. Use that to get an instance of the object and you\u2019re off to the races!<\/li>\n<\/ol>\n<p>One final consideration: while in this case it made good sense to use this approach and make the service injection available for the test, there\u2019s a reason that the tests generated by Ember CLI don\u2019t use <code>moduleFor()<\/code> by default. It\u2019s a quiet but clear signal that you should reevaluate whether this <em>is<\/em> in fact the correct approach.<\/p>\n<p>In general, mixins are best used for self-contained units of functionality. If you <em>need<\/em> dependency injection for them, it may mean that you should think about structuring things in a different way. Can all the functionality live on the service itself? Can all of it live in the mixin instead of requiring a service? Can the service calls be delegated to whatever type is using the mixin?<\/p>\n<p>But if not, and you <em>do<\/em> need a mixin which injects a service, now you know how to do it!<\/p>\n<hr \/>\n<p><strong>Side note:<\/strong> The documentation around testing mixins is relatively weak, and in general the testing docs are the weak bits in the Ember guides right now.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> After a conversation with <a href=\"https:\/\/github.com\/rwjblue\">@rwjblue<\/a> on the <a href=\"https:\/\/ember-community-slackin.herokuapp.com\">Ember Community Slack<\/a>, though, I was able to get a handle on the issue, and here we are. Since it stumped me, I\u2019m guessing I\u2019m not the only one.<\/p>\n<p>When this happens, <em>write it up<\/em>. I\u2019ve been guilty of this too often in the past few months: learning something new that I couldn\u2019t find anywhere online, and then leaving it stored in my own head. It doesn\u2019t take a particularly long time to write a blog post like this, and if you\u2019re stuck, chances are <em>very<\/em> good someone else is too.<\/p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>If you\u2019re not familiar with the \u201ccontainer\u201d, this is where all the various dependencies are registered, and where Ember looks them up to inject them when you use methods like <code>Ember.inject.service()<\/code>.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>Something I intend to help address in the next week or two via a pull request, so if you\u2019re my Ember.js documentation team friend and you\u2019re reading this\u2026 it\u2019s coming. \ud83d\ude09<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Thu, 09 Jun 2016 20:35:00 -0400","guid":"tag:v4.chriskrycho.com,2016-06-09:\/2016\/testing-emberjs-mixins-with-a-container.html","category":["emberjs","javascript","software development"]},{"title":"The Future of JavaScript","link":"http:\/\/v4.chriskrycho.com\/2016\/the-future-of-javascript.html","description":"<p>I gave a short tech talk at my new employer <a href=\"http:\/\/www.olo.com\">Olo<\/a> today, covering a number of the changes current and forthcoming in ECMAScript 2015 and later. Alas, I ran out of time in preparation and didn\u2019t get to cover everything I wanted\u2014I would have liked very much to cover modules, and to cover fat-arrow-functions in more depth than I did. I\u2019ll look forward to hopefully giving further tech talks at Olo in the future, and perhaps giving this one, expanded and finished out a bit, elsewhere. (If you\u2019d like me to give a talk, including this one, just let me know!) In the meantime, you can take a look at the <a href=\"\/\/v4.chriskrycho.com\/talks\/es-future-olo\">slides<\/a>, which I think will be helpful and interesting!<\/p>\n<p>And yes, there <em>were<\/em> a lot of really delightful <em>Doctor Who<\/em> references in this talk. Because <em>of course<\/em> there were!<\/p>\n","pubDate":"Wed, 02 Mar 2016 12:30:00 -0500","guid":"tag:v4.chriskrycho.com,2016-03-02:\/2016\/the-future-of-javascript.html","category":["talks","software development","programming languages","javascript"]},{"title":"HTML5 Location, <base>, and SVG","link":"http:\/\/v4.chriskrycho.com\/2015\/html5-location-base-and-svg.html","description":"<p>For quite some time, I have been frustrated by a bug in HolyBible.com: Firefox would not render SVGs using the <code>&lt;use xlink:xhref=\"#some-SVG-ID\"&gt;&lt;\/use&gt;<\/code> pattern. Today, I set aside my ongoing work on new user-facing functionality and dedicated what working time I had to hunting down the cause of this and fixing it at last.<\/p>\n<p>I was surprised to find the culprit: the <code>&lt;base&gt;<\/code> tag. If you don\u2019t know what the <code>&lt;base&gt;<\/code> tag is, you\u2019re not alone. It is <em>not<\/em> used all that much in general, and I had never actually seen it on a site before starting on this project last year.<\/p>\n<p>So what went wrong? How do these two things play together?<\/p>\n<p>I am using (and reusing) SVG items throughout the HolyBible.com interface, taking advantage of the ability to define symbols and reference them with the <code>&lt;use&gt;<\/code> tag, like so:<\/p>\n<pre class=\"html\"><code>&lt;svg version=&quot;1.1&quot; xmlns=&quot;http:\/\/www.w3.org\/2000\/svg&quot; xmlns:xlink=&quot;http:\/\/www.w3.org\/1999\/xlink&quot; xmlns:ev=&quot;http:\/\/www.w3.org\/2001\/xml-events&quot; style=&quot;display: none&quot;&gt;\n  &lt;symbol id=&quot;logo-shape&quot; viewBox=&quot;0 0 256 256&quot;&gt;\n    &lt;title&gt;Logo&lt;\/title&gt;\n    &lt;desc&gt;The HolyBible.com logo: sunrise breaking over an open book (the Bible).&lt;\/desc&gt;\n    &lt;path id=&quot;logo-light&quot; d=&quot;M172.1 116.3l5.1-4.1-12.5-.5 32-26.3-41.4 18.4 11-20.1L148 96l12.2-37.5L138.8 91l.1-36.2-10.3 34.4L114 36.1l4.3 54.9-22.2-34.9 13 39.9-18.3-12.4 11 20.1-42.5-19.2 32.8 26.9-10.4.8 4.4 3.9c13.1-1.6 27.4-2.7 42.4-2.7 15.4 0 30.1 1.2 43.6 2.9z&quot;\/&gt;\n    &lt;path id=&quot;logo-book&quot; d=&quot;M199.9 219.9c-47.4-9.8-96.4-9.8-143.8 0-6-28.9-12-57.7-17.9-86.6 59.3-12.3 120.4-12.3 179.7 0-6 28.9-12 57.8-18 86.6z&quot;\/&gt;\n  &lt;\/symbol&gt;\n&lt;\/svg&gt;\n\n&lt;!-- somewhere else on the page --&gt;\n&lt;svg&gt;\n  &lt;use xlink:href=&quot;#logo-shape&quot;&gt;&lt;\/use&gt;\n&lt;\/svg&gt;<\/code><\/pre>\n<p>Throughout all my early prototyping, this worked perfectly across all modern browsers. (For more, see <a href=\"https:\/\/css-tricks.com\/svg-sprites-use-better-icon-fonts\/\">CSS Tricks<\/a>.) Now, when I started moving from the prototype phase into actually building the application in Angular last fall, I learned that you have to set the base URL for the application using the <code>&lt;base&gt;<\/code> tag to use the HTML5 Location API with Angular 1.x. If you want URL-based, rather than <code>#<\/code>-based navigation in an Angular app, you need this. Following the recommendation of whatever documentation and tutorials I found, I set it so:<\/p>\n<pre class=\"html\"><code>&lt;base href=&quot;\/&quot;&gt;<\/code><\/pre>\n<p>Again, this was the recommendation I saw in every bit of documentation and every tutorial, so I assumed it would have no problems. As it turns it, that\u2019s not the case. (This is a <a href=\"http:\/\/v4.chriskrycho.com\/2015\/how-to-build-a-single-page-app-api-right.html\">recurring theme<\/a> in my experience with Angular.) In Chrome, Safari, and IE9+, this works exactly as expected. In Firefox, however, it does <em>not<\/em>. The use of the <code>&lt;base&gt;<\/code> tag changes the behavior of <code>#<\/code>-based URLs on a page. Specifically, it makes it so that if you\u2019re at a URL that <em>isn\u2019t<\/em> the base route, anchor links don\u2019t behave as expected. In order to make the <code>&lt;use&gt;<\/code> tag as expected, we would have to use the same URL as the base tag. Among other things, this would require making sure that any place we used the <code>&lt;use&gt;<\/code> tag, we would have to set that\u2014not exactly a good idea, given that it would entail an awful lot of changes if the base URL were ever changed.<\/p>\n<p>What if, instead, we did this?<\/p>\n<pre class=\"html\"><code>&lt;script&gt;document.write(&#39;&lt;base href=&quot;&#39; + document.location.origin + &#39;&quot; \/&gt;&#39;);&lt;\/script&gt;<\/code><\/pre>\n<p>This way, when the page renders, it writes the document location based on the <em>current<\/em> location. The URL history still behaves as expected with Angular, but the relative URLs for IDs behave as expected in Firefox again, while not breaking the behavior in any other browsers.<\/p>\n<p>But\u2026 then you\u2019ll navigate to another page, and Firefox will be back to not working.<\/p>\n<p>The <a href=\"https:\/\/github.com\/angular\/angular.js\/issues\/8934#issuecomment-56568466\">solution<\/a>, it turns out, only came into being after I\u2019d done the initial implementation, and I have no idea how much later it found its way into the Angular docs. However, even though it now <em>exists<\/em> in the docs, it\u2019s by no means obvious why you should do it this way, and certainly no mention of SVG! This might not seem odd to you\u2026 but it should, given that the only reason that Angular introduced this API change was to account for <em>exactly this issue<\/em>.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p>\n<p>As the Angular docs note, leaving out the <code>&lt;base&gt;<\/code> tag means all your URLs have to be absolute if you want to use HTML5 location and the <code>$locationProvider<\/code>. If you want to use SVGs with <code>&lt;use&gt;<\/code> and Firefox, though, that\u2019s what you have to do (and therefore that\u2019s what I\u2019m doing).<\/p>\n<p>Fun times, right?<\/p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>The closest it gets is this reference:<\/p>\n<blockquote>\n<p>Links that only contain a hash fragment (e.g.\u00a0<code>&lt;a href=\"#target\"&gt;<\/code>) will only change <code>$location.hash()<\/code> and not modify the url otherwise. This is useful for scrolling to anchors on the same page without needing to know on which page the user currently is.<\/p>\n<\/blockquote>\n<p>Even this, however, only <em>hints<\/em> at the root of the SVG issue.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Sat, 20 Jun 2015 10:30:00 -0400","guid":"tag:v4.chriskrycho.com,2015-06-20:\/2015\/html5-location-base-and-svg.html","category":["software development","angularjs","javascript"]},{"title":"How to Build a Single-Page App API Right","link":"http:\/\/v4.chriskrycho.com\/2015\/how-to-build-a-single-page-app-api-right.html","description":"<p>When I was first working on HolyBible.com, I struggled for quite a while to wrap my head around the right way to structure its API\u2014and in truth, I actually didn\u2019t come up with what I would call the <em>right<\/em> solution. I came up with a <em>working<\/em> solution, and the site performs all right, most of the time. However, our goal as developers shouldn\u2019t be \u201call right, most of the time.\u201d It should be \u201creally well, all the time.\u201d A big part of what I did wrong came from the bad advice I found in reading up on the issue along the way. This is my shot at helping you, dear reader, avoid making the same mistake.<\/p>\n<section id=\"the-challenge\" class=\"level2\">\n<h2>The challenge<\/h2>\n<p>When building a client-side application, we need to get the data for each view so that we can render it. In the case of HolyBible.com, that means everything from actual Bible text to study Bible notes, about pages, etc. The question is <em>how<\/em> to do this: we need to be able to load an actual page from our server, and we need a way to request data (rather than whole pages) from the server.<\/p>\n<p>(More experienced developers already know where this is going: that last sentence there has the key to this whole thing. I know. But the internet <em>doesn\u2019t.<\/em> I learned this the hard way.)<\/p>\n<section id=\"the-mistake\" class=\"level3\">\n<h3>The mistake<\/h3>\n<p>Here\u2019s the mistake I made: I built the Bible data API as (essentially) a <em>single<\/em> endpoint. When I went looking for advice on how to build this in Angular and Node\/Express, every single tutorial or blog post I found outlined the same basic solution: routes for your data endpoints, and catch-all route that returns the basic frame page for everything else. So, for HolyBible.com, that would come out with route matchers for e.g.\u00a0<code>\/data\/gen.1.1<\/code>, and for any other specific routes needed (for other views, static resources, etc.), with a default behavior of just dropping a static, basically empty template at the catchall <code>*<\/code> route. Then, once the application has loaded, it can inspect the URL and load the relevant data.<\/p>\n<p>This works. It\u2019s exactly what I did on HolyBible.com, in fact. But it\u2019s <em>slow<\/em>.<\/p>\n<p>Don\u2019t get me wrong: the time until the initial page load is actually relatively quick (though I plan to improve it substantially over the next couple months). The real problem is that the initial page load <em>doesn\u2019t include any content<\/em>.<\/p>\n<p>I <em>hate<\/em> this. That\u2019s why people are on the site: not to see my neat skills with JavaScript, just to read the Bible. And they have to wait, because once the page <em>does<\/em> load, Angular has to spin up the full application, see what content <em>should<\/em> have been loaded, and request it.<\/p>\n<\/section>\n<section id=\"the-solution\" class=\"level3\">\n<h3>The solution<\/h3>\n<p>Don\u2019t write <em>one<\/em> API. Write <em>two<\/em>. They should be structured nearly identically, but one of them will be a <em>page<\/em> API endpoint, and one will be a <em>data<\/em> API endpoint. In the context of HolyBible.com, here\u2019s how that would play out.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a> One endpoint would be based purely on the standard URL, something like <code>holybible.com\/jhn.3.16<\/code>. The other would be to retrieve a set of <em>data<\/em> associated with a given address, like <code>holybible.com\/data\/jhn.3.16<\/code>. This is only a little different from the approach suggested above, but that small difference matters\u2014in fact, it matters a <em>lot<\/em>.<\/p>\n<p>Instead of having the <code>\/jhn.3.16<\/code> route get handled by a catchall <code>*<\/code> route on the back end, it gets its own API endpoint, which looks for URLS of this shape and hands back a full page. That API endpoint is responsible to actually render the content of the page appropriately\u2014in this case, with something like the whole chapter of John 3.<a href=\"#fn2\" class=\"footnote-ref\" id=\"fnref2\" role=\"doc-noteref\"><sup>2<\/sup><\/a> <em>That<\/em> gets handed back to the browser, so the very first thing the user sees is not a blank page while the JavaScript framework spins up and requests data, but rather <em>the Bible text they asked for in the first place<\/em>.<\/p>\n<p>Meanwhile, the JavaScript framework <em>can<\/em> spin up, and load any required session data, etc. and start managing the UI like normal. Once we get to this point, the framework can go ahead and request a data payload from the <code>\/data\/&lt;reference&gt;<\/code> endpoint. So, for example, if there is a navigation control on the page (as on HolyBible.com and indeed most sites), clicking to navigate to Job 14 could, instead of requesting <code>\/job.14.4<\/code>, fetch the data from the other endpoint by running an AJAX request to <code>\/data\/job.14.4<\/code>.<\/p>\n<p>The backend thus supplies <em>both<\/em> a <code>\/&lt;resource&gt;<\/code> and a <code>\/data\/&lt;resource&gt;<\/code> route. This might seem redundant, but we\u2019ve just seen why it isn\u2019t, Moreover, if you have any logic that needs to be in place\u2014in our example here, a Bible reference parser, for example, to decide what content should be supplied\u2014you can easily reuse it between the two routes. The differences is simply in the form of the data returned: is it a fully-rendered template, or just the data?<\/p>\n<\/section>\n<\/section>\n<section id=\"so-what\" class=\"level2\">\n<h2>So what?<\/h2>\n<p>This approach has two big advantages over the catch-all approach that was frequently recommended in e.g.\u00a0Angular SPA tutorials I read.<\/p>\n<ol type=\"1\">\n<li><p>It\u2019s <em>progressive enhancement<\/em>. If the JavaScript fails, or the user has it disabled, or it fails to load because it\u2019s loaded asynchronously, the user still gets the page they asked for. Moreover, as long as the page content is build carefully (links built appropriately for other content, and so on), the entire application could continue to work even if the JavaScript <em>never<\/em> becomes available.<\/p><\/li>\n<li><p>It\u2019s <em>performant<\/em>. Loading the content this way will be <em>much<\/em> faster than the standard approach recommended for single-page apps. As noted above, it gets the content to the user immediately, then lets the JavaScript UI bits come into play. Since future page loads can take advantage of both caching and smaller data payloads, the whole thing can actually be faster than either a pure client-side <em>or<\/em> a pure server-side approach. That is, once the client-side application is running, it can just update its views with data delivered via AJAX, rather than reloading the whole page. But <em>before<\/em> that, the user doesn\u2019t have to wait to see something useful until the JavaScript framework spins up.<\/p><\/li>\n<\/ol>\n<p>It\u2019s not often an approach gives you progressive enhancement and actually increases the performance of an application, but this one does. Better yet, you can apply this in just about any framework: it\u2019s equally applicable to AngularJS with ExpressJS, Backbone with Rails, Ember with Django, Aurelia with Phoenix, or any other combination you come up with.<\/p>\n<\/section>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>Note: this is <em>not<\/em> the actual API structure of HolyBible.com, or even particularly close to it. Remember, I learned everything I\u2019m writing here by doing it <em>wrong<\/em>.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<li id=\"fn2\" role=\"doc-endnote\"><p>Or possibly a section which constitutes a semantic block of data. I have some thoughts on chunking Bible data semantically rather than by chapter and verse for this kind of thing. That\u2019s another post for another day, though.<a href=\"#fnref2\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Tue, 09 Jun 2015 22:16:00 -0400","guid":"tag:v4.chriskrycho.com,2015-06-09:\/2015\/how-to-build-a-single-page-app-api-right.html","category":["software development","javascript"]},{"title":"Lessons Learned","link":"http:\/\/v4.chriskrycho.com\/2015\/lessons-learned.html","description":"<p>Since mid July 2014, I have been working on a complete redesign and re-build of <a href=\"\/\/holybible.com\">HolyBible.com<\/a>. The good folks at <a href=\"\/\/prts.edu\">Puritan Reformed Theological Seminary<\/a> who own the site wanted to replace its previous content with a Bible reading tool. While there\u2019s still a lot to wrap up, the project is <em>nearing<\/em> its conclusion, and I thought I\u2019d note a few things I\u2019ve learned (in some cases, learned <em>again<\/em>) along the way. I want to say up front, lest these be taken the wrong way: I\u2019m extremely proud of the work I\u2019ve done, and the application I\u2019ve delivered <em>does<\/em> work to the specifications I was hired to meet. More than that, it does it well. But, of course, it could do it <em>better<\/em>. The following thoughts are therefore not, \u201cHow I failed\u201d but rather \u201cHow I will do this <em>even better<\/em> next time around.\u201d<\/p>\n<ol type=\"1\">\n<li><p><em>Single page apps are great, but not always the right choice.<\/em> I made the decision, based on my expectations and understandings of what I would need, to develop the site as a single-page web application. This was a mistake. Not the worst mistake ever: it has its upsides, including performance <em>once the app spins up<\/em>, but for the kind of content I have here, I would take a different tack today. Better in this case to deliver static content and <em>update<\/em> it dynamically as appropriate than to try to load all the content dynamically every time.<\/p>\n<p>At a technical level, that would probably mean supplementing standard HTML with <a href=\"\/\/backbonejs.org\">Backbone<\/a> instead of developing it as a single-page app in <a href=\"\/\/angularjs.org\">Angular<\/a>. For the backend, while I did it in Node.js and that would work fine, I\u2019d probably do a straight Django app (especially with a few of the goals I learned about <em>after<\/em> the project was well along in development).<\/p><\/li>\n<li><p><em>Progressive enhancement or graceful degradation are hard in web applications, but they still matter.<\/em> In the past, I\u2019ve always taken a hard line on making sure things either degrade gracefully or are simply enhanced by JavaScript content. In the architecture decisions I made for this app, I failed to take that into account (largely because I thought it would just <em>need<\/em> to work as a web app, but see above). I regret that enormously at this point; it would be much better in this particular case to have content available even if the additional functionality doesn\u2019t work. Even if you <em>are<\/em> doing something where you are building an <em>app<\/em>, finding ways to make it work on poor connections, older browsers, etc. matters. I\u2019m still thinking a <em>lot<\/em> about the best way to do this in the future.<\/p><\/li>\n<li><p><em>More popular doesn\u2019t mean better.<\/em> Angular has a ton of traction and uptake, and that was deceptive early on. I won\u2019t so easily be fooled in the future. Angular is so very popular in part because Google can put serious money behind its development\u2014and its marketing. But it\u2019s <em>not<\/em> the best for many applications; if you\u2019re not in the business of developing your own custom framework, it\u2019s not even <em>close<\/em> to the best. Use Ember or Knockout or any number of other full-stack frameworks rather than a meta-framework.<\/p>\n<p>How to avoid making that mistake? Well, for my part since then, I\u2019ve learned to look not just as the <em>quantity<\/em> of material in a given community, but its <em>quality<\/em>. For example, <a href=\"\/\/emberjs.com\">Ember<\/a> has <em>incredible<\/em> documentation (far better than Angular\u2019s), and they also have a much clearer vision and a more dependable approach to development (strict semantic versioning, etc.). Had I taken the time to read <em>both<\/em> sets of docs more carefully and think through the consequences of their designs more thoroughly, I could have recognized this before starting. Next time, I will do just that.<\/p>\n<p>I will also look at the way the community behaves. The Ember community is <em>far<\/em> friendlier for newcomers from what I\u2019ve seen than the Angular community\u2014no slam meant on the Angular crowd, but the Ember folks are just doing that really well. That matters, too. (I can\u2019t speak for other communities, of course; these are just the groups I\u2019ve watched the most.)<\/p>\n<p>All in all, Ember would have been the better fit between these two (even though, as noted above, it also wouldn\u2019t have been the <em>best<\/em> fit).<\/p><\/li>\n<li><p><em>Unit tests really are the best.<\/em> I did a vast majority of this project with unit tests\u2014the first time I\u2019ve ever been able to do that for a whole project. In other projects, I\u2019ve been able to do it for parts, but never this much. It saved my bacon a <em>lot<\/em>. Where I got in a hurry and felt like I didn\u2019t have time to write the tests, I (inevitably and predictably!) ended up spending a lot of time chasing down hard-to-isolate bugs\u2014time I could have avoided by writing well-tested (and therefore better-factored) code in the first place. Lesson learned <em>very<\/em> thoroughly. Server- and client-side unit tests are <em>really<\/em> good. They\u2019re also sometimes <em>hard<\/em>; getting mocks set up correctly for dealing with databases, etc. can take a while. That difficulty pays for itself, though.<\/p><\/li>\n<li><p><em>Unit tests <strong>really<\/strong> don\u2019t replace API documentation.<\/em> I have seen people advocate test-driven-development as a way of obviating the need to do major documentation of an API. This is, in a word, ridiculous. Having to read unit tests if you want to remember how you structured an API call is a pain in the neck. Don\u2019t believe it. Design your API and document it, <em>then<\/em> do test-driven development against that contract.<\/p><\/li>\n<li><p><em>Sometimes \u2018good enough\u2019 is enough.<\/em> There is always more to be done, and inevitably you can see a thousand things that could be improved. But \u2018good\u2019 shipping code is far more valuable than \u2018perfect\u2019 code that never ships. You should never ship <em>bad<\/em> code, but sometimes you do have to recognize \u2018good enough\u2019 and push it out the door.<\/p><\/li>\n<li><p><em>Full-stack development is fun, but it\u2019s also really hard.<\/em> I wrote every scrap of code in HolyBible.com proper (though of course it relies on a lot of third-party code). It was very, very difficult to manage that all by myself; it\u2019s a lot to hold in one\u2019s head. (One of the reasons I chose Node was because keeping my implementation and testing all in one language helped reduce that load somewhat.) Would I do it again? Sure. But very much chastened about the difficulties involved. It has been enormously rewarding, and I <em>like<\/em> being a full-stack developer. But it\u2019s a lot of work, and now I know more clearly just how much.<\/p><\/li>\n<\/ol>\n<p>I could say a great deal more about the technical side of things especially, but my biggest takeaway here is that a lot of the hardest and most important work in developing software has nothing to do with the code itself. Architecture and approach shape <em>far<\/em> more than the implementation details (even if those details still matter an awful lot). And popularity is not at all the same as either <em>quality<\/em> or (especially) <em>suitability for a given task<\/em>. In the future, I will be better equipped for the necessary kinds of evaluation, and will hopefully make still better decisions accordingly.<\/p>\n","pubDate":"Sun, 12 Apr 2015 13:49:00 -0400","guid":"tag:v4.chriskrycho.com,2015-04-12:\/2015\/lessons-learned.html","category":["software development","javascript","angularjs"]},{"title":"Unsurprisingly, In Flux","link":"http:\/\/v4.chriskrycho.com\/2015\/unsurprisingly-in-flux.html","description":"<p><i class=\"editorial\">This started as a <a href=\"https:\/\/alpha.app.net\/chriskrycho\/post\/57102562\">series of posts<\/a> on App.net. I <a href=\"http:\/\/v4.chriskrycho.com\/2014\/a-few-theses-on-blogging.html\">resolved<\/a> a while ago that if I was tempted to do that, I should just write a blog post instead. I failed at that resolution, but at a friend\u2019s <a href=\"https:\/\/alpha.app.net\/jws\/post\/57108281\">suggestion<\/a>, am adapting it into a blog post anyway. You can see the posts that prompted it <a href=\"https:\/\/alpha.app.net\/keita\/post\/57096585\">here<\/a> and <a href=\"https:\/\/alpha.app.net\/jws\/post\/57096838\">here<\/a>.<\/i><\/p>\n<hr \/>\n<ul>\n<li><p>The state of JavaScript frameworks today is a scale, really, from not-at-all-monolithic to totally-monolithic, in roughly this order: Backbone \u2013 React &amp; Angular \u2013 Ember \u2013 Meteor.<\/p><\/li>\n<li><p>Backbone and related library Underscore are really collections of common JS tools and patterns you can use to write apps, but they\u2019re not <em>frameworks<\/em>, per se. You\u2019ll write all your own boilerplate there.<\/p><\/li>\n<li><p>React and Angular supply much <em>more<\/em> of the functionality, but Angular is a \u201cmeta-framework\u201d that aims to do <em>some<\/em> boilerplate but let you construct your own custom app framework.<\/p><\/li>\n<li><p>Angular is very powerful, but it\u2019s kind of like Git: wires are exposed; you have to understand a <em>lot<\/em> about the internals to get it to do what you want. Its routing functionality is pretty limited out of the box, too\u2014so much so that there\u2019s a near-standard third-party router.<\/p><\/li>\n<li><p>React, as I understand it, supplies a paradigm and associated tools oriented primarily at view state management, though with capabilities via extensions for routing, etc. These tools are <em>extremely<\/em> powerful for performance in particular. It\u2019s not a full framework, and the docs expressly note that you can <em>just<\/em> use React for the view layer with other tools if you want.<\/p><\/li>\n<li><p>In any case, Angular and React do <em>different<\/em> things from each other, but both do substantially more than Backbone.<\/p><\/li>\n<li><p>Ember is a full framework, strongly emphasizing shared conventions (with a lot of common developers from Rails). It\u2019s perhaps less adaptable than React or Angular, but is much more full-featured; you have very little boilerplate to do.<\/p><\/li>\n<li><p>Meteor is like Ember, but does server-side Node as well as client-side stuff, with the goal being to minimize code duplication, sharing assets as much as possible.<\/p><\/li>\n<li><p>Of all of those, Ember has easily (easily!) the best-explained roadmap, most articulate leadership, and best development path. They are also aggressively adopting the best features of other frameworks wherever it makes sense.<\/p><\/li>\n<li><p>Angular is currently in flux, as Google has announced Angular 2.0 will be basically a completely different framework; there will be <em>no<\/em> direct migration path for Angular 1.x apps to Angular 2.0+. Total rewrite required.<\/p><\/li>\n<li><p>Ember uses a steady 6-week release schedule with very careful regression testing and semantic versioning, with clear deprecation notices and upgrade paths, and is therefore both rapidly iterating <em>and<\/em> relatively stable for use.<\/p><\/li>\n<li><p>If you just need a set of tools for enhance functionality on otherwise relatively static pages, Backbone+Underscore is a great combo. If you already have a bunch of things in place but want a dedicated view layer, React is good.<a href=\"#fn1\" class=\"footnote-ref\" id=\"fnref1\" role=\"doc-noteref\"><sup>1<\/sup><\/a><\/p><\/li>\n<li><p>If you\u2019re writing a new, full-on web <em>application<\/em> (SPA, or organized in whatever other way), I think Ember is the very clear winner at this point. I have good confidence in their leadership and they\u2019re firing on all cylinders.<\/p><\/li>\n<\/ul>\n<p>Regarding Angular, <a href=\"https:\/\/alpha.app.net\/mikehoss\">@mikehoss<\/a> <a href=\"https:\/\/alpha.app.net\/mikehoss\/post\/57105656\">posted<\/a>:<\/p>\n<blockquote>\n<p>For the record they are doing that to make it more mobile-friendly. The Ang1 has abysmal performance on mobile. Besides a time machine, this maybe the best option. And Mi\u0161ko is a bit of a jerk.<\/p>\n<\/blockquote>\n<p>I can\u2019t speak to his comment about Mi\u0161ko (Mi\u0161ko Hevery, one of the leads on AngularJS), but I agree about Angular itself: the rewrite needs to happen. Angular 1.x is a mess\u2014as are its docs. It\u2019s just not a good time to be using 1.x for any new projects.<\/p>\n<p>I\u2019ll add to these points that I\u2019ve used Angular for the last 9 months on HolyBible.com development. As I noted: the documentation is pretty rough, and in a lot of cases you really do have to understand what the framework is doing and how before you can get it to do the things you want. This is, in one sense, exactly the <em>opposite<\/em> of what I\u2019m looking for in a framework\u2014but it makes sense given Angular\u2019s goal of being a meta-framework.<\/p>\n<p>Rather like Git, though, which was originally going to be infrastructure for version control systems which would have their own interface, but eventually just had a \u201cgood enough\u201d interface that we\u2019re all now stuck with, Angular is being used <em>as<\/em> a framework, not just as a <em>meta-framework<\/em>, and it\u2019s unsurprisingly not great for that.<\/p>\n<hr \/>\n<p><i class=\"editorial\">Take this for what it\u2019s worth: not the final word (by a long stretch) on JavaScript frameworks, but rather the perspective of one guy who notably <em>hasn\u2019t used all of the frameworks<\/em>, but has spent some time looking at them. Moreover, I haven\u2019t particularly edited this; it\u2019s more a summary in the kind of short-form posts that I originally created than a detailed analysis. The only things I\u2019ve done are expand some of the notes on Angular and React, and add the footnote on React.<\/i><\/p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr \/>\n<ol>\n<li id=\"fn1\" role=\"doc-endnote\"><p>I <em>really<\/em> don\u2019t know a ton about React, but I do think a lot of what I do know about it is cool from a programming perspective. From a designer perspective, however, it\u2019s a bit of a pain: React\u2019s \u201cJSX\u201d domain-specific language is <em>much<\/em> less friendly to developers than standard HTML, and therefore than either Ember or Angular, both of which implement their templating via HTML templating languages. There\u2019s a substantil tradeoff there: React\u2019s model is interesting not only academically but in practice because of the performance results it produces. It\u2019s worth note, though, that others have recognized this and are adopting it to varying degrees; notably, Ember is incorporating the idea of minimizing changes to the DOM by keeping track of state and updating only differences, rather than refreshing the whole tree, in the new rendering engine (HTMLBars) they\u2019re rolling out over the past several and future several releases.<a href=\"#fnref1\" class=\"footnote-back\" role=\"doc-backlink\">\u21a9<\/a><\/p><\/li>\n<\/ol>\n<\/section>\n","pubDate":"Wed, 08 Apr 2015 16:05:00 -0400","guid":"tag:v4.chriskrycho.com,2015-04-08:\/2015\/unsurprisingly-in-flux.html","category":["software development","javascript","angularjs","emberjs","react"]}]}}