Chris Krycho - software developmenthttp://v4.chriskrycho.com/Thu, 12 Sep 2019 09:00:00 -0400User Interfaces are API Boundarieshttp://v4.chriskrycho.com/2019/user-interfaces-are-api-boundaries.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</b> software developers, especially those who work on user interfaces.</i></p>
<p><a href="https://fsharpforfunandprofit.com/ddd/">Domain-driven design</a>, and its near neighbor the <a href="https://web.archive.org/web/20060711221010/http://alistair.cockburn.us:80/index.php/Hexagonal_architecture">ports and adapters (hexagonal) architecture</a> all emphasize the importance of distinguishing between your internal “business logic” and your interactions with the rest of the world. Much of the time, the “ports” that get discussed are <abbr title="application programming interface">API</abbr> calls (e.g. over <abbr title="hyper-text transfer protocol">HTTP</abbr>) or interacting with a database.</p>
<p>Yesterday, in the midst of a rollicking conversation about building forms in web apps,<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> I realized:</p>
<p><em>User interfaces are <abbr title="application programming interface">API</abbr> boundaries, too!</em></p>
<aside>
<p>I claim no novelty here; I’m sure that if I went through the literature on domain-driven design and the adjacent architectural ideas, I’d find this same point made by others. It’s just a fruitful<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> wording I have not heard before—a concise way of expressing an idea that has been rather floating around in my head in much vaguer terms for the last couple years.</p>
</aside>
<p>One of the key insights of <abbr title="domain-driven design">DDD</abbr> and the ports-and-adapters model is that every interaction with the world outside your program is a place of uncertainty. The <abbr title="application programming interface">API</abbr> might have changed and you might be getting back different responses than you expect. The database might have been corrupted. The network might be down—or worse, degraded so that you get <em>partial</em> messages through, and have to deal with incomplete or nonsensical data. Your software design has to account for this. If you isolate the complexity of dealing with that to well-defined, well-constrained boundaries for your application, everything in between can be <em>much</em> simpler.</p>
<p>And the most reliably unpredictable source of data we have for <em>any</em> application… is users! People are complicated and distracted, and our interfaces are always imperfect, often misleading or confusing in various ways (our best intentions notwithstanding). So we get “bad” data from our users. I scare-quote “bad” here because the data is not (necessarily) <em>morally</em> bad (though: see Twitter!) and it is (usually) a <em>mistake</em> rather than <em>malice</em> at root (though: see all sorts of hacking). But from the perspective of our app’s internals, the data has to be validated and transformed to our model of the world, just as data returned from an <abbr title="application programming interface">API</abbr> or a database does.</p>
<p>If you’re familiar with how these architectures suggest handling sources of data external to your program, the implication for user interaction is obvious: you need to treat it like you would an <abbr title="application programming interface">API</abbr>. You should have a clean separation between the data model of a form and the data model used within your application. Put in common <abbr title="object oriented">OO</abbr> parlance: your form model is a kind of <a href="https://martinfowler.com/eaaCatalog/dataTransferObject.html">data transfer object</a>.</p>
<p>Notice that this holds whether you’re using a traditional web form which submits a <code>POST</code> request via <abbr title="hyper-text transfer protocol">HTTP</abbr>, or building a rich <abbr title="single page application">SPA</abbr>-style JavaScript app which will use the form data without ever sending it anywhere. You have to first validate the data to make sure it is complete and correct—presumably with a mechanism for letting the user know if it isn’t. You also normally need to <em>transform</em> the basically flat data you get back from your form into in a data structure which is appropriately rich for the domain you’re working with.</p>
<p>Again: all of this is bog standard for DDD and ports-and-adapters thinking. The point is that you should treat forms specifically and user interaction in general in much the same way as any other external data: because <em>user interfaces are <abbr title="application programming interface">API</abbr> boundaries</em>.</p>
<p>In a future post, hopefully some time in the next week or two, I’ll trace out one of the implications of this for how I think about building forms in much more concrete terms!</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>about which conversation more another day!<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>I found it <i>fruitful</i> in two senses: it was generative for me as I reflected on it, and it produced some forward motion in a conversation about real-world software development.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
Chris KrychoThu, 12 Sep 2019 09:00:00 -0400tag:v4.chriskrycho.com,2019-09-12:/2019/user-interfaces-are-api-boundaries.htmlsoftware developmentdomain-driven designUIsoftware architecturerewrite Dev Journal: How I Startedhttp://v4.chriskrycho.com/2019/rewrite-dev-journal-how-i-started.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</b> practitioners or interested lookers-on for software development—especially indies.</i></p>
<p>This week, I started the <i>actually writing software</i> phase of working on <a href="https://rewrite.software"><b><i>re</i>write</b></a>. As of yesterday evening, I actually have a bit of code that, although useless in every way, and not especially attractive, does in fact displays a single reference on an iPhone screen. I have an incredibly, impossibly long way to go.</p>
<p>It doesn’t matter: I <em>started</em>.</p>
<p>I had the day off on Monday courtesy of Labor Day, and I chose to spend the chunk of it that <em>wasn’t</em> focused on chores and housework and family time on actually getting this thing moving. I’ve been dreaming for over four years now. That time wasn’t wasted, by a long shot, but as I noted in <a href="https://v4.chriskrycho.com/2019/announcing-rewrite.html">my announcement post</a>, you can plan forever… or you can just start building at some point.</p>
<p>The problem I had—as I noted <a href="https://v4.chriskrycho.com/2019/starting.html">back in July</a>—is that I didn’t actually feel like I knew <em>how</em> to start. This a mammoth project, for one thing. For another, doing this kind of indie work requires dramatically improving my design and product chops. And of course, developing for native apps means learning whole new technology stacks as well!</p>
<p>I’ve known all along that the only way to get anywhere was to break the problem down. You know: the same as always in software development. Find something small to start on. I had already identified which <em>part</em> of the app to dig into first: reference management. This is a place where I could have something that is useful to <em>me</em> in reasonably short order (I want to be able to update my own reference library on my iPad!). Even that was daunting, though—still far too large.</p>
<p>So, Monday, I asked: <i>What is the smallest possible reference-related functionality I could build?</i> The answer, I concluded, was: <i>just display an existing library of references.</i> Then I went further, because “display an existing library of references” is surprisingly complicated. It involves, at a minimum:</p>
<ul>
<li>defining how to display a reference
<ul>
<li>…and therefore also designing the data structures representing references</li>
</ul></li>
<li>actually building that display</li>
<li>defining how to display a list of references to the user—which things to include, which not to, etc.</li>
<li>actually building that list</li>
<li>making it so that tapping on an item in a list displays the detailed view defined previously</li>
<li>making it so you can get back <em>out</em> of the detail view to the list view again</li>
<li>loading a list of references from somewhere, e.g. a BibTeX file from iCloud Drive</li>
<li>parsing that list of references into the internal data structures designed to represent them</li>
</ul>
<p>Now, for an experienced iOS or macOS developer, some of those things might feel trivial enough that they don’t even warrant their own bullet point. But I’m <em>not</em> an experienced iOS or macOS developer; I have no idea how to do any of this! What’s more breaking it down that way means that I have small, discrete tasks that I can go after in small blocks of time. Remember: this is a side project, which I am fitting in around my day job, my church commitments, and time with friends and family. I have to be able to make progress in small blocks of time! I have to <em>feel</em> that progress, at least a little, so that I can keep going.</p>
<p>Every bullet point on the list I came up with represents a discrete item of work. It not only <em>may</em> but <em>must</em> be small, so that I can do it in an evening or three. It needs to be done in such a way that later steps can build on it—but it doesn’t actually need to be anything like what those later steps will transform it into. It just needs to be enough to keep momentum moving, and done in such a way that later changes are not too difficult to make.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>Monday evening, I took the items I had identified and turned them into GitHub Issues in a GitHub project, called <b>Display a BibTeX Library</b>. (I’ll talk about how I’m using GitHub projects a little at some point in the future; it’s a nice flow so far.) Every single one of those items, no matter how apparently small, got its own card. One of them, about Swift-Rust interop, got a note saying, roughly, “I’m pretty sure this will need to be its own whole sub-project.” And looking at that list… I felt a lot less daunted! Every one of the tasks involves something I don’t know how to do yet—but only <em>one</em> thing I don’t know how to do yet, not <em>many</em>.</p>
<p>Last night, I took the first item on the list: display a single reference item. Not <em>parsing</em> them, not even from a string hard-coded into the app, and certainly not loading a file or anything like that. Just hard-coding in a data structure and displaying it on the screen. And, over the course of a few hours, including <em>lots</em> of searching<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> for answers about specific SwiftUI error messages,<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> I managed to implement that one thing.</p>
<p>As I said above: it’s <em>useless</em> in the strict sense. It’s not especially pretty, either. But it’s progress. I started. And now I have that little sense of momentum, and I can keep going!</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>If you think this sounds like the ideas current in the best parts of agile software development—working to make future changes easy; iterating rapidly; delivering the smallest possible chunks of value, and doing so continuously—you’re not wrong!<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>“Searching,” not “Googling,” because I only very rarely Google anything. I search, with <a href="https://duckduckgo.com">Duck Duck Go</a> as my starting point and its <a href="https://duckduckgo.com/bang">! search commands</a> as power tools for searches in specific places.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p><em>Wow</em> could SwiftUI’s compiler diagnostics use some improvement! I sincerely hope that the Swift team in general and the SwiftUI folks in particular take a close look at Rust and Elm for inspiration here.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoWed, 04 Sep 2019 21:30:00 -0400tag:v4.chriskrycho.com,2019-09-04:/2019/rewrite-dev-journal-how-i-started.htmlrewriterewrite dev journalsoftware developmentproductivityStartinghttp://v4.chriskrycho.com/2019/starting.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</b> anyone who has ever struggled to start something new and unknown and therefore difficult and intimidating.</i></p>
<p>I am sitting here on a weekday evening, trying to figure out exactly how to <em>start</em> building <a href="https://rewrite.software"><b><i>re</i>write</b></a>. There is an enormous amount to be done, and I genuinely have no idea how to do… almost any of it. I asked myself: “Where would I start if this were a web app?”—because web apps are my bread and butter, the place I have spent the majority of my time over the last half decade.</p>
<p>But the answer is that I <em>still</em> don’t know. I have only started two completely “greenfield” projects in my entire career. In every other case someone else had done <em>this</em> part, and in most cases I was working with a product manager or someone like that, who was divvying up the tasks. And those two greenfield projects were (a) extremely well-scoped and (b) of a very different sort than this one is. The last time I started a truly greenfield app, it was for a web app… but a web app <em>extremely</em> heavy on words: exactly my home terrain, as it were, on the web. Not that different from a blog.</p>
<p>This is not like that. The problems to solve—managing references, dealing with PDFs, writing large documents, building up projects, you name it: they are all <em>completely</em> new to me. And it’s just me: no product owner handing me feature specs.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> I’m out of my comfort zone even in terms of the technologies I’m using: no deep comfort with the web stack here to fall back on.</p>
<p>Can I do this? Yes. I can. I’ll figure it out. I have figured out hard things before. But it doesn’t change the fact that <em>starting is hard</em>, and I have no idea how to begin.</p>
<p>I’m going to start anyway. Most of what I build these next few weeks will almost certainly get thrown away. That’s okay. I’ll have started. That’s enough for now.</p>
<hr />
<p>An aside, a confession: I have made an enormous amount of progress on my website redesign over the last month. Some of that is because it’s just plain fun. Some of it, though, is because it’s easier to keep working in my comfort zone than to buckle down and get started on the hard new thing where I have <em>no</em> comfort at all. Time to get into it.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>however ill defined!<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoTue, 16 Jul 2019 21:00:00 -0400tag:v4.chriskrycho.com,2019-07-16:/2019/starting.htmlrewritesoftware developmentAnnouncing rewritehttp://v4.chriskrycho.com/2019/announcing-rewrite.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</b> people interested in note-taking, research, and long-form writing.</i></p>
<p>For the past four years, I have been dreaming of an absurdly ambitious application: a tool that can actually handle research writing <em>well</em>. Good research writing—whether it’s a college paper or a Ph.D. thesis, a journal publication or a magazine article, a scholarly blog or a big book—is a complex and challenging task. At a <em>minimum</em>, research writing includes:</p>
<ul>
<li>finding resources, tracking references to them, and citing them correctly</li>
<li>taking, and making good use of, notes—including quotes from those references</li>
<li>writing large, complex, highly structured documents</li>
<li>publishing in a <em>very</em> specific format for everything from typeface to page margins to citation styles</li>
</ul>
<p>There are tools out there which handle <em>some</em> of those pieces well—a few genuinely great notes apps in particular, and some solid contenders in the reference management space. They don’t play together well, though—whether it’s sync errors between apps, the disjointed experience of using tools which know almost nothing about each other, fighting with different journals’ styles, or the simple pain of trying to <em>write</em> in what is really a <i>desktop publishing tool</i> (looking at you, Microsoft Word).</p>
<p>And I would know: over the course of my M.Div., I wrote well over a hundred thousand words of papers; and never mind the many books’ worth of notes I took.</p>
<p>I eventually found a flow that worked for me during those years, pulling together <a href="https://daringfireball.net/projects/markdown">Markdown</a>, <a href="https://en.wikipedia.org/wiki/BibTeX">BibTeX</a>, <a href="https://pandoc.org">pandoc</a>, and <a href="https://citationstyles.org"><abbr title="citation style languages">CSL</abbr>s</a> to generate Word documents. (I wrote about that <a href="https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html">here</a>, if you’re curious.) It did what I wanted! But it was arcane: even after years of working that way, I could never remember the various script invocations involved without looking them up. In short: there was something wonderful there… but the user experience was terrible.</p>
<p>Even by the time I wrote <a href="https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html">that blog post</a>, I was thinking: <i>what would a genuinely great app in this space look like?</i> I had sketched out the basics in a notebook early that month—</p>
<figure>
<img src="https://f001.backblazeb2.com/file/rewrite/first-page.jpeg" title="a picture of the first page of my working notebook" alt="the first page of my working notebook" /><figcaption>the first page of my working notebook</figcaption>
</figure>
<p>—and I haven’t stopped thinking about it ever since. <i>How do you do reference management well? What makes for a good note-taking system? How do you author large, complex documents with easy reference to those notes? How do you pull all those all together for publishing? How do you make it a <em>great</em> app <em>and</em> make it cross-platform?</i></p>
<p>For the past four years, I have been doing two things in preparation for building <b><i>re</i>write</b> (the working title for this app):</p>
<ul>
<li>filling up that same notebook with design constraints, software architecture considerations, and business model ideas</li>
<li>developing the technical skills I’ll need to actually deliver on that dream</li>
</ul>
<p>Even with those years of planning, though, I’d be lying if I said I feel ready to take this on: this project is huge. It will take years to get to a minimum viable product. But you can plan forever and never ship… or you can just get moving, whether you feel ready or not. I quietly launched <a href="https://buttondown.email/rewrite">a newsletter</a> for the project back at the end of April, and over the past few weeks since getting back from vacation—and having at last <a href="https://v4.chriskrycho.com/2019/finishing-things-on-the-internet.html">wrapped up New Rustacean</a>—I have been working on it in earnest. I started digging into <a href="https://developer.apple.com/xcode/swiftui/">SwiftUI</a>, and have been sketching out more detailed <abbr title="user interface">UI</abbr> ideas, and even decided on what to build first.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>And so today, I’m publicly “launching” the project, by which I mean: giving it a little more fanfare than I have previously by blogging about it here <em>and</em> by giving it its own website: <a href="https://rewrite.software">rewrite.software</a>. For now, it’s just a simple landing page with a form to sign up for the mailing list, mostly there so I have a place to direct people to sign up for <a href="https://buttondown.email/rewrite">the project mailing list</a>. Anything more than that would be a distraction from what I really need to be doing now: learning and building!</p>
<p>I hope some of you will follow along as I take on this absurdly ambitious project, and I expect to be blogging about my adventures in Swift and SwiftUI, Rust, and more in the years to come!</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I’m going to try to ship a nice tool for managing references. It’ll be good to have the experience of actually <em>shipping</em> an app. More on that<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 06 Jul 2019 21:50:00 -0400tag:v4.chriskrycho.com,2019-07-06:/2019/announcing-rewrite.htmlrewritesoftware developmentnote-takingBeing an Amateur Againhttp://v4.chriskrycho.com/2019/being-an-amateur-again.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</b> Just about anyone… but I do assume a bit of familiarity with programming.</i></p>
<p>Just a little note here, nothing long or fancy tonight.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> I’ve just started working in earnest on my long-dreamt-of applications for research writing. This means I’m trying to figure out how to build some applications with native toolkits: UIKit and AppKit, specifically. And, for the first time in most of a decade, I have <em>no idea</em> what I’m doing.</p>
<p>I started doing web development in college, over a decade ago. I used a free Dreamweaver clone to build a simple portfolio website for my music when I was a sophomore. I was hacking on <abbr>XML</abbr> templates for my old Blogger site as a junior. In the year after I finished college, I was building websites for friends, family, and my old church. I built multiple responsive web designs within months of Ethan Marcotte’s <a href="https://alistapart.com/article/responsive-web-design">original article on the idea</a>. I was writing loads of jQuery by mid-2011. I built my first single-page app in 2014 (and it’s still running!).</p>
<p>All of that is not to brag but to say: I am <em>deeply</em> comfortable (and relatively expert) with web development. It is in many ways “old hat” to me. Pretty much any tool or framework that sits in that space, I can pick up very quickly, simply because I have deep experience in the space at this point.</p>
<p>And now: I am starting over in many ways. Native app development has a lot in common with web UI development in some ways… but in others, it could not be more foreign. While some of the patterns are the same, and if some of the terminology is curiously familiar<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> the actual details are all <em>wildly</em> different.</p>
<p>The net of it all is discomfort.</p>
<p>I am used to this feeling, so it does not bother me: I have made a point to be <em>learning</em> constantly throughout my career. I will admit, though, that trying to dive in here is intimidating. I want to build apps that are distinguished in no small part by their quality and ease of use… and I am in over my head even to build things that work at <em>all</em> on these platforms.</p>
<p>It helps that I have a five-year horizon for this project.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> But it’s still strange to be diving into the deep end <em>without</em> the comfort of all that existing knowledge. Every time I picked up a new thing in web development, I could layer it onto the things I already knew. Here, that is much less true. Yes, I have a reasonably good sense for how UIs work in many ways, and I have a great deal of general programming knowledge. But with iOS and macOS, at the end of the day, I’m still just a newb.</p>
<p>It’s both a bit intimidating and a little exhilarating. So: here we go!</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I’ve successfully been <em>not blogging</em>, though not for exactly the reasons I hoped. One of the ways <a href="https://v4.chriskrycho.com/burnout">the burnout</a> lingers is that my bandwidth is lower than I might have hoped. Doing both <a href="https://newrustacean.com">New Rustacean</a> and my <a href="https://emberconf.com/speakers.html#chris-krycho">EmberConf workshop</a> was more than enough to keep me full for the first couple months of the year.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Reading docs for UIKit and Swift is a lot like reading a weird mirror-universe version of Ember and TypeScript—you can still see Ember’s <a href="https://sproutcore.com">SproutCore</a> roots, and if you were reading the Ember docs back in the 1.x days, well… there’s a lot to recognize.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>Being in your 30s has some advantages, it turns out! Comfort with longer time-scales is one of them.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 05 Apr 2019 20:00:00 -0400tag:v4.chriskrycho.com,2019-04-05:/2019/being-an-amateur-again.htmlsoftware developmentlearningSeeing Things Throughhttp://v4.chriskrycho.com/2019/seeing-things-through.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</b> Just about anyone. But especially people interested in ideas of “productivity” or accomplishing the things we set out to do.</i></p>
<p>I have on my mind this week starting things, and finishing things.</p>
<p>I picked up a chest strap heart-rate monitor again a week ago, and took a run with it. It felt like starting (<em>again</em>, in this case!) with running. I am training for a couple of half marathons and a long couple days’ of road cycling in the Rocky Mountains in between them. As I wrote in a <a href="https://v4.chriskrycho.com/2019/serious-running-and-my-heart-rate-monitor.html">blog post earlier this week</a>, putting that chest strap on flipped the little switch in my brain that said “This is serious running again.” It helps to have registered for those races and committed to that event. I have <em>always</em> done better at running when I have had a concrete goal in view. It has helped me with <em>finishing</em>. Though I have had to skip out on a few races I have registered for by way of illness or (in one case) moving across the country, I have only failed to train up sufficiently for a race I had registered for <em>once</em> (and that, too, was a function of illness, though it wasn’t initially clear to me).</p>
<p>Over the past four months I decided it was time to start working seriously on some things I have been thinking about for a long time now. One is developing an app (really: a family of them) that I have been nooding on for almost four years now. Another is learning how to build programming languages. Still another is writing some long-form essays, the subjects of which I have been mulling on in some way or another for as long as five years. My challenge in these kinds of projects is twofold: in many cases, the projects themselves are large enough as to seem daunting to me. In others, though I start them, I find the finishing difficult when I am already tired with the many other things on my plate. Having specific and concrete goals would, it seems to me, <em>help</em>—just as in running.</p>
<p>I have, several times now, started open source software projects and never finished them. I have started a (genuinely interesting!) novel/novella/short story (the format is hard to nail down for this idea!) three or four times, and never seen it through. I have a handful of <em>very good</em> essays sitting in my drafts folder that I began either for this site or for Mere Orthodoxy during my seminary years; some of them are 90% done and had I taken just another half an hour they would have been ready to go.</p>
<p>Strange though it might seem to people who see only what looks like very high productivity from me, I have a surprisingly hard time <em>finishing</em> things. Starting them is easy. But sitting down, week in and week out, to get them across the line—it is <em>hard</em>. The more amorphous the task, the less clear-cut “done” is, the harder I find it.</p>
<p>One of my goals for the rest of my thirties is to get better at this: at picking specific projects and leaning into them until I finish them. Even if that means setting aside other good and important projects along the way. There are only so many hours in the day, and there are many few of them available for side projects when one aims to be a good husband and father. I am still getting a handle on this; more reports from the field as I hopefully improve at it!</p>
Chris KrychoSat, 02 Mar 2019 20:10:00 -0500tag:v4.chriskrycho.com,2019-03-02:/2019/seeing-things-through.htmlwritingsoftware developmentproductivityrunningMy Current Setuphttp://v4.chriskrycho.com/2019/my-current-setup.html<p><i><b><a href="https://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</b> people interested in productivity and work flow and app choice.</i></p>
<p>A friend was asking me the other day what my workflow looks like, and while I don’t generally spend a <em>lot</em> of time writing about my working setup, I figured I’d throw up a quick post representing my <em>current</em> list so that if people ask I can point them here.</p>
<p>Two important notes on this, though: First, this is <em>just what I use</em>. I make no particular claim that it’s <em>the best</em>. There are lots of things here that are very specific to me and the way I work, and even to my specific mental quirks. Second, it’s far more important to care about the work you do than about the tools you use to get it done. The tools matter: some people say they don’t and I don’t think that’s right at all. But they don’t matter as much as they might <em>feel</em> like they do, and tool fetishism is real. I think the happy point is finding tools which are good enough and fit comfortably enough into your workflow that they don’t <em>distract</em> you, and then get back to the work you do!</p>
<hr />
<section id="software-development" class="level2">
<h2>Software development</h2>
<p>For software development, I currently use:</p>
<ul>
<li><p><a href="https://code.visualstudio.com">VS Code</a> as my primary text editor; I also occasionally use Sublime Text or Vim for specific tasks where it makes sense. Code is incredibly fast, impressively low in memory usage given it’s an Electron app, and remarkably customizable. My only outstanding complaint is that there’s no way to actually make it look like a native macOS app. Happily, I <em>can</em> make it <em>behave</em> like a native macOS app in all the ways that matter to me. Its support for both TypeScript and Rust—the two languages I spend the most time with right now—is <em>great</em>. You’re welcome to see <a href="https://gist.github.com/chriskrycho/f39442dd78ad6d150bcaaadd9fedf9f4">my full configuration</a>; I keep it updated at that location via the <a href="https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync">Settings Sync</a> plugin.</p></li>
<li><p>macOS’ built-in Terminal app, just using its tabs for individual tasks. I have spent a lot of time with alternatives, including <a href="https://iterm2.com">iTerm 2</a> and <a href="https://sw.kovidgoyal.net/kitty/">kitty</a>, and I’m comfortable in <a href="https://github.com/tmux/tmux/wiki">tmux</a> – but at the end of the day I just like the way Terminal <em>feels</em> the best. It’s fast, light, and built-in macOS things all just work correctly out of the box.</p></li>
<li><p><a href="http://git-fork.com">Fork</a> for a <a href="https://git-scm.com">git</a> <abbr>GUI</abbr>. I’ve also used <a href="https://www.git-tower.com">Tower</a> in the past, but I’ve found Fork to be lighter, faster, and a better fit for the way I think and how I expect things to behave (e.g. for interactive rebasing). I do a ton of work in git on the command line as well.</p></li>
<li><p>A mix, varying day by day, of Safari Tech Preview, Firefox, and Chrome for my test browsers. I substantially prefer Safari in nearly every way, but Chrome’s dev tools remain best in class for most things—with the exception of Grid, where Firefox is still the undisputed champion. (When I can, I do most of my JavaScript/TypeScript debugging in VS Code, though: it’s a much better experience.)</p></li>
<li><p><a href="https://kapeli.com/dash">Dash</a> for offline documentation access. There are other options out there, including some which are free, but Dash remains the best in my experience, and if nothing else it’s deeply integrated into my workflow and muscle memory.</p></li>
</ul>
<p>That’s basically the whole list at the moment. I keep my software development workflow fairly light.</p>
</section>
<section id="research-and-writing" class="level2">
<h2>Research and writing</h2>
<p>For research and writing, I use:</p>
<ul>
<li><p><a href="https://ia.net/writer">iA Writer</a> for all my blogging and longer-form writing. This is a recent change; I had been a heavy user of <a href="http://www.ulysses.app">Ulysses</a> for the last few years. However, while Ulysses was the best option I had found for how I work, it’s never been quite <em>right</em> for me. For one, I’ve always found Ulysses’ “feel” to be a bit heavy: it’s <em>just</em> noticeably slower for me than most of the other writing apps, and I’m hypersensitive to input latency. I’ve also always disliked one of the things that makes many people love it: the way it abstracts Markdown into its “smart text objects.” iA Writer gives me the ability to manage a library in much the same way that Ulysses did, but in a way that feels more truly native on both macOS and iOS; it just uses normal Markdown (no fancy text objects); and it’s <em>fast</em>.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> That combo makes it a better fit for me.</p></li>
<li><p><a href="https://bear.app">Bear</a> for my note-taking. I’ve talked about this <a href="https://v4.chriskrycho.com/2018/starting-to-build-a-zettelkasten.html">a fair bit</a> here <a href="https://v4.chriskrycho.com/2018/zettelkasten-update-all-in-on-bear.html">before</a>, so I won’t belabor the details. It’s an excellent, lightweight note-taking app. The main way it falls down for me is that it does not really handle nested block content in Markdown documents (e.g. it won’t correctly display a block quote inside another block quote, or a code sample inside a list, etc.). I’d also love it if it stored its library in a way that made it easier for me to interact with from other apps, i.e. as plain text on the local drive. (You can export content from it easily enough, which is great, but it’s not quite as seamless as I’d like.) Those nits are just that, though: nits. I’m very happy with Bear for my note-taking at this point.</p></li>
<li><p><a href="https://www.goldenhillsoftware.com/unread/">Unread</a> on iOS for reading RSS, with <a href="https://feedbin.com">Feedbin</a> as my long-preferred RSS feed service backing it. (I’m a fan of paying for these kinds of services, so I’m happy to lay out the $5/month for Feedbin. Free alternatives exist, but I don’t love ad-driven models and avoid them where I can.)</p></li>
</ul>
<p>You’ll note that there are no apps for reading <em>longer</em> material on that list. I could mention Apple Books as the place I read most ebooks I read, but that’s more a function of the alternatives not being meaningfully <em>better</em> in the ways I care about.</p>
</section>
<section id="productivity" class="level2">
<h2>“Productivity”</h2>
<p>For “productivity” concerns, I use:</p>
<ul>
<li><p><a href="https://tadamapp.com">Tadam</a> for a Pomodoro timer—because it’s precisely as annoyingly obtrusive as I need it to be, which is <em>very</em>!—and <a href="https://bear.app">Bear</a> for <a href="https://v4.chriskrycho.com/2018/just-write-down-what-you-do.html">tracking</a> what I do each Pomodoro cycle, each day, each week, each month, and each year. That habit remains very helpful for me.</p></li>
<li><p><a href="https://culturedcode.com">Things</a> for a to-do app. Things hits the sweet spot for me in terms of its ability to manage everything from simple tasks and recurring to-do items around the house up to complex multi-month-long projects. I particularly like its distinction between when I want to be <em>reminded</em> about something and when that task is <em>due</em>. I’ve used <a href="https://www.omnigroup.com/omnifocus/">OmniFocus</a> in the past, but it never quite <em>fit</em> me; Things does. They’re very comparable in terms of features; it’s just that the way Things approaches those features works better for me.</p></li>
<li><p><a href="https://sparkmailapp.com">Spark</a> as my email client, mostly for its snooze feature, which I use when I know I need to see an email <em>as an email</em> sometime later, and its ability to integrate nicely with other apps. I have it connect to Things, and emails that require an <em>action</em> get put there instead of snoozed. The combination lets me keep my inbox at Zero by the end of every day. And its lovely “Inbox Zero” images are a really nice touch:</p>
<figure>
<img src="https://f001.backblazeb2.com/file/chriskrycho-com/images/inbox-zero-spark.png" alt="Inbox Zero in Spark" /><figcaption>Inbox Zero in Spark</figcaption>
</figure></li>
</ul>
</section>
<section id="podcasting" class="level2">
<h2>Podcasting</h2>
<p>For podcast production, I use:</p>
<ul>
<li><p><a href="https://www.izotope.com/en/products/repair-and-edit/rx.html">iZotope RX</a> (I’m using v6 Standard) for audio cleanup, as I <a href="https://v4.chriskrycho.com/2018/izotope-rx-is-amazing.html">recently wrote about</a>.</p></li>
<li><p><a href="https://www.apple.com/logic-pro/">Logic Pro X</a> for the actual editing work most of the time, occasionally using <a href="https://www.wooji-juice.com/products/ferrite/">Ferrite</a>. Logic is overkill for what I do, but I’m <em>fast</em> with it at this point, so I can’t see moving anytime soon, and there’s nothing else out there that I think is substantially <em>better</em> (though there are other apps that are comparably good).</p></li>
<li><p><a href="https://www.overcast.fm/forecast">Forecast</a> for encoding and including chapter breaks.</p></li>
<li><p><a href="https://reinventedsoftware.com/feeder/">Feeder</a> for generating the <abbr>RSS</abbr> feeds, since all my podcasts are currently built in ways that don’t support <abbr>RSS</abbr> feed generation: <a href="http://docs.getpelican.com/en/stable/">Pelican</a> for <a href="https://winningslowly.org">Winning Slowly</a> and <a href="https://massaffection.com">Mass Affection</a>,<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> and <a href="https://doc.rust-lang.org/rustdoc">rustdoc</a> for <a href="https://newrustacean.com">New Rustacean</a>. (If I ever manage to finish building my own site generator, it’ll have out-of-the-box support for custom RSS feed templates, so that I can have this stuff generated automatically for me!)</p></li>
<li><p><a href="https://www.netlify.com">Netlify</a> for serving the actual static site content (i.e. HTML, CSS, and JS), and <a href="https://www.backblaze.com/b2">Backblaze B2</a> for hosting the audio.</p></li>
<li><p><a href="https://panic.com/transmit/">Transmit</a> for actually uploading the audio files.</p></li>
</ul>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>iA Writer seems to get <em>randomly</em> slow at times for reasons I haven’t yet identified, but at least for now, I’m taking that tradeoff over Ulysses’ habit of being a bit slow <em>all the time</em>. As I’ve often noted before: <a href="https://v4.chriskrycho.com/2016/ulysses-byword-and-just-right.html" title="Ulysses, Byword, and “Just Right”">my ideal writing app doesn’t exist</a>.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Mass Affection isn’t dead! I promise!<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 19 Jan 2019 09:00:00 -0500tag:v4.chriskrycho.com,2019-01-19:/2019/my-current-setup.htmlproductivitypomodoroappswritingreadingsoftware developmentJavaScript is Chttp://v4.chriskrycho.com/2018/javascript-is-c.html<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>
<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>
<p>That probably doesn’t make any sense, so let’s 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’s tools. <em>This</em> action on <em>that</em> piece of data was only valid if <em>this</em> condition held true… but even with the fully-type-checked TypeScript application we now have, the action (because of the entire application’s architecture and indeed the entire way that Ember apps are wired together!) could not be statically verified to be safe.</p>
<p>As I considered the best way to handle this—I ended up having the function involved in the action just throw an error if the invariant wasn’t properly maintained—I was reminded of the years I spent writing C. In C, it’s 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>
<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>
<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—but 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’s 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>
<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’s a real and profound shift in what kinds of things you can <em>know for certain</em> about your program.</p>
<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’d-better-check-those-last-2%-really-closely. One hundred percent. That’s a game-changer.</p>
<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’t even apply the relevant transformations in question if it isn’t! That’s a game-changer.</p>
<p>Neither of those is a guarantee I won’t 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’t intentionally do stupid things that violate invariants in ways that get the program into broken states from the user’s 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’re not looking for an absence of all bugs or a system which can prevent us from making any kind of mistake. We’re 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>
<p>So: I’m not going back to C, and I’m ready to move past JavaScript and TypeScript.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>This goes for plenty of languages that aren’t JavaScript, too. It’s equally true of c<sup>♯</sup> or Python.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Obviously there are some kinds of things you don’t 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">↩</a></p></li>
</ol>
</section>
Chris KrychoThu, 20 Dec 2018 18:45:00 -0500tag:v4.chriskrycho.com,2018-12-20:/2018/javascript-is-c.htmlJavaScriptTypeScriptElmRustCsoftware developmentInternal and External Parameter Names in JavaScript and TypeScripthttp://v4.chriskrycho.com/2018/internal-and-external-parameter-names-in-javascript-and-typescript.html<p>Earlier this month I was working on a fairly thorny problem for work—taking 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>
<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’s the latter I want to dive into (the former is a little tricky but not all that interesting).</p>
<p>I started out with just simple parameters to the function:</p>
<pre class="ts"><code>function splitNicely(
total: number, components: number, factor?: number
): number {
// the implementation
}</code></pre>
<p>This is nice enough to use internally. But calling it is pretty confusing:</p>
<pre class="ts"><code>const result = splitNicely(50, 5, 2);</code></pre>
<p>Which number is what value here? Who knows!</p>
<p>So then I just exposed <em>all</em> of the items as an options hash:</p>
<pre class="ts"><code>interface SplitArgs {
total: number;
components: number;
factor?: number;
}
function splitNicely(
{ total, components, factor }: SplitArgs
): number {
// the implementation
}</code></pre>
<p>This was a lot nicer to call:</p>
<pre class="ts"><code>splitNicely({ total: 50, components: 5, factor: 2 });</code></pre>
<p>However, it was a bit verbose, and I realized that it’s fairly obvious that the first argument should be the value we’re splitting up, so I simplified a bit:</p>
<pre class="ts"><code>interface SplitArgs {
components: number;
factor?: number;
}
function splitNicely(
total: number,
{ components, factor }: SplitArgs
): number {
// the implementation
}
</code></pre>
<p>Now calling it read <em>relatively</em> well:</p>
<pre class="ts"><code>splitNicely(10, { components: 5, factor: 2 });</code></pre>
<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—while having these useful names for operating on the implementation internally.</p>
<p>At this point, I remembered two things:</p>
<ol type="1">
<li>Swift and Objective-C have the nice notion of internal and external parameter names.</li>
<li>JavaScript (and thus TypeScript) let you rename values in “destructuring assignment.”</li>
</ol>
<p>The second one lets us get the same basic effect in JavaScript or TypeScript as we get in Swift, if we’re using an options argument! Here’s how destructuring works in the function definition. Let’s see it first with just JavaScript. The object passed as a parameter has a key named <code>of</code>, which has a string value—but <code>of</code> is a bad name inside the function; there, we can just call it <code>str</code> and it’s perfectly clear.</p>
<pre class="js"><code>function length({ of: str }) {
return str.length;
}
console.log(length({ of: &quot;waffles&quot; })); // 7</code></pre>
<p>That’s the equivalent of a function that looks like this:</p>
<pre class="js"><code>function length({ of }) {
const str = of;
return str.length
}</code></pre>
<p>Here’s the same code but in TypeScript:</p>
<pre class="ts"><code>function length({ of: str }: { of: string }): number {
return str.length;
}
console.log(length({ of: &quot;waffles&quot; })); // 7</code></pre>
<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’ve destructured, but the effect is the same once we get past the declaration. It’s also pretty silly to do this kind of thing at all in this example—but it becomes much more useful in more complicated functions, like the one that motivated me to explore this in the first place.</p>
<p>Recall that I <em>liked</em> having <code>components</code> and <code>factor</code> as the internal names. They weren’t great for <em>calling</em> the function, though. After some consideration, I decided invoking the function should look like this:</p>
<pre class="ts"><code>splitNicely(10, { into: 5, byMultiplesOf: 2 });</code></pre>
<p>By using the destructuring technique, we can get exactly this, while keeping <code>components</code> and <code>factor</code> internally:</p>
<pre class="ts"><code>interface SplitArgs = {
into: number;
byMultiplesOf?: number;
}
function splitNicely(
total: number,
{ into: components, byMultiplesOf: factor }: SplitArgs
): number {
// the implementation
}</code></pre>
<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’s 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>
Chris KrychoMon, 26 Nov 2018 20:25:00 -0500tag:v4.chriskrycho.com,2018-11-26:/2018/internal-and-external-parameter-names-in-javascript-and-typescript.htmljavascripttypescriptswiftsoftware developmentScales of Feedback Time in Software Developmenthttp://v4.chriskrycho.com/2018/scales-of-feedback-time-in-software-development.html<p><i class=editorial><strong><a href="http://v4.chriskrycho.com/2018/assumed-audiences.html">Assumed Audience</a>:</strong> fans of compiled languages with expressive type systems. I’m not trying to persuade fans of dynamic languages they should use a compiler here; I’m trying to surface something that often goes unstated in discussions among fans of compiled languages with expressive type systems, but hopefully it’s interesting beyond that. If you don’t like compiled languages, just skip the build step bits; the rest all still applies.</i></p>
<p>There are basically six stages of the development of any given software component where you can receive feedback on what you build:<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<ol type="1">
<li>compilers, static analysis tools, and/or pair programming</li>
<li>automated test suites</li>
<li>manual local testing</li>
<li>continuous integration (<abbr>CI</abbr>) test results</li>
<li>deploying to staging (or a similar test environment) for manual testing</li>
<li>deploying to live, i.e. when production traffic is meaningfully different from what you can test on staging</li>
</ol>
<p>What’s interesting to note is that there are also, in my experience, roughly order-of-magnitude differences between each of those layers in terms of the <em>cycle time</em> between when you make a change and whether you know it is broken. That is, there seem to be rough factor-of-ten differences between the feedback you get from—</p>
<ol type="1">
<li><p>compilers, static analysis tools, and/or pair programming—all of which can show you feedback in near-real-time as you’re typing and saving your code, especially with a good language server or a fast compiler or a speedy linter</p></li>
<li><p>automated test suites, assuming they’re running on every build change and are reasonably speedy themselves, or scoped to the things impacted by the changes made</p></li>
<li><p>manual local testing, which you can repeat after every build, but which usually requires you to switch contexts to execute the program in some way</p></li>
<li><p><abbr>CI</abbr>, presumably doing the automated equivalent of what you do in both layers 2 and 3, but requiring a push to some central location and a remote build and execution of the test suite, and often a much larger integration test suite than you’d run locally</p></li>
<li><p>deploying to staging, and repeating the same kinds of manual testing you might do locally in layer 2 in a more production-like environment</p></li>
<li><p>deploying to live, and repeating the same kinds of manual testing you might do locally in layers 2 or 5, as well as getting feedback from observability or monitoring systems using your real traffic</p></li>
</ol>
<p>(Those last two <em>might</em> be comparable in the cycle time sense. However, the way most teams I’ve heard of work, any deploy to live is usually preceded by a deploy to staging. What’s more, with most changes that you can’t test until it’s live, it’s often the case that you’re not going to know if something is wrong until it has been live for at least a little while. Finally, some kinds of things you can really only test with production load and monitoring or observability systems, and those kinds of things are at least sometimes not to be visible immediately after deployment, but only in the system’s aggregate behavior or weird outliers that show up given enough scale.)</p>
<p>What all of this gets at is that stepping to a higher layer nearly always entails a <em>dramatic</em> increase in the <em>cycle time</em> for software development: that is, the amount of time between when I make a change and when I know whether it’s broken or not. If I can know that I have a problem because my compiler surfaces errors in my editor, that probably saves me a minute or two each day over only being able to see the same error in a test suite. By the same token, being able to surface an error in a test suite running on every build will likely save me anything from minutes to hours of cycle time compared to something I can only test in production.</p>
<p>At first blush, this looks like an argument for pushing everything to the lowest-numbered layer possible, and I think that’s <em>kind of</em> right. I (and probably many other people who end up in, say, Rust or Haskell or Elm or other languages with similarly rich type systems) tend to prefer putting as much as possible into layer 1 here precisely because we have so often been bitten by things that are at layer 2 in other languages or frameworks and take a lot of time to figure out why they broke at layer 2. This happened to me in a C<sup>♯</sup> server application just a couple weeks ago, and chasing it down was <em>not fun</em>.</p>
<p>However, my enthusiasm for rich type systems notwithstanding, I <em>don’t</em> think this observation about these layers of cycle time means we should put everything in the compiler all the time. Indeed, there are some things it is too expensive or difficult to test anywhere <em>but</em> production (all the way up at layer 6). What’s more–although this is often overlooked in these discussions–putting too much of this rich information in layer 1 can absolutely kill your compile times in many languages. In my experience, this is particularly true of many of the languages with rich enough type systems to make layer 1 handling genuinely viable in the first place!<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<p>I do think, though, that being aware of the cost in cycle time is useful, as is being explicit about <em>why</em> we think it’s worth slotting a particular set of feedback into layer 2 vs. layer 1 (or layers 3, 4, 5, or 6). That goes for library development, of course.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> It goes equally for application development, though! It can be really helpful to make explicit both which of these layers you’re landing in and (just as important) why you’ve landed there for any given bit of feedback you want or need to get–making the tradeoffs explicit along the way.</p>
<hr />
<p><i class=editorial>Thanks to my friend Ben Makuh for looking over an earlier draft of this piece and providing really helpful feedback on it! Thanks as well to Greg Vaughn for noting shortly after I published it that pair programming also sits at the “immediate feedback” layer.</i></p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>There’s some ongoing work in the Rust web working group to build an exemplar web framework, <a href="https://rust-lang-nursery.github.io/wg-net/2018/09/11/tide.html">Tide</a>. The <a href="https://rust-lang-nursery.github.io/wg-net/2018/10/16/tide-routing.html">most recent post</a> tackled routing, and prompted <a href="https://internals.rust-lang.org/t/routing-and-extraction-in-tide-a-first-sketch/8587">an interesting discussion</a> on the <a href="https://internals.rust-lang.org/">Rust internals forum</a>. This post is a cleaned-up, better-articulated, more general version of <a href="https://internals.rust-lang.org/t/routing-and-extraction-in-tide-a-first-sketch/8587/36?u=chriskrycho">a post</a> I offered in that thread.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Right now I and a few others are trying to figure out why one particular type definition in the TypeScript definitions for Ember.js causes a build to take about 20× as long as the build without that type definition. It’s the difference between a 6.5-second build and a 2.5-<em>minute</em> build.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>as in the example of a web server’s <abbr>API</abbr> for route handling which originally prompted this post<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoMon, 22 Oct 2018 21:15:00 -0400tag:v4.chriskrycho.com,2018-10-22:/2018/scales-of-feedback-time-in-software-development.htmlsoftware developmenttestingprogramming languagesRustA Real Victoryhttp://v4.chriskrycho.com/2018/a-real-victory.html<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 “the app type-checks”… in the loosest strictness settings.</p>
<p>And as of 6pm today—September 5, 2018, almost two full years later, and 21 months after we switched from Flow to TypeScript (more on this below)—we have a fully type-checked TypeScript Ember application, with the strictness notches dialed as strict as they will go.</p>
<p>It took almost two full years for us to get there, and I’m incredibly proud of that work.</p>
<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—we had to sneak in improvements between features we were working urgently on for our clients and our own internally goals. More, it wasn’t 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—which 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’s build pipeline.</p>
<p>Happily, I did <em>not</em> do most of that work alone, and even on our app I’ve 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’s 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> “I promise this isn’t <code>null</code> or <code>undefined</code> here” operator on some nullable field, with long comments explaining <em>why</em> it’s not possible for it to be null there.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>But it type-checks today, and type errors fail the builds, and that <em>is</em> a real victory.</p>
<hr />
<p>You can consider this “part 1” of my thoughts on what feels to me like a pretty significant achievement. I’ll hopefully follow this up with some backstory sometime in the next few weeks.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<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’s strict null checking available from day one!<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoWed, 05 Sep 2018 21:45:00 -0400tag:v4.chriskrycho.com,2018-09-05:/2018/a-real-victory.htmlTypeScriptJavaScriptFlowEmber.jssoftware developmentTrue Myth 2.1.0 Releasedhttp://v4.chriskrycho.com/2018/true-myth-210-released.html<p>I’ve just released True Myth 2.1.0 (<a href="https://github.com/chriskrycho/true-myth/tree/v2.1.0">source</a>, <a href="https://true-myth.js.org">docs</a>), which includes a handful of new utility functions for use with the <code>Maybe</code> types and arrays or tuples. Note that to make use of these you’ll need to be on at least TypeScript 3.0: they take advantage of the some of the shiny new features in the type system!</p>
<p><strong>Edit:</strong> and, five minutes later, versions 2.1.1 and 2.1.2 are out with bugfixes consisting of “I forgot to export two functions. Now they’re exported.” Because that’s how this <em>always</em> works, right?</p>
<p>Here’s what’s new:</p>
<ul>
<li><p><strong><code>Maybe.find</code>:</strong> for those times when you want to do <code>Array.prototype.find</code> and would love to not have to wrap up the result with a <code>Maybe</code> explicitly every time. As with most functions in True Myth, it’s curried so you can easily use it in a functional programming style.</p>
<pre class="ts"><code>import Maybe from &#39;true-myth/maybe&#39;;
let foundRegular = Maybe.find(n =&gt; n &gt; 1, [1, 2, 3]);
console.log(foundRegular.toString()); // Just(2)
let notFound = Maybe.find(n = n &lt; 1, [1, 2, 3]);
console.log(notFound.toString()); // Nothing
let findAtLeast5 = Maybe.find((n: number) =&gt; n &gt; 5);
let foundCurried = findAtLeastFive([2, 4, 6, 8, 10]);
console.log(foundCurried.toString()); // Just(6)</code></pre></li>
<li><p><strong><code>Maybe.head</code> (aliased as <code>Maybe.first</code>):</strong> for getting the first item of an array safely. Like lodash’s <code>_.head</code> (or <code>someArray[0]</code>) but it returns a <code>Maybe</code> instead of possibly giving you back <code>undefined</code>.</p>
<pre class="ts"><code>import Maybe from &#39;true-myth/maybe&#39;;
let empty = Maybe.head([]);
console.log(empty.toString()); // Nothing
let hasItems = Maybe.head([1, 2, 3]);
console.log(hasItems.toString()); // Just(1)</code></pre></li>
<li><p><strong><code>Maybe.last</code>:</strong> the same as <code>Maybe.head</code>, but for getting the <em>last</em> element in an array.</p>
<pre class="ts"><code>import Maybe from &#39;true-myth/maybe&#39;;
let empty = Maybe.last([]);
console.log(empty.toString()); // Nothing
let hasItems = Maybe.last([1, 2, 3]);
console.log(hasItems.toString()); // Just(3)</code></pre></li>
<li><p><strong><code>Maybe.all</code>:</strong> for converting an array of <code>Maybe</code>s to a <code>Maybe</code> of an array. If you have an array whose contents are all <code>Maybe</code>s, it’s sometimes useful to be able to flip that around so that if all of the items are <code>Just</code>s, you get back a single <code>Just</code> wrapping the array of the values which were wrapped in all the <code>Just</code>s in the array, but if any were <code>Nothing</code>, the whole thing is a single <code>Nothing</code>. This works for both heterogeneous and homogenous arrays, which is pretty cool. A code sample will make this a lot clearer:</p>
<pre class="ts"><code>import Maybe, { just, nothing } from &#39;true-myth/maybe&#39;;
let includesNothing = Maybe.all(just(2), nothing&lt;string&gt;());
console.log(includesNothing.toString()); // Nothing
let allJusts = Maybe.all(just(2), just(&#39;hi&#39;), just([42]));
console.log(allJusts.toString()); // Just([2, &#39;hi&#39;, [42]]);</code></pre>
<p>The resulting type of both <code>includesNothing</code> and <code>allJusts</code> here is <code>Maybe&lt;Array&lt;string | number | Array&lt;number&gt;&gt;&gt;</code>.</p></li>
<li><p><strong><code>Maybe.tuple</code>:</strong> just like <code>Maybe.all</code> except it works in tuples (preserving their types’ order) for up to five-item tuples. (As the docs I wrote say: if you’re doing a larger tuple than that I don’t want to know what you’re doing but I won’t help with it!)</p>
<pre class="ts"><code>import Maybe, { just, nothing } from &#39;true-myth/maybe&#39;;
type Tuple = [Maybe&lt;number&gt;, Maybe&lt;string&gt;, Maybe&lt;number[]&gt;];
let withNothing: Tuple = [just(2), nothing(), just([42])];
let withNothingResult = Maybe.tuple(withNothing);
console.log(withNothingResult.toString()); // Nothing
let allJusts: Tuple = [just(2), just(&#39;hi&#39;), just([42])];
let allJustsResult = Maybe.tuple(allJusts);
console.log(allJustsResult.toString()); // Just([2, &quot;hi&quot;, [42]])</code></pre>
<p>These have the same <em>output</em> (i.e. the same underlying representation) as the array output, but a different type. The resulting type of both <code>includesNothing</code> and <code>allJusts</code> here is <code>Maybe&lt;[number, string, Array&lt;number&gt;]&gt;</code>.</p></li>
</ul>
<p>Once TypeScript 3.1 is out, I should be able to collapse these into a single <code>all</code>, and <code>tuple</code> will just become an alias for it.</p>
Chris KrychoSun, 02 Sep 2018 16:25:00 -0400tag:v4.chriskrycho.com,2018-09-02:/2018/true-myth-210-released.htmlTypeScriptfunctional programmingmonadslibrariessoftware developmentopen source softwareTrue MythType-Informed Designhttp://v4.chriskrycho.com/2018/type-informed-design.html<p>I’ve 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—a few of them really core to the behavior of the app!—which we never, <em>ever</em> would have made if we had been using Typescript in the first place.</p>
<p>One of these is pervasive references to certain optional properties that appear in services throughout our app—the 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’s there to use. We’ve 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’t obvious how pervasive this was—and how badly we were just assuming the presence of something that may well be absent <em>all over the app</em>!—until I saw the type errors from it. Dozens of them.</p>
<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’t make any sense without it, indeed lives in a part of the app such that it’s not even possible to render the component without it.</p>
<p>And sure, we could document that invariant and use TypeScript’s override tools to carry on. (What do you think I’m doing this week?)</p>
<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’d have seen these kinds of things when we were building it in the first place!</p>
<p>That’s a bit of wishing for the impossible in one sense: we literally couldn’t have done that when we started on the app, because TS didn’t 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>
Chris KrychoThu, 30 Aug 2018 19:40:00 -0400tag:v4.chriskrycho.com,2018-08-30:/2018/type-informed-design.htmlTypeScriptJavaScriptfunctional programmingtypessoftware developmentEmber.jsStable Librarieshttp://v4.chriskrycho.com/2018/stable-libraries.html<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’t really expect it to change much in the future. <em>That’s okay.</em></p>
<p>There’s a strange idea in some parts of the software development ecosystem—a way of think I also find myself falling into from time—which takes a lack of changes to a library as a sign that the library is <em>dead</em> and shouldn’t be used. I call this idea “strange” because if you take a step back, it’s actually not necessarily very healthy for certain kinds of libraries to be changing all the time.</p>
<p>But if you’re in an ecosystem where rapid change in libraries is normal, you end up assuming that something which <em>isn’t 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’s in my normal working time. (That’s easy enough for me to do because it’s a small, simple library; I don’t have the scale problems that larger projects do.) The project isn’t <em>dead</em>. It’s just mostly <em>done</em>.</p>
<p>One of the things I’d 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 “churn” we all feel to varying degrees would be much diminished if maintainers didn’t feel a constant push to be changing for the sake of, well… change. The burden on maintainers would be lower, too. Maybe we’d all get to spend less time on small changes that just keep us “up to date” and more on solving bigger problems.</p>
<p>Don’t get me wrong: sometimes changing perspective warrants a rewrite. But in libraries as in apps, just as often you’ll 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>—not never, but rarely—clean wins.</p>
Chris KrychoTue, 14 Aug 2018 19:45:00 -0400tag:v4.chriskrycho.com,2018-08-14:/2018/stable-libraries.htmlsoftware developmentopen source softwarelibrariestrue mythjavascriptBuilding Thingshttp://v4.chriskrycho.com/2018/building-things.html<section id="i." class="level2">
<h2>I.</h2>
<p>For almost three years, now, I have been more or less steadily—sometimes more, sometimes less!—putting out episodes of New Rustacean. It’s fairly popular. I’ve had really smart people tell me how helpful it was in getting them up to speed with the language. I have had the surprising and slightly weird (if also somewhat gratifying) experience of walking into a room and seeing people respond in recognition of my voice.</p>
<p>I’m grateful for the impact the podcast has had, and as I tell people often: this is far and away the most significant thing I could have done in the Rust ecosystem in the last three years. There are a lot of people better-equipped than I to write top-notch libraries and applications in the ecosystem. People well-equipped for podcasting by dint of already being active in the space, and well-equipped for teaching specifically by dint of background and training? There are a lot fewer of those. I don’t think there is anywhere at all I could have made a bigger dent in the same time for Rust.</p>
<p>And yet.</p>
<p>If I went and applied for a job today, where actual Rust <em>experience</em> was desired, the vast majority of my show’s listeners would have substantially more to show than me. A command line tool here, a little experiment there. My <a href="https://github.com/chriskrycho/lightning-rs" title="lightning (lx)">one real project</a> has been on hold almost since I started it. Another project, my original inspiration for learning Rust at all, I’ve never even started. My actual lines of Rust code written in the last three years top out somewhere under 3,000. It’s a pittance. As well as I know the language’s <em>ideas</em>, and indeed as well as I can explain them… I actually haven’t gotten to <em>build</em> much of anything with it.</p>
</section>
<section id="ii." class="level2">
<h2>II.</h2>
<p>The last few months at work, I’ve spent a lot of my time—and an increasingly large proportion of it—on mentoring, code reviews, and leading the team and effort I’m on. This is genuinely wonderful in a lot of ways. I <em>love</em> teaching, and it’s a pleasure to help shape the overall direction of a project and a codebase.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> In many ways, I’m right in line with the goals I set explicitly with my manager at the beginning of the year.</p>
<p>That’s really good, and really important. I recently saw someone tweet the pithy remark that the <em>definition</em> of a senior engineer is that they are mentoring a more junior engineer. I don’t think that’s quite right—there is a lot of room for really outstanding technical contributors who don’t have the gift of teaching, but whose technical chops mean they genuinely <em>are</em> senior people on the team.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> But the reasonable insight under the hyperbole is that enabling others can often be far more effective than merely doing work yourself.</p>
<p>And yet.</p>
<p>Over the last several months, the amount of code I have written myself has dropped substantially. Not to nothing, of course; I’m still doing the actual work of designing and implementing pieces of the application I work on a majority of the time. But I’m not sure how much more than 50% of my time it is on any given week at this point. As much as I’ve enjoyed helping drive this particular project forward,<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> I haven’t actually gotten to <em>build</em> as much during this phase of it.</p>
</section>
<section id="iii." class="level2">
<h2>III.</h2>
<p>These two things have a great deal in common, for all their superficial differences. Both are places where my most valuable contributions are not what I can build myself, but what I can enable <em>others</em> to build.</p>
<p>Thousands and thousands of people have listened to New Rustacean. For some non-trivial number of them, the podcast was an important part of their wrapping their heads around the language. I know this because they tell me, in emails and conversations and tweets that are genuinely my favorite parts of doing the show! I have done far, far more with the podcast than I possibly could have by building another library in Rust.</p>
<p>Similarly, albeit on a much smaller scale, my role in my team at Olo matters. I’ve been able to help set the overall technical direction of a number of our front-end initiatives at the company in important ways. I’ve been able to help more junior developers ramp up their skills. I have done far more in this kind of role than I could possibly have done by just quietly shipping features.</p>
<p>And yet.</p>
<p>Being a “force multiplier” (what a terrible phrase!) isn’t always what it’s cracked up to be. It can be both <em>worth it</em> and also <em>profoundly frustrating and boring</em> at times. I was drawn to software in no small part because of the joy of being able to make things—to start with nothing but an idea or a sketch and a few hours later have something people can interact with, that solves a problem for them. I still love that side of it, and it’s clear to me if nothing else that (for the foreseeable future, anyway) I have no desire whatsoever to go into management roles, “force multiplier” or not.</p>
<p>There’s a real trick here, because it’s not that I’m <em>not</em> building things in these roles. It’s just that building a team or a community is not quite the same thing—it does not scratch the same itch—as building a really elegant user interface component with an elegant and communicative animation. They’re both good; and they’re very, very different from each other.</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I separate those on purpose: a project and a codebase are <em>related</em>, but they’re far from identical. A project can succeed—at least in the short term—with a terrible codebase; an excellent codebase is no guarantee of project success. Getting them aligned is rare, difficult, and rewarding.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>This seems like a typical overcorrection: against the idea that teaching is <em>unimportant</em>, it now comes into vogue to say that teaching is the <em>most</em> important. Imagine if we simply noted that teaching is some people’s gift and vocation, and not others; and that we can complement one another’s strengths by sharing our own—that it is not a zero-sum game but one in which <a href="https://www.esv.org/1+Corinthians+12+12/" title="1 Corinthians 12:12 and following">we are like hands and feet and elbows and ears, each one needing the other, none able to do without the others</a>.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>much of the time anyway; the <a href="https://v4.chriskrycho.com/2018/some-mild-burnout.html" title="Some Mild Burnout">burnout</a> I’m experiencing is related to some of the dynamics of this particular project<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoMon, 06 Aug 2018 21:15:00 -0400tag:v4.chriskrycho.com,2018-08-06:/2018/building-things.htmlsoftware developmentleadershippodcastingNew RustaceanIs Agile the Enemy of Good Design?http://v4.chriskrycho.com/2018/is-agile-the-enemy-of-good-design.html<p><i class=editorial>In line with my recently stated <a href="https://v4.chriskrycho.com/2018/continuing-to-reflect-on-my-internet-presence.html" title="Continuing to Reflect on My Internet Presence">desire</a> to share out things I’m reading:</i></p>
<p>I just ran into a really excellent piece by John Cutler (who is also new to me), <a href="https://hackernoon.com/is-agile-the-enemy-of-good-design-14a35806cde7">Is Agile the Enemy (of Good Design)?</a>. The whole thing is worth your time, but a couple bits in particular stood out to me in light of some ongoing conversations <a href="https://mobile.twitter.com/bmakuh">Ben Makuh</a> about wisdom and folly in startup culture.</p>
<p>In particular, these two bits from other designers Cutler cites sum up a <em>huge</em> amount of what’s wrong with a lot of what passes for “Agile” and indeed for “startup culture”:</p>
<blockquote>
<blockquote>
<p>The stuff you’re talking about rarely happens. It is all about “ship, ship, ship”. We don’t pivot. We don’t refine. The product owner just wants to mark it done in Jira. The MVPs are an excuse to get crappy stuff out the door. I guarantee that if I am methodical with my prototype testing, I can come up with something better because I will expose it to users. Not AS great as doing it the perfect Agile way, but better than nothing. I mean I struggle even to do usability testing. So you know…yes in theory all that is good, but it doesn’t happen.</p>
</blockquote>
</blockquote>
<!-- -->
<blockquote>
<blockquote>
<p>The enemy of both actual agilistas and the UX/design community in 2018 is, as John points out, short-term, output-centric thinking driven by a focus on short-term financial results, and all the cultural ramifications of this mindset.</p>
</blockquote>
</blockquote>
<p>These things are <em>antithetical</em> to the original ideas of the <a href="http://agilemanifesto.org">Manifesto for Agile Software Development</a>. But they’re also, well… pretty common. As Cutler puts it:</p>
<blockquote>
<p>…Agile — like many other things in cut-throat business — is often no match for the universal threats of output fetishism, success theater, and cutting corners. Trust me… these predated Agile.</p>
</blockquote>
<p>And this is some hot fire here:</p>
<blockquote>
<p>So where does this leave us? Designers have a right to be concerned. At least with waterfall no one prematurely yells “ship it” in the middle of the project. Designers have time to work instead of trying to jump on and off the sprint conveyor belt. And because the “thing” is built in a big batch, they have time to tackle the design problem holistically right from the beginning. “Good” waterfall beats abused Agile any day.</p>
</blockquote>
<p>He’s not wrong. <a href="https://hackernoon.com/is-agile-the-enemy-of-good-design-14a35806cde7">You should read the whole thing.</a></p>
Chris KrychoSun, 29 Jul 2018 16:15:00 -0400tag:v4.chriskrycho.com,2018-07-29:/2018/is-agile-the-enemy-of-good-design.htmldesignagilesoftware developmentbusinessTrue Myth 1.3.0 and 2.0.0http://v4.chriskrycho.com/2018/true-myth-130-and-200.html<p>Today I released two versions of <a href="https://github.com/chriskrycho/true-myth">True Myth</a>: <a href="https://github.com/chriskrycho/true-myth/releases/tag/v1.3.0">1.3.0</a> and <a href="https://github.com/chriskrycho/true-myth/releases/tag/v2.0.0">2.0.0</a>. You can read the <a href="https://v4.chriskrycho.com/2017/announcing-true-myth-10.html">1.0 announcement</a> from last November for an overview of the library and a discussion of why you might want to use the library in the first place!</p>
<p>Since its initial release last November, True Myth has gone through a number of small <a href="https://github.com/chriskrycho/true-myth/releases" title="True Myth releases on GitHub">feature and bug fix releases</a>, each of which is more interesting in its own right than 2.0 is—because there are almost no new “features” here, and the changes to the <em>functionality</em> which are in 2.0 are purely additive and could readily have gone in 1.3 instead.</p>
<p>In fact, the act of writing that sentence made me realize that there really <em>should</em> be a 1.3 which people can trivially upgrade to and then take on the changes in 2.0 later.</p>
<section id="section" class="level2">
<h2>– 1.3.0 –</h2>
<p>There are a few very small changes in 1.3 that are just nice ergonomic wins. (You may also be interested in looking back at the <a href="https://github.com/chriskrycho/true-myth/releases">list of other releases</a> to see what else has landed since 1.0.)</p>
<section id="expose-value-and-error" class="level3">
<h3>Expose <code>value</code> and <code>error</code></h3>
<p>The <code>value</code> property in <code>Maybe.Just</code> and <code>Result.Ok</code> instances, and the <code>error</code> property in <code>Result.Err</code> instances, are now <em>public, readonly properties</em> instead of <em>private properties</em>. I made those private in the initial implementation because I thought it made more sense to expose them via methods, but experience showed that this is a relatively common pattern in practice:</p>
<pre class="ts"><code>function dealsWithAMaybe(couldBeAString: Maybe&lt;string&gt;) {
if (couldBeAString.isJust()) {
console.log(`It was! ${couldBeAString.unsafelyUnwrap()}`);
}
}</code></pre>
<p>This is a contrived example of course, but I and my colleagues found in practice that this is a scenario that comes up relatively often, <em>especially</em> when integrating with existing code rather than writing new code – control flow patterns there tend to assume early-return-on-<code>null</code> or similar instead.</p>
<p>So I made a change (leaning on TypeScript’s notion of <a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards" title="“User-Defined Type Guards” in the TypeScript handbook">“type narrowing”</a>) so that you don’t have to use <code>unsafelyUnwrap</code> in this scenario anymore! You can use the method types, the standalone functions, or direct matching against the variants on the property</p>
<pre class="ts"><code>import Maybe from &#39;true-myth/maybe&#39;;
function dealsWithAMaybe(maybe: Maybe&lt;string&gt;) {
if (maybe.isJust()) {
console.log(`It was! ${maybe.value}`);
}
}</code></pre>
<p>In the <code>Result</code> case this is even nicer (notice that I’m using the variant, rather than a function, to discriminate between the two and narrow the types here):</p>
<pre class="ts"><code>import Result, { Variant } from &#39;true-myth/result&#39;;
function dealsWithAResult(result: Result&lt;string, Error&gt;) {
if (result.variant === Variant.Ok) {
console.log(`Huzzah: ${result.value}`);
} else {
console.log(`Alas: ${result.error.message}`);
}
}</code></pre>
<p>Basically: you now have more options for handling these scenarios, a nicer <abbr title="application programming interface">API</abbr>, and—not that it should <em>usually</em> matter that much, but for whatever it’s worth—better performance by way of doing things with property lookups instead of function invocations in quite a few places.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
</section>
<section id="static-helper-methods" class="level3">
<h3>Static helper methods</h3>
<p>At my friend and collaborator <a href="https://mobile.twitter.com/bmakuh">Ben Makuh</a>’s suggestion, I built a couple static helper methods to go with those. These helpers just give you nice abstractions to drop into functional pipelines. For example, you can lean on the type-narrowing capabilities described above while working through a <em>list</em> of <code>Maybe</code>s to <em>know</em> that an item is a <code>Just</code> and use the new <code>Just.unwrap</code> static method in the pipeline:</p>
<pre class="ts"><code>import Maybe, { Just } from &#39;true-myth/maybe&#39;;
function justLengths(maybeStrings: Array&lt;Maybe&lt;string&gt;&gt;) {
return maybeStrings
.filter(Maybe.isJust)
.map(Just.unwrap)
.map(s =&gt; s.length);
}</code></pre>
<p>Analogous helpers exist for <code>Result</code> in the form of the <code>Ok.unwrap</code> and <code>Err.unwrapErr</code> methods. (<code>Nothing</code> has no analog for what I hope are obvious reasons!)</p>
</section>
<section id="tweaks-to-the-variant-properties" class="level3">
<h3>Tweaks to the <code>variant</code> properties</h3>
<p>The <code>variant</code> property on both <code>Maybe</code> and <code>Result</code> has changed in two ways:</p>
<ol type="1">
<li><p>It is now <code>readonly</code>. This was an implicit invariant previously—you would break <em>everything</em> in the library if you changed the <code>variant</code> value—and I’ve just made it explicit in the type system.</p></li>
<li><p>It is now properly constrained with a <em>literal type</em> on the concrete instances. That is, the type of <code>Just.variant</code> is no longer <code>Variant</code> but specifically <code>Variant.Just</code>. (This is what enables you to use the variant for narrowing as demonstrated above. I should have done this in 1.0, and just forgot to!)</p></li>
</ol>
<p>And that’s it for 1.3.0!</p>
</section>
</section>
<section id="section-1" class="level2">
<h2>– 2.0.0 –</h2>
<p>The 2.0 release is identical in <em>features</em> with the 1.3 release. However, it makes a breaking change to how consumers interact with the application, requiring updates to your <code>tsconfig.json</code> file and your bundler configuration, and removing support for Flow types.</p>
<section id="configuration-file-updates" class="level3">
<h3>Configuration file updates</h3>
<p>Getting True Myth working nicely with consuming TypeScript packages has been a source of frustration for me <em>and</em> others. In short, requiring you to use the <code>"paths"</code> key in the <code>"compilerOptions"</code> section of the <code>tsconfig.json</code> made for an annoying amount of setup work, <em>and</em> it meant that using True Myth in a library <em>required</em> you to set it up in any consuming app. No good.</p>
<p>For type resolution to Just Work™, the types <em>must</em> be at the root of the distributed package.</p>
<p>As a result, I’ve stopped using <a href="https://github.com/tildeio/libkit">libkit</a>, which put the generated types in a reasonable-seeming but (in my experience) painful-to-use place, and have simplified the build layout substantially.</p>
<ul>
<li>The types themselves are generated only when publishing an update to npm. They go in the root at that point, and they get cleaned up after publishing. (This is pretty much identical to the solution we came up in <a href="https://github.com/typed-ember/ember-cli-typescript">ember-cli-typescript</a>.)</li>
<li>The other build files no longer get dropped in a nested <code>src</code> directory.</li>
<li>Since I was already at it, I renamed the two build directories from <code>commonjs</code> to <code>cjs</code> and from <code>modules</code> to <code>es</code></li>
</ul>
<p>So the distributed build now looks something like this:</p>
<pre><code>/
index.d.ts
maybe.d.ts
result.d.ts
unit.d.ts
utils.d.ts
dist/
cjs/
index.js
maybe.js
result.js
unit.js
utils.js
es/
index.js
maybe.js
result.js
unit.js
utils.js</code></pre>
<p>You’ll just need to completely remove the <code>"paths"</code> mapping for True Myth from your <code>tsconfig.json</code> and, if you’ve done anything unusual with it, update your bundler configuration to point to the new build location, i.e. <code>dist/commonjs/src</code> should now just be <code>dist/cjs</code>. Bundlers which respect the <code>modules</code> key in <code>package.json</code> will pick it up automatically, as will Ember <abbr>CLI</abbr>.</p>
</section>
<section id="removing-flow-types" class="level3">
<h3>Removing Flow types</h3>
<p>To my knowledge, no one is actually using the Flow types for the library. When I first started on it, my collaborator <a href="https://github.com/bmakuh">Ben Makuh</a> <em>was</em> using Flow, but he ended up migrating to TypeScript in the intervening time, and there are no consumers I know of. I was always relatively unsure of their correctness, <em>and</em> I don’t have a good way to validate their correctness, <em>and</em> maintaining them involved doing manual work on every release to update the types by hand.</p>
<p>If you <em>do</em> use True Myth with Flow, and you’re missing the types, please let me know. I just can’t maintain them myself at this point!</p>
<hr />
<p>And that’s it! We’ve been using True Myth in production at Olo for quite some time, and it’s proved to be a really valuable tool. Give it a spin and let me know how these latest versions work for you!</p>
</section>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I’ve made some changes under the hood to take advantage of this as well, so the library should be faster. Probably <em>trivially</em> faster, but my philosophy around library code is very much <em>be as fast as you can</em>; it’s a way of considering the people using your code—not just the developers, but the end users.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 18 May 2018 19:15:00 -0400tag:v4.chriskrycho.com,2018-05-18:/2018/true-myth-130-and-200.htmlTypeScriptfunctional programminglibrariessoftware developmentopen source softwareversioningTrue MythCareer Trajectoryhttp://v4.chriskrycho.com/2018/career-trajectory.html<p>I’ve been thinking a bit, for the last year or so, about my <em>career trajectory</em>. Where do I want to go, and what do I want to do, over the next 5–10 years?</p>
<p>For the first seven years or so of my working life, I was just learning everything I could in software, following my interests but without much of a conscious plan, and making sure I put food on the table for my family. And I think that was absolutely the right tack to take! I <em>did</em> learn a ton, across a relatively wide swath of the industry. I have worked:</p>
<ul>
<li>as a cog in megacorporation with over 100,000 employees, writing C targeting a real-time operating system;</li>
<li>as the sole dedicated software developer in a company where I was the 12th employee, maintaining decades-old Fortran and C and C++ and writing a fair bit of Python in a scientific computing and physics modeling context;</li>
<li>as a subcontractor for a small consultancy doing PHP and jQuery and (both My- and Postgre)SQL;</li>
<li>as a solo consultant on projects ranging from WordPress setups to building a small but non-trivial application front-to-back in JavaScript;</li>
<li>and, most lately, at a VC-funded startup in the very-tricky scale-up phase, writing JavaScript, TypeScript, and a smidge of C<sup>♯</sup>.</li>
</ul>
<p>As a result, I’ve seen nearly every part of the stack to some degree—from writing a lex/yacc parser spike for a one-off assembly language to building rich browser client applications—and I’ve seen a lot of the kinds of companies that exist in our industry. I’ve also seen (and created!) a pretty remarkable amount of tech debt.</p>
<p>All of which means that, at 30 (almost 31!) and about a year from the end of my first decade in this industry, I’m starting to have a pretty good sense of the things I like, the things I don’t, and some of the directions I might like to go in the future.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> It actually feels a little odd, precisely <em>because</em> I just went where my interests and reasonably good opportunities appeared.</p>
<p>But it’s also important. I know better now than I did a decade ago the things that bring me joy and the places where I’m best equipped to contribute effectively to a team. (I am of course also far better equipped to contribute effectively to a team than I was when I started!) I find that I care enormously about what to build as well as how to build it—my instincts and interests seem to be roughly 25% product person, 25% mentor and teacher, and 50% individual contributor, with a particular interest in building enabling tools for others.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> I have no idea where that will take me in the future, and I’m working closely with my (really excellent) manager at Olo to find ways to both use and develop those effectively where I am.</p>
<p>There are two upshots to all of this:</p>
<ol type="1">
<li><p>If you’re a young developer (or, <em>probably</em>, early on in almost any field), getting as varied—but not shallow!—experience you can in the early years is incredibly valuable. That goes double if you’re coming in from a “non-traditional” background as I did, because it’s a great way to get exposed practically to a lot of the different parts of software and to computer science ideas you won’t if you stay in just one spot. That’s obviously a hard luxury to come by in some ways, but if you <em>can</em> manage it, it pays huge dividends.</p></li>
<li><p>I’m happy to be starting to have a sense of <em>direction</em> and <em>trajectory</em>. I’m in the early stages of that, though; I’m curious to see what I sort out in conversation with Jaimie and my church community and others I trust, as well as my leadership at Olo, over the next year.</p></li>
</ol>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>To be clear to any fellow <a href="https://www.olo.com">Olo</a>-ers who might read this: I’m not planning to go anywhere soon. This isn’t <em>that</em> kind of post.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Hello, <a href="https://newrustacean.com">New Rustacean</a> and <a href="https://github.com/typed-ember/ember-cli-typescript">ember-cli-typescript</a>…<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoWed, 02 May 2018 07:00:00 -0400tag:v4.chriskrycho.com,2018-05-02:/2018/career-trajectory.htmlworksoftware developmentcareerGood Work Takes Timehttp://v4.chriskrycho.com/2018/good-work-takes-time.html<p>It’s obvious enough when you say it aloud, of course, but it bears reiterating, and often: <em>Good work takes time, and most of the time and effort behind good projects remains forever invisible.</em></p>
<p>One of the things I did in 2017 that I’m most proud of (and which I get <em>enormous</em> utility from every day at work) is building <a href="https://github.com/chriskrycho/true-myth">True Myth</a>, a library implementing <code>Maybe</code> and <code>Result</code> types in TypeScript.</p>
<aside>
<p>Note: if you’re about to tune out because this sounds technical, don’t. You can understand everything important in this post without understanding a thing about TypeScript or these particular types.</p>
</aside>
<p>There’s nothing <em>particularly</em> special about that library compared to any of the others in the space which already do the same thing. It makes its own <a href="https://github.com/chriskrycho/true-myth/blob/master/README.md#why-not" title="Comparisons with Folktale and Sanctuary">design tradeoffs</a>, which are slightly <em>different</em> from others, and it has what I think are <a href="https://true-myth.js.org">best-in-class docs</a>, but mostly it’s comparable to the others. Still, it’s <em>good</em>, and it fits that particular niche in terms of design tradeoffs pretty well in my view.</p>
<p>If you just saw the public work on that, you’d have first heard of it <em>at the earliest</em> when I pushed the first commit to GitHub on September 21, 2017. But the roots go much, much further back.</p>
<p>For one thing, I just found a related bit of work dating all the way back to January 10, 2017: an early attempt to see if I could directly reimplement Rust’s Result and Option types in TypeScript, in the early days of my adoption of TypeScript.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> That initial spike didn’t work—and I mean that literally; I didn’t yet have enough of a handle on TypeScript’s type system to get it to actually compile! But it was the first of <em>multiple</em> (mostly very brief) swings I took at it over the course of the year. The culmination of those repeated stabs at the problem was True Myth, with its polish, test coverage, and very considered design tradeoffs.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> But none of that would have happened without the better part of a year of experimenting along the way.</p>
<p>What’s more: even that January spike wasn’t the real start of True Myth. I have code in our codebase (code we’re finally mostly done replacing with True Myth!) that was an early attempt to capture these same basic ideas in plain-old JavaScript—code that dates to March 2016!</p>
<p>So: do not be discouraged when your own work seems to take a long time, or when you see others produce what seem to be fully-formed projects all in a rush. Always, our best work stands on a foundation—of ideas simmering over time, of previous attempts that got partway, of previous outright <em>failures</em>—and all of that is “underground,” out of sight.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Somewhat amusingly to me in retrospect, I’d switched from Flow to TypeScript on our codebase at Olo as my final act of 2016.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>I remain convinced that we hit a <em>really</em> sweet spot with the design here: it works well as idiomatic JavaScript <em>and</em> supports nice functional idioms and I think it just feels nice to use <em>in JavaScript</em>—not just as a port of ideas from Haskell, Scala, etc.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 17 Feb 2018 18:00:00 -0500tag:v4.chriskrycho.com,2018-02-17:/2018/good-work-takes-time.htmlsoftware developmentwritingethicsTypes are Smallhttp://v4.chriskrycho.com/2017/types-are-small.html<p>I’ve been reading through <a href="https://fsharpforfunandprofit.com" title="F♯ for Fun and Profit">Scott Wlaschin</a>’s really excellent book <a href="https://pragprog.com/book/swdddf/domain-modeling-made-functional"><em>Domain Modeling Made Functional</em></a> and this quote (from his chapter introducing the idea of <em>types</em> in <em>typed functional programming</em>) crystallized something for me:</p>
<blockquote>
<p>A type in functional programming is not the same as a class in object-oriented programming. It is much simpler. In fact, a type is just the name given to the set of possible values that can be used as inputs or outputs of a function.</p>
</blockquote>
<p>A lot of times when I’m trying to explain how I use types in a typed functional programming style, this is a serious point of confusion—both for the Java or C♯ OOP programmer and for the programmers coming from dynamic languages. When people think of “types” they tend to think of <em>classes and interfaces and methods, oh my!</em><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>One is the big heavy class. The other is a nice little LEGO block. The difference is <em>huge</em> in my day to day experience, but I’ve never been able to express it so clearly as Wlaschin’s quote.</p>
<p>I suspect that when I’m talking to most people coming from dynamically typed languages <em>or</em> from the standard OOP languages, they hear “Write three interfaces and six classes” when I say “using types to help me with my program.” But what I mean is “Write three tiny little shapes, and then one more that shows how they snap together in a slightly bigger one.” Types aren’t big heavy things. They’re just the shapes I want to flow through my program, written down like documentation for later… that gets checked for me to make sure it stays up to date, and lets me know if I missed something in my description of the shape of the data, or tried to do something I didn’t mean to before.</p>
<p>You <em>can</em> write a language like F♯ or TypeScript or Elm like you would C♯, but it’s generally not going to be an especially <em>happy</em> experience (and it’ll be less happy the more “purely functional,” <em>a la</em> Elm, you go). But you don’t have to! Types are just tiny little descriptions of the shapes you plan to deal with in a particular spot—more concise and more dependable than writing a JSDoc or something like that.</p>
<p>Types are small. You can build big things with them, but <em>types are small</em>.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>In fact, nearly every “I’m just not into types” or even “I think types are worse for most things” talks I’ve seen—including <a href="https://www.youtube.com/watch?v=2V1FtfBDsLU">this recent and popular one by Rich Hickey</a>—tend to conflate <em>all</em> type systems together. But the experience of writing TypeScript is <em>very</em> different from the experience of writing C♯. (You’ll note that in that talk, for example, Hickey freely jumps back and forth between Java-style types and Haskell-style types when it suits his purposes, and he entirely skips past the structural type systems currently having something of a heyday.) In many cases, I <em>suspect</em> this is simply a lack of deep experience with the whole variety of type systems out there (though I’d not attribute that to any specific individual).<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 29 Dec 2017 14:00:00 -0500tag:v4.chriskrycho.com,2017-12-29:/2017/types-are-small.htmlfunctional programmingsoftware development2017 in Review: Looking Forwardhttp://v4.chriskrycho.com/2017/2017-in-review-looking-forward.html<p>As I do every year, I’ve been making some goals for myself for 2018. I’m breaking these down into three big categories this year, having learned from the experience of summarizing my goals for last year:</p>
<ul>
<li><strong>Standing aims</strong>: things that I can’t exactly check off as <em>done</em>, but which are extremely important to me.</li>
<li><strong>Goals</strong>: things I <em>can</em> mark as done.
<ul>
<li><strong>Primary:</strong> the most important of my goals—the ones I’ll count myself as having failed in some way if I don’t accomplish them over the course of the year (barring <em>major</em> unforeseen goings-on, which are, well… impossible to foresee).</li>
<li><strong>Flexible</strong>: other goals, which I’d <em>like</em> to get to, but which it won’t bother me if I don’t get to them.</li>
</ul></li>
</ul>
<section id="standing-aims" class="level2">
<h2>Standing aims</h2>
<ul>
<li>Integrate well into our new church—including finding specific ways and places to serve regularly, joining a small group, and making some good friends.</li>
<li>Spend more, better, and more consistent time with my family.</li>
<li>Work hard at Olo.</li>
</ul>
</section>
<section id="goals" class="level2">
<h2>Goals</h2>
<section id="primary" class="level3">
<h3>Primary</h3>
<ul>
<li>Podcasting:
<ul>
<li>Ship a minimum of 3 episodes of New Rustacean per month January—October.</li>
<li>Publish Winning Slowly Season 6.</li>
</ul></li>
<li>Writing:
<ul>
<li>Publish at least 4 medium-length (2,000–3,500 words) at Mere Orthodoxy.</li>
</ul></li>
<li>Software:
<ul>
<li>Get ember-cli-typescript “finished”—i.e. with full support for addons and fast incremental builds.</li>
<li>Ship a <a href="https://alistapart.com/article/responsive-web-design">responsive</a>, <a href="https://developer.mozilla.org/en-US/Apps/Progressive">progressive</a> version of a major application I work on.</li>
</ul></li>
<li>Read, or finish reading, the following books:
<ul>
<li><em>Resurrection and Moral Order</em>, Oliver O’Donovan (started in 2017)</li>
<li><em>Theology and the Mirror of Scripture</em>, Kevin Vanhoozer and Daniel Treier (started in 2017)</li>
<li><em>How Buildings Learn</em>, Stewart Brand (started in 2017)</li>
<li><em>City of God</em>, Augustine</li>
<li><em>The Technological Society</em>, Jacques Ellul</li>
<li><em>The Meaning of the City</em>, Jacques Ellul</li>
<li><em>The Ethics of Freedom</em>, Jacques Ellul</li>
<li><em>Blasphemy: A Radical Critique of our Technological Culture</em>, Ivan Illich</li>
</ul></li>
<li>Fitness:
<ul>
<li>Run a half marathon.</li>
<li>Finish the <a href="http://www.childrenscoloradofoundation.org/courage-classic/">Courage Classic</a> with my dad.</li>
<li>Get back to my target/healthiest weight.</li>
</ul></li>
</ul>
</section>
<section id="flexible" class="level3">
<h3>Flexible</h3>
<ul>
<li>Publish one essay at a larger publication (for money, if possible!).</li>
<li>Archive static versions of the prior versions of my website.</li>
<li>Improve the page load performance of this site (e.g. with progressive font-loading).</li>
<li>Make meaningful progress on <a href="https://github.com/chriskrycho/lightning-rs">Lightning</a> November–December.</li>
<li>Lead a book club at Olo.</li>
<li>Get up to 20 consecutive pull-ups and 100 consecutive push-ups.</li>
<li>Print hard copies of at least one year of my website archive.</li>
</ul>
<hr />
<p>That seems like <em>plenty</em> to go after this year. One thing that isn’t apparent here is that a fair bit of this is aimed at goals that extend past this year. There are things I want to do in the first half of my thirties if possible, of which some of these are a part. I don’t have those kinds of things written down (and when I write them down, I probably won’t publish them here!) but as I come into the broad swath of life that is just “adulthood”—not <em>young</em> adulthood or <em>old age</em>—I am increasingly mindful of the kinds of things I want to do that take more than a single year to accomplish. Some of these move the needle substantially in that direction, so hopefully I’ll get there!</p>
</section>
</section>
Chris KrychoTue, 26 Dec 2017 09:35:00 -0500tag:v4.chriskrycho.com,2017-12-26:/2017/2017-in-review-looking-forward.htmlproductivitywritingfamilyfitnesspodcastingsoftware development2017-reviewI Want JSON Decodershttp://v4.chriskrycho.com/2017/i-want-json-decoders.html<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’re doing really great work over there, so I encourage you to check out their content and consider subscribing!</i></p>
<hr/>
<p>The other day, I got a report about the Ember.js app I’m working on: when a customer applied a coupon in the basket, they’d see an indication that the coupon was applied, but the basket total would still display as if it hadn’t been updated. Orders were <em>placed</em> correctly, but they wouldn’t 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>
<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’t send back a value on the payload at all. Instead of <code>{ total: 0, ... }</code>, there was just, well, <code>{ ... }</code> – no <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>
<p>The combination was terrible, though: because the server didn’t 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 “no change here!”</p>
<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>
<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♯’s <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’ll automatically derive the type for you so you don’t 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 – certainly none of those type safe guarantees. In TypeScript, you can write the types you receive out carefully – 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’re back to checking for <code>null</code> or <code>undefined</code> everywhere, and <em>why isn’t this already a solved problem?</em></p>
<p>And it turns out, it <em>is</em> a solved problem – 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’t get to write Elm at work right now (or any time in the foreseeable future) – but if I can’t write Elm, I can at least try to steal a bunch of its great ideas and push them back into my TypeScript.</p>
<p>So… what exactly are <abbr>JSON</abbr> Decoders and how would they have solved this problem? (And why, if you’re already familiar a little with Elm and possibly feeling frustrated with decoding, are they actually worth it?)</p>
<p>A <abbr>JSON</abbr> Decoder is just a way of guaranteeing that once you’re inside the boundary of your program, you <em>always</em> have a valid instance of the data type you’ve decoded it into, <em>or</em> an error which tells you why you <em>don’t</em> have a valid instance of the data. They’re 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 – and if <em>any</em> piece of a decoded type doesn’t match with what you’ve specified, you’ll end up with an <code>Err</code>.</p>
<p>Now, initially that might sound like a recipe for disaster – <abbr>JSON</abbr> payloads can be formed in weird ways all the time! – 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’t 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’t have the data. With Elm’s decoders, I would have had three choices:</p>
<ol type="1">
<li>I could have treated this as an error, and passed that along to be dealt with in some way.</li>
<li>I could have normalized it as a 0-value payload.</li>
<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. the implicit behavior of my actual data store.</li>
</ol>
<p>What I <em>couldn’t</em> do, though, is do any one of those <em>accidentally</em>. I could still support incomplete payloads (via option 3), but I’d 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’t also in charge of the <abbr>API</abbr>: if I couldn’t 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>
<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’d have been really happy not to have to spend a morning hunting down this particular bug.</p>
<p>Sometimes that explicitness can seem like quite a lot of boilerplate, and indeed it is: there’s 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♯ type providers, I think the Elm approach has a slight edge in the long-term for <em>maintainability</em> specifically. It’s 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’s something else entirely to be able to <em>know</em> that you’ve accounted for all the varieties of responses you might get (and without throwing an exception for failed <abbr>JSON</abbr> decoding at that!).</p>
<p>Given all of this, I’ve started mentally teasing out what such a <abbr>JSON</abbr> decoding library for Ember.js might look like in TypeScript. It’s a long way off, but it’s 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’s <em>great</em> in my book.</p>
Chris KrychoMon, 25 Dec 2017 19:20:00 -0500tag:v4.chriskrycho.com,2017-12-25:/2017/i-want-json-decoders.htmlJavaScriptElmTypeScriptweb developmentsoftware development2017 in Review: My Goalshttp://v4.chriskrycho.com/2017/2017-in-review-my-goals.html<p>As has been my habit for a few years now, I’m taking some time to reflect on the year as it comes to a close. Thinking about how this year went and what I accomplished, and how I would like the next year to go and what I would like to accomplish <em>then</em>, has become an important part of my life. There is value in taking stock and making plans—as long as you hold those plans loosely. And this particular set of reflections majors on holding plans loosely.</p>
<p>The best place to start seems to be with a review of my goals for 2017, set out <a href="http://v4.chriskrycho.com/2017/2016-review-6.html" title="2016 in Review, Part 6: Plans for 2017">here</a>. In a post later this week, I’ll write up some thoughts on what I hope to accomplish in 2018—though, as you’ll see, there are some hints of that here.</p>
<p>One other note: there are many things going on in our lives that don’t end up in these reflections—because these reflections (as I conceive them at present, at least) are about the kind of public-facing things I did this year. A blog is not a journal, even if there are some analogies between the two.</p>
<section id="major-goals" class="level2">
<h2>Major goals</h2>
<blockquote>
<ol type="1">
<li>Graduate seminary.</li>
</ol>
</blockquote>
<p><strong>Done!</strong></p>
<blockquote>
<ol start="2" type="1">
<li>Spend good time with my family.</li>
</ol>
</blockquote>
<p>This isn’t really a thing you can ever call <em>done</em> in a real sense; there’s always more to do. But we did it well this year, and better than any previous year. I’m looking forward to building on the foundation we laid this year as we move into 2018.</p>
<blockquote>
<ol start="3" type="1">
<li>Love our church well.</li>
</ol>
</blockquote>
<p>I have much the same to say here as I do about family time. I’ll add that we did move across country and join a new church (and a new denomination!), and I expect to write at much greater length about the convictions which drove the <em>way</em> we landed on our new congregation after moving across the country.</p>
<blockquote>
<ol start="4" type="1">
<li>Work hard for Olo.</li>
</ol>
</blockquote>
<p>I shipped a <em>massive</em> amount of code this year, including making some pretty significant architectural contributions for the main app I work on—laying the foundation for it to transition from being a <em>mobile</em> web application to being a <em>responsive, progressive</em> web application in 2018. I also built <a href="https://true-myth.js.org">True Myth</a> and made some pretty substantial progress on <a href="http://v4.chriskrycho.com/typing-your-ember/" title="Typing Your Ember">TypeScript in Ember.js</a>.</p>
<blockquote>
<ol start="5" type="1">
<li>Save money for a house.</li>
</ol>
</blockquote>
<p><strong>Done!</strong> And, to our surprise relative to the beginning of the year, we’re moving in less than a month from now!</p>
<blockquote>
<ol start="6" type="1">
<li>Replace <a href="https://github.com/getpelican/pelican">Pelican</a> with <a href="https://github.com/chriskrycho/lightning-rs">Lightning</a> for this site.</li>
</ol>
</blockquote>
<p><strong>Not done.</strong> I basically ended up putting Lightning on hold entirely this year. New Rustacean and all of the things we had to do around moving just left me with insufficient time to make any sustained progress on it.</p>
<section id="minor-goals" class="level3">
<h3>Minor goals</h3>
<blockquote>
<ul>
<li>publish two episodes of New Rustacean every month (of various formats—not all the full-length teaching-a-subject type)</li>
</ul>
</blockquote>
<p><strong>On average… done.</strong> But only on average. I put out a <em>lot</em> more episodes in November and December than any other month, courtesy of the <a href="http://www.newrustacean.com/show_notes/interview/rbr_2017/index.html">micro-interviews</a> I conducted at <a href="https://rust-belt-rust.com">Rust Belt Rust</a>. The rest of the year, I did publish quite a few episodes, but not nearly as many as I would have liked – more like an average of 1–1.5 each month.</p>
<blockquote>
<ul>
<li>publish 16–20 episodes of Winning Slowly</li>
</ul>
</blockquote>
<p><strong>Very much <em>not</em> done.</strong> Winning Slowly did not go <em>at all</em> the way we thought this year. Our ambitions were… ambitious, given we were both planning to finish graduate degrees and knew that <em>at least</em> Stephen and possibly <em>both of us</em> would be moving across the country. Total episodes published this year: 4.</p>
<blockquote>
<ul>
<li>complete a full-length sprint triathlon<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></li>
<li>run a <a href="http://cityofoaksmarathon.com" title="City of Oaks Marathon">marathon</a></li>
</ul>
</blockquote>
<p><strong>Not done.</strong> The spring ended up busier and, most importantly, more unpredictable schedule-wise than I hoped, and than allowed for sufficiently regular exercise as to be ready for a triathlon in the summer. And our move across the country both eliminated the final six weeks of training I would have needed for the marathon, and also left us 1,800 miles away from the marathon.</p>
<blockquote>
<ul>
<li>be able to do 15 consecutive pull-ups and 100 consecutive push-ups</li>
</ul>
</blockquote>
<p><strong>Not sure!</strong> I haven’t done a max set in a few months. I <em>have</em> been doing a bunch of push-ups and pull-ups since arriving in Colorado, so… maybe. I’ll edit this in a couple days after I do a max set!</p>
<blockquote>
<ul>
<li>lose ten pounds and get back down to my target weight</li>
</ul>
</blockquote>
<p><strong>Sadly, not done.</strong> I have not yet gotten a good handle on what <em>specific</em> dietary changes I’ll need to make to accomplish this goal, but the ones I tried this year didn’t do the trick. I’ll try something new in 2018.</p>
<blockquote>
<ul>
<li>document all the undocumented features in Rust, and get the Rust reference all the way up to date (<a href="https://github.com/rust-lang/rust/issues/38643">tracking issue</a>)</li>
</ul>
</blockquote>
<p><strong>Not done:</strong> I made a fair bit of progress at the beginning of the year, but this is a <em>mammoth</em> task. That said, it’s on my radar to try to help drive it forward (hopefully with community involvement) in 2018—it would be great for a complete and accurate reference to be part of the Rust 2019 epoch.</p>
<blockquote>
<ul>
<li>finish a couple side projects (and bring in the associated money!)</li>
</ul>
</blockquote>
<p><strong>Done.</strong> In particular, I fixed the last couple bugs and tightened things down in the implementation of <a href="https://holybible.com">HolyBible.com</a>. While there’s a lot—oh is there a lot!—I would do differently now (3 years after I finished the base implementation of the app), I’m really delighted that in the last six months I’ve had exactly zero bug reports.</p>
<blockquote>
<ul>
<li>teach in our small group at least a half dozen times</li>
</ul>
</blockquote>
<p><strong>Not done, <em>but</em>…</strong> this was an intentional choice as we started into the year, because there were a couple other guys who it was more helpful to have in that role for their <em>own</em> training. I’ve taught a lot over the years, and both of those guys are going to be actively in church-planting roles in the next year or so.</p>
<blockquote>
<ul>
<li>write at least one long essay for Mere Orthodoxy</li>
</ul>
</blockquote>
<p><strong>Done.</strong> I published <a href="https://mereorthodoxy.com/rhythms-family-worship/" title="The Rhythms of Family Worship">one essay on our family worship</a> and another (just last week), <a href="https://mereorthodoxy.com/faithful-extension-question-human-origins/" title="Faithful Extension and the Question of Human Origins">a book review essay</a> on William T. Cavanaugh and James K. A. Smith’s _Evolution and the Fall_.</p>
<blockquote>
<ul>
<li>publish the scripts and transcripts of New Rustacean as an ebook</li>
</ul>
</blockquote>
<p><strong>Not done.</strong> I <em>do</em> expect to tackle this in 2018, but it just ended up not being a high priority in 2017.</p>
<blockquote>
<ul>
<li>publish hard copies of the archives of my blog, in a way that mirrors the style of the site at the time it was written</li>
</ul>
</blockquote>
<p><strong>Not done.</strong> Same as with the New Rustacean ebook.</p>
<blockquote>
<ul>
<li>fully archive the Blogger and WordPress versions of this blog as static HTML</li>
</ul>
</blockquote>
<p><strong>Started, but incomplete.</strong> I pulled those archives down for the Blogger site, but have yet to do some systematic cleanup on the <abbr>HTML</abbr>. (This <em>might</em> actually happen by the end of the year, depending on what all I do on my week off, but as of the time I’m drafting this, it’s not done.)</p>
<blockquote>
<ul>
<li>move all the sites I host (mine and others) out of shared hosting and into a server I manage (probably Digital Ocean or Linode)</li>
</ul>
</blockquote>
<p><strong>Not done.</strong> I did get a Linode server configured, on which I’m running our family blog (<a href="https://krycho.com">krycho.com</a>), and which I should pretty easily be able to use for other non-static sites going forward. Though, as I’ve thought about it over the last year and change: it’s likely I’ll split it up into a small handful, with one consisting of a kind of “shared hosting” for the various friends’ WordPress blogs I host; and one consisting of my own and my family’s sites.</p>
</section>
<section id="in-summary" class="level3">
<h3>In summary</h3>
<p>This year didn’t really go as we thought it would. A lot of that came down to finding a house plan we loved and could build on a lot that we equally loved—it shifted financial and temporal priorities alike. Add in some pretty serious family health issues in my extended family, and, well, no surprise some of my plans and goals didn’t pan out. That’s how it goes! The point of making these kinds of goals, for me, isn’t so much that I accomplish everything on my list as it is taking time to orient myself and to choose what I will and won’t <em>focus</em> on in the year ahead. And in 2017, I did focus on many of the things on this list. Some of them ended up more important than expected; others less. Interestingly and importantly, though, almost nothing I really spent my time focusing on <em>wasn’t</em> on the list. And that’s why I keep doing this year after year!</p>
</section>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>750m swim, 20km (12mi) ride, 5km (3.1mi) run<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSun, 24 Dec 2017 17:50:00 -0500tag:v4.chriskrycho.com,2017-12-24:/2017/2017-in-review-my-goals.htmlproductivitywritingfamilyfitnesspodcastingsoftware development2017-reviewBecoming a Contributorhttp://v4.chriskrycho.com/2017/becoming-a-contributor.html<p><i class=editorial>Here is the full text of the talk I gave at Rust Belt Rust, as it was prepared; headings correspond to individual slides. You can see the slides as they were presented <a href="/talks/rust-belt-rust/">here</a>. Note that I extemporize fairly freely when actually giving a talk, so this is <em>not</em> a word-for-word equivalent of the talk as delivered, but the gist is the same!</i></p>
<p><i class=editorial>I’ll update this post with the video once it’s available!</i></p>
<hr />
<figure>
<img src="/talks/rust-belt-rust/img/family.jpg" alt="family" /><figcaption>family</figcaption>
</figure>
<p>Hello, everyone! It’s good to see all of you. We only have half an hour, and even if that’s ten to fifteen minutes longer than a normal New Rustacean episode, that’s still not much time, so let’s jump right in! Our theme is “Becoming a Contributor.” There are two prongs to this talk, two big ideas I hope you all walk away with.</p>
<section id="introduction-the-big-ideas" class="level3">
<h3>Introduction: The Big Ideas</h3>
<p>The first thing I hope all of you take away is that <strong>there is no reason <em>you</em> cannot contribute meaningfully</strong> to the success of Rust – or indeed any open-source project you care about. Anyone can be a contributor. And not “even you” but perhaps “<em>especially</em> you”. The fact that you’re an outsider, or new to programming, or new to systems programming: sometimes that makes you a <em>better</em> contributor. Because you don’t necessarily share the biases of – you’re not wearing the same blinders that – someone who’s been writing systems-level code for 20 years have. So the first idea: <strong>you can contribute</strong>.</p>
<p>The second idea I hope you take away is <strong>just <em>how many</em> ways there are to contribute meaningfully</strong>. It has almost become a cliche in the Rust community to say “code isn’t the only thing that matters,” but I want to show you today just how true that is. And I want to make that point again more forcefully, because for all that we often say that, the idea that <em>shipping code</em> is what really matters is the kind of pernicious lie that can come back and bite any of us. It certainly gets to me at times! But it’s a lie, and we’re going to see that in detail. That’s the second big idea: <strong>there are an <em>astounding</em> number of ways you can contribute</strong>.</p>
</section>
<section id="introduction-why" class="level3">
<h3>Introduction: Why?</h3>
<p>There are a lot of things to be passionate about in the world of software development. But at the end of the day, I care about software because I care about <em>people</em>. To borrow a label from Scott Wlaschin – a developer I admire enormously, mostly working over in the F# community – I am a <em>humanist</em>, not a <em>technologist</em>. The technologies are interesting in themselves to a degree; but I mostly care about the ways that technologies can help us serve people more effectively. As software developers, that takes a lot of shapes. But today I want to zoom in on just these two ideas about open-source software:</p>
</section>
<section id="introduction-the-big-ideas-1" class="level3">
<h3>Introduction: The Big Ideas</h3>
<p>So: why these two ideas? For one thing, because I think they are among the most applicable to everyone here. We have an enormous open-source focus. But for another, because they can also serve as windows into the ways we can – and should – think about software more generally. So: let’s talk about how you become a <em>contributor</em>.</p>
</section>
<section id="introduction-outline" class="level3">
<h3>Introduction: Outline</h3>
<p>We’re going to take this on in the good old grammar-school fashion: <em>who</em>, <em>what</em>, <em>when</em>, <em>where</em>, <em>why</em>, and <em>how</em>. We’re not going to take them in that order though, and we might smash a few of them together.</p>
<ol type="1">
<li>Introduction</li>
<li>Why bother contributing? <!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>Who is a contributor? <!-- .element: class="fragment" data-fragment-index="2" --></li>
<li>What is a contribution? How can you contribute? <!-- .element: class="fragment" data-fragment-index="3" -->
<ul>
<li>…so many things they won’t fit on this slide. <!-- .element: class="fragment" data-fragment-index="4" --></li>
</ul></li>
<li>When and where to contribute? <!-- .element: class="fragment" data-fragment-index="5" --></li>
<li>Conclusion <!-- .element: class="fragment" data-fragment-index="6" --></li>
</ol>
</section>
<section id="why-bother-contributing" class="level2">
<h2>Why bother contributing?</h2>
<p>The first question we might be asking is: <em>why contribute at all</em>? Why should you be interested in becoming a contributor? And the best answer I can offer is: because there is more work than hands to do it. Always. Every open-source maintainer can tell you the truth of this.</p>
</section>
<section id="who-is-a-contributor" class="level2">
<h2>Who is a contributor?</h2>
<p>People define this differently, but I have a very simple definition: <strong>A contributor is <em>anyone</em> who improves a project.</strong></p>
<section id="who-is-a-contributor-examples" class="level3">
<h3>Who is a contributor? Examples</h3>
<p>For example:</p>
<ul>
<li>submit a patch to fix a typo <!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>add a small correction for a code sample in a project <!-- .element: class="fragment" data-fragment-index="2" --></li>
<li>file an issue instead of just suffering through a problem in silence <!-- .element: class="fragment" data-fragment-index="3" --></li>
<li>everything else we’re going to talk about today <!-- .element: class="fragment" data-fragment-index="4" --></li>
</ul>
</section>
<section id="who-is-a-contributor-me" class="level3">
<h3>Who is a contributor? Me!</h3>
<p>That might sound overblown, but it’s really not. I am literally standing on this stage in front of you today because I submitted some small typo and code sample improvements to “Rust by Example” a few years ago, and realized: I can make a difference in this community. And that gave me the motivation I needed to <em>keep</em> contributing.</p>
<p><img src="/talks/rust-belt-rust/img/first-commit.png" alt="my first Rust commit" /><!-- .element: class="fragment" data-fragment-index="1" --></p>
</section>
<section id="who-is-a-contributor-1" class="level3">
<h3>Who is a contributor?</h3>
<p>I don’t imagine the story is all that different for <em>most</em> people who are open-source contributors in this room. Something got them over the hump, and it was probably something small, insignificant-seeming at the time. They might be particularly skilled in this thing or that thing, but in fact a lot of them are in those roles just because they saw a need and stepped up to fill it. And then kept at it for a long time. But it made them a contributor. And that feeling – of helping build something bigger than you can build on your own – is a good one. I’d go so far as to say it’s part of what humans are <em>meant</em> for. It’s part of us in a deep, deep way.</p>
</section>
</section>
<section id="who-is-a-contributor-2" class="level2">
<h2>Who is a contributor?</h2>
<p>If you’re inclined to quibble with that definition, I challenge you to ask <em>why?</em> I think, most often, it’s because we feel defensive about wanting to project our own particular kinds of contribution as the most important, or the most valuable. But I’m more of the mindset that, as I read recently, “anyone who would be first… must be last of all, and servant of all.” We should stop worrying about our own prestige and turf-marking, and start rejoicing in the many different ways people are able to make our projects better.</p>
<p>There’s no magic that makes you qualified to be a contributor. There’s just a willingness to serve where you see a need.</p>
</section>
<section id="what-how-can-you-contribute" class="level2">
<h2>What &amp; how can you contribute?</h2>
<p>And that takes us into the “what” of all of this, the <em>how</em>. (Yes, I’m combining those two). <strong><em>What</em> is a contribution? <em>How</em> can you contribute?</strong> Turns out, this is a <em>long</em> list.</p>
<section id="what-how-code" class="level3">
<h3>What &amp; how: code</h3>
<p>Let’s get this right out of the way up front, because it’s the most obvious: you can write code. You can fix bugs or help implement new features. You can do that even if you’re not an expert – especially in the Rust community. Many Rust projects have gone out of their way to mark issues as good-first-issues, or easy-to-tackle, or mentorship-available. Maybe it’s your first contribution to an open-source project: that’s okay. You can take a stab at it, and the fact that it might not be good <em>is okay</em>. The whole point of these kinds of issues is that they give you a place where you can jump in safely.</p>
<p><img src="/talks/rust-belt-rust/img/good-first-issue.png" alt="good first issue" /> <img src="/talks/rust-belt-rust/img/mentored.png" alt="mentored" /> <img src="/talks/rust-belt-rust/img/easy.png" alt="easy" /></p>
<p>That goes equally for everything from the Rust compiler itself to many of the other projects in the ecosystem. Look at the repository, for example! And it’s not just this project. <em>Lots</em> of projects in the Rust ecosystem are like this.</p>
<section id="what-how-code-were-kind-here" class="level4">
<h4>What &amp; how: code – we’re kind here</h4>
<p>And no one is going to swear at you or insult for making a mistake here. Not even if you’re working on something important, and not even if you’ve been doing it for a while. That is not. how. we. roll. here. <em>Everyone</em> makes mistakes!</p>
<p>Instead, we <em>want</em> people to show up, knowing nothing: we’re happy to help. Remember: we want people to contribute! So: try opening a PR and let people help you learn how to do it well! In fact, if you haven’t ever opened a PR on a Rust project, find one that looks interesting to you and has an issue tagged that way, and submit a PR before the weekend is out! You can do it!</p>
<p><img src="/talks/rust-belt-rust/img/good-first-issue.png" alt="good first issue" /> <img src="/talks/rust-belt-rust/img/mentored.png" alt="mentored" /> <img src="/talks/rust-belt-rust/img/easy.png" alt="easy" /></p>
</section>
<section id="what-how-code-a-caveat" class="level4">
<h4>What &amp; how: code – a caveat</h4>
<p>But code is not the only thing that makes you a contributor. I put it up front because I think it’s worth doing – but I also wanted to get it out of the way. In every software community, it’s easy to <em>over</em>-value the code. That might sound crazy, given that it’s open-source <em>software</em>, but the reality is that no one fails to value the code. We <em>do</em> often fail to value all the other things that make an open-source software project actually useful. It’s certainly true that there’s no project without the code. But it’s also the case that there’s no <em>useful</em> software without a lot of other things besides the code, and we often undervalue those.</p>
</section>
</section>
<section id="filing-bugs" class="level3">
<h3>Filing bugs</h3>
<p>So let’s take one step away from code, and talk about what is probably the single <em>easiest</em> way anyone can contribute. <em>File issues.</em> If you’re using a binary and it doesn’t work, open a ticket. If you’re integrating a library and it seems like the API doesn’t do what it should, or if it seems like it’s missing some functionality… well, you can suffer in silence, or you can open a bug ticket! Many times, the author of the software <em>doesn’t know there’s a problem</em>. The only way they can fix it is if they know about it!</p>
<figure>
<img src="/talks/rust-belt-rust/img/new-issue.png" alt="filing bugs" /><figcaption>filing bugs</figcaption>
</figure>
</section>
<section id="docs" class="level3">
<h3>Docs</h3>
<p>Perhaps the thing most of you will be most persuaded of the utility of is <em>documentation</em>. All of us have faced the difficulty of trying to figure out how to integrate some poorly-documented (or undocumented!) library into our own codebase. That experience, in word, <em>sucks</em>.</p>
<p>So working on documentation is one of the highest-value areas you can contribute to any project. It’s also really hard, in a bunch of ways – harder, in some ways, than writing the code is!</p>
<section id="docs-who" class="level4">
<h4>Docs: who?</h4>
<p>One kind of documentation is <strong>explanation of how things work under the hood</strong>. The implementer is the most qualified there! That doesn’t mean they don’t still need help even with that, though! Some people are incredible implementors and terrible explainers; you can often do a great service by serving as an “interpreter” for them – taking their explanations and making the literary tweaks and cleanups and polish that they need.</p>
<p>Another kind of documentation, though, developers and maintainers are often really poorly equipped to write, and that’s <strong>introductory documentation</strong>. This is the problem of expertise: when you know exactly how something is <em>meant</em> to work, and especially when you’re the one who implemented it, there are things that seem obvious to you which simply aren’t obvious to someone approaching it for the first time. And as hard as you try, you <em>can’t</em> escape that entirely. You can imagine what it might be like not to know something, but there’s no substitute for actually not knowing something.</p>
</section>
<section id="docs-how" class="level4">
<h4>Docs – how?</h4>
<p>What that means is that one of the most valuable things you can do as you learn a new library is <em>write down the things you don’t understand from the docs as you go</em>. And when you figure them out, <em>write that down, too</em>. If nothing else, writing up that experience – filing it as an issue on the bug tracker, or otherwise getting it in the hands of the maintainers – can help them make important changes to things like the order various concepts are introduced, or adding little notes to help people feel comfortable with not knowing something until it <em>can</em> be introduced later, and other things like that. It can help them recognize and fill in gaps in their docs – things they simply assumed but which they didn’t realize they were assuming – and fill those in. At the most extreme, you might even help them realize that some parts of the docs need full rewrites… and the work you’ve done in writing things down might just be the foundation or the actual content of those new docs.</p>
<ol type="1">
<li>Write down the things you don’t understand from the docs as you go.<!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>When you figure them out, write that down, too.<!-- .element: class="fragment" data-fragment-index="2" --></li>
<li>Then: file an issue or write a PR to improve it!<!-- .element: class="fragment" data-fragment-index="3" --></li>
</ol>
</section>
<section id="docs-varieties" class="level4">
<h4>Docs: varieties</h4>
<p>So what kinds of things would we call <em>documentation</em>?</p>
<ul>
<li>API documentation<!-- .element class="fragment" data-fragment-index="1" --></li>
<li>READMEs<!-- .element class="fragment" data-fragment-index="2" --></li>
<li>Tutorials<!-- .element class="fragment" data-fragment-index="3" --></li>
<li>Books<!-- .element class="fragment" data-fragment-index="4" --></li>
<li>The Rust Reference<!-- .element class="fragment" data-fragment-index="5" --></li>
</ul>
<p>Okay, books are a <em>huge</em> undertaking, but they can genuinely serve as documentation. Especially for large projects. In fact, several of the most important pieces of “documentation” the Rust project itself has are books: “The Rust Programming Language”, “Rust by Example”, and “The Rustonomicon”. But there are also important but totally unofficial books like Daniel Keep’s “A Practical Intro to Macros in Rust 1.0” and “The Little Book of Rust Macros”, or Jorge Aparicio’s book on microcontrollers with Rust.</p>
<p>The Rust Reference: This is a special category, and one that’s especially important to me. The Rust Reference is supposed to be an exhaustive guide to the language, and the value of that being complete and accurate is hard to overstate. It’s also wildly out of date today. I wrote an RFC last year that said, basically, “We need to actually document everything! That includes updating the Reference!” The trick is: it’s a huge undertaking, and while I and a few others made a good start on it earlier this year, that effort got bogged down by life, and it needs to be resuscitated. And it’s not just Rust which could use investment in that area. Other languages and frameworks have the same issue. It’s <em>really</em> important that there be an answer other than “dive into the source and try to figure out what its intent is” – the more central the component is in the ecosystem, the more important that is.</p>
</section>
<section id="docs-translation" class="level4">
<h4>Docs: Translation</h4>
<p>Another huge place you can contribute to documentation is <em>translation</em>. For good or ill, English has become the sort of <em>primary</em> language of programming, but that doesn’t mean we should treat it as the <em>only</em> language, or as <em>more important</em> than other languages. Translating documentation is amazing and very needed work, and it’s work that not everyone is really capable of! I’m fluent in English and… ancient Hebrew and ancient Greek. For some reason, there’s not much demand for technical writing in Greek from the era when Plato was alive. So I’m not much use at translation.</p>
<figure>
<img src="/talks/rust-belt-rust/img/translation.png" alt="translation" /><figcaption>translation</figcaption>
</figure>
<p>But many of you out there <em>are</em> multilingual, and could take docs written in English and convert them for, say, Czech-speaking developers. Perhaps just as importantly, you can go the <em>other</em> direction, and help non-English-speaking maintainers reach a broader audience. Take an amazing project which only has documentation in Amharic (because its developers don’t feel comfortable enough in English to translate it themselves) and translate it to English: <em>use</em> the fact that English <em>is</em> the common language to increase the reach of non-Western developers!</p>
</section>
</section>
<section id="visual-design" class="level3">
<h3>Visual Design</h3>
<p>One of the areas where you could move the ball down the field fastest in the Rust community is with <strong><em>visual</em> design</strong>. (To be clear, the <em>language</em> design is great!) But our websites could sometimes use some work.</p>
<section id="visual-design-its-not-just-us" class="level4">
<h4>Visual design: it’s not just us</h4>
<p>Systems programming language types have historically <em>not</em> spent a lot of time on the <em>presentation</em> of their tools. In part this is just a matter of what these kinds of languages have been oriented towards: if you spend all day hacking on kernel code, you’re <em>likelier</em> to be a person for whom user interface and visual design is less interesting than, say, optimizing memory performance or minimizing the number of cache misses a given approach has. But presentation <em>does</em> matter, and it matters especially as we want to enable more and more people to be able to write this kind of code.</p>
<p>Speaking frankly, though I’ve spent a large chunk of my career to date writing systems-level languages, I’ve found the way a lot of these tools are presented to be a huge turn-off, and at times a barrier even to getting them working for me locally. Perhaps the most egregious example of that was some of the “documentation” – I’m not sure I should even call it that! – for Fortran, when I was first getting started programming back in college. The presentation of the material was essentially hacker-ish in a <em>bad</em> way: no CSS, no attention to organization of the material, no structure to help you find your way through it.</p>
</section>
<section id="visual-design-how" class="level4">
<h4>Visual design: how</h4>
<p>If you’re an expert or just a talented amateur, please pitch in<!-- .element: class="fragment" data-fragment-index="1" --></p>
<p>You can help here even if you’re not especially comfortable with visual design or even if you’re outright bad at it if you’re willing to spend just a little time on it! For example, you can simply help a team adopt something like Bootstrap. Yes, it’ll look like many other open-source projects out there. But it won’t be horribly, catastrophically ugly and unreadable! Or you can do use one of these simple starter kits:</p>
<ul>
<li><a href="http://usewing.ml">Wing</a></li>
<li><a href="https://purecss.io">Pure.css</a></li>
<li><a href="http://getskeleton.coma">Skeleton</a></li>
</ul>
<p>So don’t think that just because you aren’t a design expert means you can’t help here.</p>
<p>Just as important as the <em>visual</em> design is thinking about and actively designing the <strong>information hierarchy</strong> of your content. What leads to what? Which pieces go together, and which pieces can be broken up into their own pages or sections within pages? Think about the content like an <em>outline</em>. Many sites don’t have any such structure to them; they’re kind of haphazardly cobbled together. If you can help the maintainers with the <em>structure</em> and <em>organization</em> of their content, that can make an enormous differences as well.</p>
</section>
</section>
<section id="blogging" class="level3">
<h3>Blogging</h3>
<p>One of the other big ways you can help a project may not even end up in the repository at all. You can <em>blog</em>.</p>
<p>I know blogging can seem intimidating, for many of the same reasons that writing documentation can. Technical writing is hard, and it’s a completely different skill from programming. But it doesn’t have to be amazing; it just has to get the information out there – and you’ll get better as you practice.</p>
<section id="blogging-easy-mode" class="level4">
<h4>Blogging: “Easy Mode”</h4>
<p>You can start on “easy mode”, too. I mentioned this earlier when talking about documentation, but “just write down what you’re learning” is an incredibly effective technique for generating content. If you look at a lot of the technical blogging I’ve done over the years, it has been nothing more complicated than “here is what I just learned.” And if you want a <em>superb</em> example of this which is <em>very</em> different from mine, take a look at the work that Julia Evans does on her blog! She regularly writes down, in an inimitable way, highly technical ideas she’s just learning. If you want someone to make arcane Linux command line tools seem amazing and approachable, her blog is your ticket.</p>
<blockquote>
<p>Just write down what you’re learning.<br/> —Me, just now</p>
</blockquote>
</section>
<section id="blogging-good-examples" class="level4">
<h4>Blogging: good examples</h4>
<p>But even beyond “what I just learned,” blogging is a superb way for teaching in general. Over the course of this year, for example, Vaidehi Joshi has been writing what is essentially a friendly introduction to computer science on her blog on Medium. This is a totally different style of <em>content</em> (as well as of presentation!) from the kind of “what I just learned” content that Julia Evans writes,but it’s also really effective, because she takes her knowledge and translates it into something others can pick up. That’s obviously more work than just writing down things you just learned, but it can also pay really high dividends as others are able to substantially deepen their knowledge.</p>
</section>
<section id="blogging-all-the-options" class="level4">
<h4>Blogging: all the options!</h4>
<p>In blogging, as in documentation, there is a whole spectrum of basic teaching content you can contribute! And communities need the whole spectrum for simple introductions to extremely thorough, advanced tutorials.</p>
<p>But blog posts can also be much more versatile than traditional documentation.</p>
<ul>
<li><strong>They can be one-offs, or series.</strong> You can give a topic as much depth, or as little depth, as you <em>care about</em> or <em>think it deserves</em>. I wrote an 18-part series comparing Rust and Swift, and it could have been 30 parts if I hadn’t eventually gotten derailed. That’s not <em>documentation</em>, but there’s a lot people can learn from those kinds of things.</li>
<li><strong>They can introduce a technology, or dig deep into how to use it, or how it’s built.</strong> You’re not limited to just one particular tack when blogging. Is your interest in the specific implementation details of some corner of the compiler? Write about that! Is your interest in how a given Rust library solves a specific kind of problem you’ve run into with another library, or with a similar library in another language? Write about that! You get the idea.</li>
<li><strong>They can critique or highlight problems with specific pieces of the ecosystem!</strong> A careful, well-articulated, critical blog post can do wonders for showing the problems with a given approach and can even sometimes help suggest the right solutions to those problems. I’ve repeatedly watched, for example, as people have blogged about their struggles getting their heads around the Tokio tooling; the result has been a <em>lot</em> of work by the Tokio team to respond to those problems. The more thoughtful and careful you are in that kind of criticism, the better! Good criticism is <em>incredibly</em> valuable. Because we all have blind spots, and someone else’s perspective can help jar us out of those.</li>
<li><strong>They can show how to <em>integrate</em> different parts of the ecosystem.</strong> For example, as part of the “Increasing Rust’s Reach” initiative, Ryan Blecher recently wrote up a detailed walk-through on how to use the Diesel ORM and the Rocket web framework together to build a small blogging engine. That’s <em>huge</em>! It makes it that much easier for someone who’s just starting out with Rust, coming in from something like Python or Ruby, to dive in and get that intensely rewarding feeling of <em>having built something</em> in a relatively small amount of time. That’s also helpful because (almost) no one is building something with <em>just</em> Diesel, or just <em>any</em> crate. A huge part of what every software developer does is about fitting together other pieces of software.</li>
<li><strong>They can invite feedback on your own projects.</strong> Talk about what you’re doing, what your stumbling blocks are, what you don’t understand. People will often show up and help you with comments and clarifications!</li>
</ul>
<p>And that’s just scratching the surface. Blogs are incredibly versatile, and you should lean on that.</p>
</section>
</section>
<section id="audio-and-video" class="level3">
<h3>Audio and Video</h3>
<p>Not just words! Noises and pictures, too!</p>
<section id="audio-podcasts" class="level4">
<h4>Audio: podcasts</h4>
<ul>
<li>Not everyone learns the same way.<!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>Lots of people have commutes.<!-- .element: class="fragment" data-fragment-index="2" --></li>
</ul>
</section>
<section id="audio-but-there-are-already-podcasts" class="level4">
<h4>Audio: but there are already podcasts</h4>
<p>Everything I’ve talked about so far has been in written form. But audio and video media can also be really helpful. Not everyone learns best by reading. And not everyone has tons of time to sit down and read a book every day. One of the reasons I started the New Rustacean podcast is that it gives people a way to get up to speed on the language while on a daily commute. But there’s still a <em>huge</em> need for more audio and video content in this space!</p>
<p>One podcast is not enough!</p>
<figure>
<img src="/talks/rust-belt-rust/img/newrustacean.png" alt="New Rustacean" /><figcaption>New Rustacean</figcaption>
</figure>
<p><em>Two</em> podcasts is not enough!</p>
<figure>
<img src="/talks/rust-belt-rust/img/rfe.png" alt="Request for Explanation" /><figcaption>Request for Explanation</figcaption>
</figure>
<p>Seriously, not even <em>three</em> podcasts is enough!</p>
<figure>
<img src="/talks/rust-belt-rust/img/rusty-spike.png" alt="Rusty Spike" /><figcaption>Rusty Spike</figcaption>
</figure>
<p>So I’m laying down another challenge: there’s plenty of room for more, and more kinds, of audio content in this ecosystem.</p>
</section>
<section id="video" class="level4">
<h4>Video</h4>
<p>Again: people have different learning styles!</p>
<p>There’s also a huge opening for people to produce good video content. I’ve heard often from people that things like RailsCasts were essential in helping them learn the Ruby on Rails ecosystem. We <em>need</em> video tutorials which might look kind of like that, or like the kinds of things I’m doing on the podcast. If you have any skill that way, and any interest in teaching, you should make Rust videos – there aren’t many out there.</p>
</section>
<section id="video-what" class="level4">
<h4>Video: what</h4>
<p>There are lots of options here—not just live streaming!</p>
<p>Another, totally different tack you can take with video is <em>live-streaming</em>. Sean Griffin has done this at times, and I’ve actually done it just once, and it’s a ton of fun – and it can be incredibly illuminating for other people to see how you work and how you solve problems. You can also do like I did and live-pair on something. It’s a pain to set up, but it’s also a lot of fun.</p>
<p>And no doubt there are more ideas you have—please just go do them!</p>
</section>
</section>
<section id="talk-to-people" class="level3">
<h3>Talk to people</h3>
<p>Just talking with people matters. And there are lots of places to do it:</p>
<ul>
<li>IRC/Gitter/Slack/Discourse</li>
<li>Meetups</li>
<li>Conferences</li>
</ul>
<p>You can also host or help with a local meet-up! For a lot of people, one of the major challenges of learning <em>any</em> new piece of technology is that – even with IRC and Gitter and Slack and so on – you can feel isolated and alone. And people can help you solve problems in person, and make you feel supported in person, in ways that even a great community can’t really manage online. So <em>go</em> to meet-ups, at a minimum. And help the organizers. And if there isn’t a meet-up in your community… you can start one! The #rust-community team has a ton of resources.</p>
<p>Physicality matters. Presence matters. (We know this! We’re at a conference!)</p>
</section>
<section id="being-inviting" class="level3">
<h3>Being inviting</h3>
<p>Last but not least in this list of <em>how</em> to be a contributor, I want to take a minute and talk about “being a contributor” to those of you who’ve been contributors for a long time. Some of you have been shipping open-source software for years – some of you even for decades. Much of what I’ve said so far is old hat for you. Maybe not the design bits quite so much! But you’ve been doing this for a long time, and you’re not trying to get over the hump of making your first contribution. You have other things to contribute here:</p>
<ul>
<li><p>The most important thing you can do is practice <strong>welcome people.</strong> The Rust community does this well, in general, but it’s something we need to keep in front of us as a goal as the community grows. It’s easy to get frustrated with newcomers as your project grows, demands on your time increase, and your work as a maintainer seems less like fun and more like a second job. But continuing to actively welcome newcomers in is <em>incredibly</em> powerful. You can make it possible for people to go from zero to really making a difference. And remember: so once were you. None of us started out as magical wizards of Rust and open-source.</p></li>
<li><p>The second big thing you can do is <strong>mentoring.</strong> As I mentioned, I’m now the maintainer of one of the core pieces necessary to make Ember.js and TypeScript play nicely together. But while I’ve done <em>some</em> writing-of-code with that, a much larger part of my current and future work there is about helping other people learn TypeScript well enough to start using it in their apps and add-ons. But the flip-side of that is: even a fair bit of the code I <em>have</em> written, I was able to write because someone more comfortable with some of the infrastructure mentored <em>me</em> through its quirks and oddities.</p></li>
</ul>
</section>
</section>
<section id="when-where-to-contribute" class="level2">
<h2>When &amp; where to contribute</h2>
<p>The last thing I want to touch on is <em>when and where</em> to contribute. There are two things I’d suggest you should consider here:</p>
<section id="when-where-you" class="level3">
<h3>When &amp; where: you</h3>
<p>Where are <em>you</em> in the process of becoming comfortable with contributing?</p>
<ul>
<li>Just getting started?<!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>Already comfortable?<!-- .element: class="fragment" data-fragment-index="2" --></li>
</ul>
<p>If you’ve never done any open-source work at all before, that’s different than if you’ve gotten pretty comfortable with it in a different ecosystem and are just figuring out where to make yourself useful in <em>this</em> ecosystem.</p>
<section id="when-where-if-youre-just-getting-started" class="level4">
<h4>When &amp; where: if you’re just getting started</h4>
<p>If you’re just getting started, I’d pick a big project with lots of those “Help Wanted” and “Mentoring” and “Easy” tags on issues, and let the size of the project help you out. Those are projects that are <em>used to</em> helping people make their first contributions. Crazy as it seems, something like Servo can actually be an <em>easier</em> place to start out that a much smaller project. Sure, the technical lift is higher, but there are also a lot more people actively invested in your success there.</p>
<ol type="1">
<li><p>Look for these!<!-- .element: class="fragment" data-fragment-index="1" --></p>
<p class="fragment" data-fragment-index="1">
<p><img src="/talks/rust-belt-rust/img/help-wanted.png" alt="help wanted" /> <img src="/talks/rust-belt-rust/img/easy.png" alt="help wanted" /></p>
</p></li>
<li><p>Pick big projects!<!-- .element: class="fragment" data-fragment-index="2" --></p></li>
</ol>
</section>
<section id="when-where-if-youre-experienced" class="level4">
<h4>When &amp; where: if you’re experienced</h4>
<p>On the other hand, if you’re already comfortable contributing and have some idea what you’re best at, you might look around and find smaller projects with fewer contributors which look interesting and <em>could use the help</em>. Because again, there’s always more work to do than hands to do it.</p>
</section>
<section id="when-where-project-lifecycles" class="level4">
<h4>When &amp; where: project lifecycles</h4>
<p>The second consideration dovetails nicely with that: <strong>where is a given project at in its life-cycle?</strong> As enthusiastic as you might be about some project, if it’s a small project and it’s already in a “basically done” state, well… that’s probably a lot less useful a place to invest your time <em>if</em> you’re focusing on code. On the other hand, it’s often the case that projects are “done” in terms of code, but desperately need help with documentation, their web site, etc. Big projects, or projects just starting out, are often better places to dig in if you’re really looking to flex your coding muscles (but both of them <em>also</em> usually have huge needs in terms of all those non-code avenues we talked about).</p>
<p>Where is a given project at in its life-cycle?</p>
<ul>
<li>small project, basically done?<!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>need docs?<!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>big project, a billion needs?<!-- .element: class="fragment" data-fragment-index="1" --></li>
<li>etc.<!-- .element: class="fragment" data-fragment-index="1" --></li>
</ul>
<p>Think about those, and then see if you can pick a project that’s a good fit for your current skillset and comfort level and jump in!</p>
</section>
</section>
</section>
<section id="conclusion" class="level2">
<h2>Conclusion</h2>
<p>And that’s a good place to wrap things up! I hope you’re feeling like <em>you can do this</em>. Because you can. Open-source a project of your own and see where it goes. Write a blog post. Add some docs. Open a PR. Record a podcast. Make some videos. Start a meet up. Become a contributor! And remember:</p>
<ul>
<li>Anyone can contribute meaningfully.</li>
<li>People can contribute in a stunning variety of ways.</li>
</ul>
</section>
<section id="more-info" class="level2">
<h2>More info</h2>
<ul>
<li><a href="https://www.rust-lang.org/en-US/contribute.html" class="uri">https://www.rust-lang.org/en-US/contribute.html</a></li>
<li><a href="https://blog.rust-lang.org/2017/09/18-impl-future-for-rust.html" class="uri">https://blog.rust-lang.org/2017/09/18-impl-future-for-rust.html</a></li>
<li><a href="https://internals.rust-lang.org/" class="uri">https://internals.rust-lang.org/</a></li>
<li><code>#rust</code>, <code>#rust-community</code>, <code>#rust-internals</code>, etc. on irc.mozilla.org</li>
</ul>
</section>
Chris KrychoThu, 02 Nov 2017 07:00:00 -0400tag:v4.chriskrycho.com,2017-11-02:/2017/becoming-a-contributor.htmltalkssoftware developmentrustopen source softwareAnnouncing True Myth 1.0http://v4.chriskrycho.com/2017/announcing-true-myth-10.html<p>I’m pleased to announce the release of <a href="https://github.com/chriskrycho/true-myth">True Myth 1.0</a>! True Myth is a library I’ve been working on over the last month or so, for saner programming in JavaScript, with first-class support for TypeScript (and Flow).</p>
<p>True Myth provides standard, type-safe wrappers and helper functions to help you with two <em>extremely</em> common cases in programming:</p>
<ul>
<li>not having a value—which it solves with a <code>Maybe</code> type and associated helper functions and methods</li>
<li>having a <em>result</em> where you need to deal with either success or failure—which it solves with a <code>Result</code> type and associated helper functions and methods</li>
</ul>
<p>You could implement all of these yourself – it’s not hard! – but it’s much easier to just have one extremely well-tested library you can use everywhere to solve this problem once and for all.</p>
<p>Even better to get one of these with no runtime overhead for using it other than the very small cost of some little container objects—which we get by leaning hard on the type systems in TypeScript or Flow!</p>
<p><strong>Aside:</strong> If you’re familiar with <a href="http://folktale.origamitower.com">Folktale</a> or <a href="https://sanctuary.js.org">Sanctuary</a>, this has a lot in common with them—its main differences are:</p>
<ul>
<li>True Myth has a much smaller API surface than they do</li>
<li>True Myth aims to be much more approachable for people who aren’t already super familiar with functional programming concepts and jargon</li>
<li>True Myth does <em>no</em> runtime checking of your types, whereas both those libraries do by default—it relies on TypeScript or Flow instead</li>
</ul>
<p>I really like both of those libraries, though, so you might check them out as well!</p>
<section id="maybe" class="level2">
<h2><code>Maybe</code></h2>
<p>Sometimes you don’t have a value. In JavaScript land, we usually represent that with either <code>null</code> or <code>undefined</code>, and then trying to program defensively in the places we <em>think</em> we might get <code>null</code> or <code>undefined</code> as arguments to our functions. For example, imagine an endpoint which returns a JSON payload shaped like this:</p>
<pre class="json"><code>{
&quot;hopefullyAString&quot;: &quot;Hello!&quot;
}</code></pre>
<p>But sometimes it might come over like this:</p>
<pre class="json"><code>{
&quot;hopefullyAString&quot;: null
}</code></pre>
<p>Or even like this:</p>
<pre class="json"><code>{}</code></pre>
<p>Assume we were doing something simple, like logging the length of whatever string was there or logging a default value if it was absent. In normal JavaScript we’d write something like this:</p>
<pre class="javascript"><code>function logThatValue(thePayload) {
const length = !!thePayload.hopefullyAString
? thePayload.hopefullyAString.length
: 0;
console.log(length);
}
fetch(someUrl)
.then(response =&gt; response.json())
.then(logThatValue);</code></pre>
<p>This isn’t a big deal right here… but—and this <em>is</em> a big deal—we have to remember to do this <em>everywhere</em> we interact with this payload. <code>hopefullyAString</code> can <em>always</em> be <code>undefined</code> or <code>null</code> everywhere we interact with it, anywhere in our program. 😬</p>
<p><code>Maybe</code> is our escape hatch. If, instead of just naively interacting with the payload, we do a <em>very small</em> amount of work up front to normalize the data and use a <code>Maybe</code> instead of passing around <code>null</code> or <code>undefined</code> values, we can operate safely on the data throughout our application. If we have something, we get an instance called <code>Just</code>—as in, “What’s in this field? Just a string” or “Just the string ‘hello’”. If there’s nothing there, we have an instance called <code>Nothing</code>. <code>Just</code> is a wrapper type that holds the actual value in it. <code>Nothing</code> is a wrapper type which has no value in it. But both of them are concrete types and you’ll never get an <code>undefined is not an object</code> error when trying to use them!</p>
<p>Both of them have all the same methods available on them, and the same static functions to work on them. And, importantly, you can do a bunch of neat things with a <code>Maybe</code> instance without checking whether it’s a <code>Nothing</code> or a <code>Just</code>. For example, if you want to double a number if it’s present and do nothing if it isn’t, you can use the <code>Maybe.map</code> function:</p>
<pre class="typescript"><code>import Maybe from &#39;true-myth/maybe&#39;;
const hereIsANumber = Maybe.just(12); // Just(12)
const noNumberHere = Maybe.nothing&lt;number&gt;(); // Nothing
const double = (n: number) =&gt; n * 2;
hereIsANumber.map(double); // Just(24)
noNumberHere.map(double); // Nothing</code></pre>
<p>There are <a href="https://true-myth.js.org/modules/_maybe_.html">a <em>lot</em></a> of those helper functions and methods! Just about any way you would need to interact with a <code>Maybe</code> is there.</p>
<p>So now that we have a little idea what <code>Maybe</code> is for and how to use it, here’s that same example, but rewritten to normalize the payload using a <code>Maybe</code> instance. We’re using TypeScript, so we will get a compiler error if we don’t handle any of these cases right—or if we try to use the value at <code>hopefullyAString</code> directly after we’ve normalized it!</p>
<p>(Note that <code>Maybe.of</code> will construct either a <code>Maybe.Just</code> if the string is present, or <code>Maybe.Nothing</code> if the value supplied to it is <code>null</code> or <code>undefined</code>.)</p>
<pre class="typescript"><code>import Maybe from &#39;true-myth/maybe&#39;;
type Payload = { hopefullyAString?: string };
type NormalizedPayload = { hopefullyAString: Maybe&lt;string&gt; };
function normalize(payload: Payload): NormalizedPayload {
return {
hopefullyAString: Maybe.of(payload.hopefullyAString)
};
}
function logThatValue(payload: NormalizedPayload) {
const length = payload.hopefullyAString.mapOr(0, s =&gt; s.length);
console.log(length);
}
fetch(someUrl)
.then(response =&gt; response.json())
.then(normalize)
.then(logThatValue);</code></pre>
<p>Now, you might be thinking, <em>Sure, but we could get the same effect by just supplying a default value when we deserialize the data.</em> That’s true, you could! Here, for example, you could just normalize it to an empty string. And of course, if just supplying a default value at the API boundary is the right move, you can still do that. <code>Maybe</code> is another tool in your toolbox, not something you’re <em>obligated</em> to use everywhere you can.</p>
<p>However, sometimes there isn’t a single correct default value to use at the API boundary. You might need to handle that missing data in a variety of ways throughout your application. For example, what if you need to treat “no value” distinctly from “there’s a value present, and it’s an empty string”? <em>That’s</em> where <code>Maybe</code> comes in handy.</p>
</section>
<section id="result" class="level2">
<h2><code>Result</code></h2>
<p>Another common scenario we find ourselves in is dealing with operations which might fail. There are a couple patterns we often use to deal with this: <em>callbacks</em> and <em>exceptions</em>. There are major problems with both, especially around reusability and composability.</p>
<p>The callback pattern (as in e.g. Node) encourages a style where literally every function starts with the exact same code:</p>
<pre class="js"><code>function getMeAValue(err, data) {
if (err) {
return handleErr(err);
}
// do whatever the *actual* point of the function is
}</code></pre>
<p>There are two major problems with this:</p>
<ol type="1">
<li><p>It’s incredibly repetitive – the very opposite of “Don’t Repeat Yourself”. We wouldn’t do this with <em>anything</em> else in our codebase!</p></li>
<li><p>It puts the error-handling right up front and <em>not in a good way.</em> While we want to have a failure case in mind when designing the behavior of our functions, it’s not usually the <em>point</em> of most functions – things like <code>handleErr</code> in the above example being the exception and not the rule. The actual meat of the function is always after the error handling.</p></li>
</ol>
<p>But if we’re not using some similar kind of callback pattern, we usually resort to exceptions. But exceptions are unpredictable: you can’t know whether a given function invocation is going to throw an exception until runtime as someone calling the function. No big deal if it’s a small application and one person wrote all the code, but with even a few thousand lines of code or two developers, it’s very easy to miss that. And then this happens:</p>
<pre class="js"><code>// in one part of the codebase
function getMeAValue(url) {
if (isMalformed(url)) {
throw new Error(`The url `${url}` is malformed!`);
}
// do something else to load data from the URL
return data;
}
function render(toRender) {
// if toRender can&#39;t generate valid HTML, throw Error(&quot;invalid HTML&quot;);
// if it can, theRenderedHTML;
}
function setDom(html) {
/* magic to render into DOM */
}
// somewhere else in the codebase -- throws an exception
const badUrl = &#39;http:/www.google.com&#39;; // missing a slash
const response = getMeAValue(badUrl); // throws here
// we never get here, but it could throw too
const htmlForPage = render(value);
// so we definitely can&#39;t get here safely
setDom(htmlForPage);</code></pre>
<p>Notice: there’s no way for the caller to know that the function will throw. Perhaps you’re very disciplined and write good docstrings for every function – <em>and</em> moreover, perhaps everyone’s editor shows it to them <em>and</em> they pay attention to that briefly-available popover. More likely, though, this exception throws at runtime and probably as a result of user-entered data – and then you’re chasing down the problem through error logs.</p>
<p>More, if you <em>do</em> want to account for the reality that any function anywhere in JavaScript might actually throw, you’re going to write something like this:</p>
<pre class="js"><code>try {
const badUrl = &#39;http:/www.google.com&#39;; // missing a slash
const response = getMeAValue(badUrl); // throws here
// we never get here, but it could throw too
const htmlForPage = render(value);
// so we definitely can&#39;t get here safely
setDom(htmlForPage);
} catch (e) {
handleErr(e); // ends up here
}</code></pre>
<p>This is like the Node example <em>but even worse</em> for repetition!</p>
<p>And TypeScript and Flow can’t help you here! They don’t have type signatures to say “This throws an exception!” (TypeScript’s <code>never</code> might come to mind, but it might mean lots of things, not just exception-throwing.)</p>
<p>Instead, we can use a <code>Result</code> to get us a container type, much like <code>Maybe</code>, to let us deal with this scenario. A <code>Result</code> is either an <code>Ok</code> wrapping around a value (like <code>Just</code> does) or an <code>Err</code> wrapping around some type defining what went wrong (<em>not</em> like <code>Nothing</code>, which has no contents). Both of them have the same sets of methods on them, and the same static functions which can operate on them.</p>
<pre class="typescript"><code>import Result from &#39;true-myth/result&#39;;
type Payload = {/* details of the payload...*/}
function getMeAValue(url: string): Result&lt;Payload, string&gt; {
if (isMalformed(url)) {
return Result.err(`The url &#39;${url}&#39; is malformed`);
}
// do something else to load data from the url
return Result.ok(data);
}
function render(toRender: string): Result&lt;HTMLElement, string&gt; {
// if toRender can&#39;t generate valid HTML, return Err(&quot;invalid HTML&quot;);
// if it can, return Ok(theRenderedHTML);
}
function setDom(html: HTMLElement) {
}
// somewhere else in the codebase -- no exception this time!
const badUrl = &#39;http:/www.google.com&#39;; // missing a slash
// value = Err(The url &#39;${http:/www.google.com}&#39; is malformed)
const value = getMeAValue(badUrl);
// htmlForPage = the same error! or, if it was Ok, could be a different
// `Err` (because of how `andThen` works).
const htmlForPage = value.andThen(render);
// we can&#39;t just invoke `setDom` because it doesn&#39;t take a `Result`.
value.match({
Ok: html =&gt; setDom(html);
Err: reason =&gt; alert(`Something went seriously wrong here! ${reason}`);
})</code></pre>
<p>When we have a <code>Result</code> instance, we can perform tons of operations on whether it’s <code>Ok</code> or <code>Err</code>, just as we could with <code>Maybe.Just</code> and <code>Maybe.Nothing</code>, until we <em>need</em> the value. Maybe that’s right away. Maybe we don’t need it until somewhere else deep in our application! Either way, we can deal with it easily enough, and have type safety throughout!</p>
</section>
<section id="conclusion" class="level2">
<h2>Conclusion</h2>
<p>Give it a spin!</p>
<ul>
<li><code>yarn add true-myth</code></li>
<li><code>npm install true-myth</code></li>
<li>You can even just <code>ember install true-myth</code> and use it if you’re using Ember (in which case I encourage you to also use <a href="https://github.com/typed-ember/ember-cli-typescript">ember-cli-typescript</a>)</li>
</ul>
<p>Let me know what you think – if there’s stuff missing, <a href="https://github.com/chriskrycho/true-myth">open issues</a>! And if it’s just not to your taste, again, I encourage you to take a look at <a href="http://folktale.origamitower.com">Folktale</a> and <a href="https://sanctuary.js.org">Sanctuary</a>, which are both excellent and land in very different design spaces in many ways.</p>
</section>
Chris KrychoWed, 01 Nov 2017 08:40:00 -0400tag:v4.chriskrycho.com,2017-11-01:/2017/announcing-true-myth-10.htmlsoftware developmentlibrariesprogramming languagestypescriptfunctional programmingtrue mythDifferences of Opinionhttp://v4.chriskrycho.com/2017/differences-of-opinion.html<p>I could not possibly agree more with <a href="http://www.pyret.org/pyret-code/">this view of teaching software/CS</a>.</p>
<blockquote>
<p>We are focused on introductory programming education at a high-school and collegiate level — what is often called “CS 1” and “CS 2” (roughly, the first year of college). Pyret is being actively used in everything from high-schools to upper-level collegiate courses, giving us a tight feedback loop.</p>
<p>Of course, even in that setting there are differences of opinion about what needs to be taught. Some believe inheritance is so important it should be taught early in the first semester. We utterly reject this belief (as someone once wisely said, “object-oriented programming does not scale down”: what is the point of teaching classes and inheritance when students have not yet done anything interesting enough to encapsulate or inherit from?). Some have gone so far as to start teaching with Turing Machines. Unsurprisingly, we reject this view as well.</p>
<p>What we do not take a dogmatic stance on is exactly how early state and types should be introduced. Pyret has the usual stateful operations. We discussed this at some length, but eventually decided an introduction to programming must teach state. Pyret also has optional annotations, so different instructors can, depending on their preference, introduce types at different times.</p>
</blockquote>
<p>I’m <em>delighted</em> to see work on languages like Dr. Racket and Pyret, and the more so because the teams behind both have been willing to set aside many of the dogmas of how CS has been taught and actually do <em>pedagogical research</em>. Also: OOP is a useful tool, but I’m with them: treating inheritance as a first-semester concept is… nutty.</p>
<p>The whole <a href="http://www.pyret.org/pyret-code/">“Why Pyret?”</a> page is worth reading if you have any interest in programming languages or teaching software development and computer science.</p>
Chris KrychoSun, 12 Mar 2017 08:05:00 -0400tag:v4.chriskrycho.com,2017-03-12:/2017/differences-of-opinion.htmlprogramming languagessoftware developmentpedagogylinksBetter Off Using Exceptions?http://v4.chriskrycho.com/2017/better-off-using-exceptions.html<p>I saw this post on error-handling in F<sup>♯</sup>, <a href="https://eiriktsarpalis.wordpress.com/2017/02/19/youre-better-off-using-exceptions/" title="You’re better off using Exceptions">“You’re better off using Exceptions”</a> making the rounds on Twitter:</p>
<blockquote>
<p>Exception handling is an error management paradigm that has often been met with criticism. Such criticisms typically revolve around scoping considerations, exceptions-as-control-flow abuse or even the assertion that exceptions are really just a type safe version of goto. To an extent, these seem like valid concerns but it is not within the scope of this article to address those per se.</p>
<p>Such concerns resonate particularly well within FP communities, often taken to the extreme: we should reject exceptions Show more…</p>
</blockquote>
<p>And I get the argument, and in the specific context of F<sup>♯</sup>—especially given how much C<sup>♯</sup>-interoperating and therefore exception-throwing-code-interoperating there is there—it’s reasonable.</p>
<p>But it still makes me sad. (To be clear: exceptions were and are a big win over what you get in languages like C. I’ll take them any day over <code>goto</code> or <code>segfault</code>.)</p>
<p>You need to embrace exceptions in F<sup>♯</sup> <em>because F<sup>♯</sup> has exceptions</em> and because <em>many of its libraries rely on exceptions</em>. But my experience with Rust and other non-exception-using languages is that you <em>don’t</em> need exceptions in the general case.</p>
<p>The questions are: whether your language has good support for things like flat-mapping, and whether you’re willing to commit to letting the compiler help you with these problems.</p>
<p>To be sure: there’s more work involved up front to deal with that. But that’s a tradeoff I’m <em>always</em> willing to make. I’d rather have the compiler tell me if I’m failing to account for something than learn because I saw a runtime error report come up in <a href="https://raygun.com">Raygun</a>, especially because that tends to mean an error that affects the user in some way.</p>
<p>Rust’s model gives you something like exceptions for truly unrecoverable errors, “panics.” A panic gives you all the context you’d get from an exception (one of the virtues of exceptions highlighted in that post), but you can only “catch” it at thread boundaries, and it otherwise just kills the program. Because it’s catastrophic, you only use it where you don’t have any way to recover in your immediate context. But where you can recover in your immediate context… using something like a highly descriptive enum (just as suggested at the end of <a href="https://eiriktsarpalis.wordpress.com/2017/02/19/youre-better-off-using-exceptions/" title="You’re better off using Exceptions">that original post</a>!) is a better option.</p>
<p>It’s well-understood in my circles that you shouldn’t use exceptions for things you can recover from; you should use them for things you <em>can’t</em> recover from. But in most languages which lean heavily on exceptions, you inevitably start using them for control flow. I say: if you can recover from an error… just recover from it! Account for recoverable errors as possible conditions in your program and carry on! If you can’t recover… don’t. Die and let some other part of your system kick things back off.</p>
<p>In summary: yes, if you’re in F<sup>♯</sup>, use exceptions. It <em>is</em> the right thing to do in many cases (and you don’t have a choice in many others). But I’m hopeful for a future where we handle recoverable errors locally, and <a href="http://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html">act like Erlang or Elixir otherwise</a>.</p>
Chris KrychoMon, 20 Feb 2017 12:00:00 -0500tag:v4.chriskrycho.com,2017-02-20:/2017/better-off-using-exceptions.htmlfsharpsoftware developmentrustfunctional programmingTypeScript keyof Follow-Uphttp://v4.chriskrycho.com/2017/typescript-keyof-follow-up.html<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>
<p>In the previous post, I concluded with an example that looked like this:</p>
<pre class="typescript"><code>type UnionKeyToValue&lt;U extends string&gt; = {
[K in U]: K
};
type State
= &#39;Pending&#39;
| &#39;Started&#39;
| &#39;Completed&#39;;
// Use `State` as the type parameter to `UnionKeyToValue`.
const STATE: UnionKeyToValue&lt;State&gt; = {
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
}</code></pre>
<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>
<p>It turns out we don’t <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>
<figure>
<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>
</figure>
<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’s 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>
<p>This makes it something of a wash with the original approach, as long as you’re 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’re just progressively adding TypeScript to an existing JavaScript codebase, that’s possibly reason enough to stick with it.</p>
<p><strong>Edit</strong>: an additional reason to prefer my original solution:</p>
<blockquote class="twitter-tweet" data-lang="en">
<p lang="en" dir="ltr">
<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.
</p>
— Timm (@timmpreetz) <a href="https://twitter.com/timmpreetz/status/816672215924097024">January 4, 2017</a>
</blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
Chris KrychoTue, 03 Jan 2017 20:35:00 -0500tag:v4.chriskrycho.com,2017-01-03:/2017/typescript-keyof-follow-up.htmlprogramming languagessoftware developmenttypescriptjavascript2016 in Review, Part 6 of 6http://v4.chriskrycho.com/2017/2016-review-6.html<p><i class='editorial'>I originally drafted a single, mammoth post reflecting on this whole year—but at more than 6,000 words, that seemed like a bit much. As such, I’ve broken it into a series of posts, to be published daily through the start of the new year. Hopefully they’re a bit more digestible that way!</i></p>
<ul>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-intro.html">Introduction, or: a ridiculous year summarized</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-1.html">Part 1: Running headfirst into a wall of pneumonia.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-2.html">Part 2: So. many. words. I had no idea how many words.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-3.html">Part 3: Podcasting: Winning Slowly, New Rustacean, and more!</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-4.html">Part 4: Writing software for Olo and for open source.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-5.html">Part 5: Getting things done in 2016 and beyond.</a></li>
<li>Part 6: Plans for 2017! (this post)</li>
</ul>
<hr />
<p>In 2017, I really only have a few big goals:</p>
<ol type="1">
<li>Graduate seminary.</li>
<li>Spend good time with my family.</li>
<li>Love our church well.</li>
<li>Work hard for Olo.</li>
<li>Save money for a house.</li>
<li>Replace <a href="https://github.com/getpelican/pelican">Pelican</a> with <a href="https://github.com/chriskrycho/lightning-rs">Lightning</a> for this site.</li>
</ol>
<p>I have a bunch of smaller goals, too, of course. That list includes:</p>
<ul>
<li>publish two episodes of New Rustacean every month (of various formats—not all the full-length teaching-a-subject type)</li>
<li>publish 16–20 episodes of Winning Slowly</li>
<li>complete a full-length sprint triathlon<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></li>
<li>run a <a href="http://cityofoaksmarathon.com">marathon</a></li>
<li>be able to do 15 consecutive pull-ups and 100 consecutive push-ups</li>
<li>lose ten pounds and get back down to my target weight</li>
<li>document all the undocumented features in Rust, and get the Rust reference all the way up to date (<a href="https://github.com/rust-lang/rust/issues/38643">tracking issue</a>)</li>
<li>finish a couple side projects (and bring in the associated money!)</li>
<li>teach in our small group at least a half dozen times</li>
<li>write at least one long essay for Mere Orthodoxy</li>
<li>publish the scripts and transcripts of New Rustacean as an ebook</li>
<li>publish hard copies of the archives of my blog, in a way that mirrors the style of the site at the time it was written</li>
<li>fully archive the Blogger and WordPress versions of this blog as static HTML</li>
<li>move all the sites I host (mine and others) out of shared hosting and into a server I manage (probably Digital Ocean or Linode)</li>
</ul>
<p>But basically all of those are flexible (and, if I’m honest, so is #6 in the first list—though it’s a <em>high</em> priority as far as the flexible ones go).</p>
<p>I have a pretty good handle on how I’m going to chase those things. The productivity patterns I’ve established over the last couple years are serving me well so far, and I expect them to continue to. After graduation, things will obviously look a little different, and I’m looking forward to that, too. Being able to take vacations where I’m not losing ground by not working on school projects? That sounds truly amazing.</p>
<p>I’m also looking forward to digging into more books I want to read and making progress on writing I want to do in the realm of theology, philosophy, ethics, and so on. I’ve spent nearly all the mental energy I have available for those subjects on seminary work over the past several years (with varying degrees of value for that effort). Once again being able to focus my own external studies as I like will be very freeing, I think. I hope to find some ways to continue to work at something like an academic level, and—crazy though it sounds right <em>now</em>—I do hope to get a Ph.D. in <em>something</em> in a few decades. But I am looking forward to having a lot of years of reading and writing outside academia between now and then.</p>
<p>All those goals are good, but ultimate I’m willing to just see what the year brings. I’d love to compose music again more regularly and at greater length. I’d love to write more fiction, and more (and better) poetry. But we’ll also be starting some schooling with Ellie, and dealing with the logistics of planning a move to Colorado sometime in late 2017 or the first half of 2018. We’ll be enjoying just not having nearly so much to do right after finishing seminary. It’s worth remembeirng to rest, and not do just jump into another season of being incredibly slammed by busyness. I plan to take some time to read novels and play video games, too. Those things are good for our souls in their own way.</p>
<p>And come what may, I hope to glorify God in the midst of it. Rest, work, play, side projects, you name it—<em>soli deo gloria.</em></p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>750m swim, 20km (12mi) ride, 5km (3.1mi) run<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSun, 01 Jan 2017 08:00:00 -0500tag:v4.chriskrycho.com,2017-01-01:/2017/2016-review-6.htmlwritingpodcastingsoftware developmentfamilyproductivityfitness2016-in-review2016 in Review, Part 5 of 6http://v4.chriskrycho.com/2016/2016-review-5.html<p><i class='editorial'>I originally drafted a single, mammoth post reflecting on this whole year—but at more than 6,000 words, that seemed like a bit much. As such, I’ve broken it into a series of posts, to be published daily through the start of the new year. Hopefully they’re a bit more digestible that way!</i></p>
<ul>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-intro.html">Introduction, or: a ridiculous year summarized</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-1.html">Part 1: Or: a ridiculous year summarized!</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-2.html">Part 2: So. many. words. I had no idea how many words.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-3.html">Part 3: Podcasting: Winning Slowly, New Rustacean, and more!</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-4.html">Part 4: Writing software for Olo and for open source.</a></li>
<li>Part 5: Getting things done in 2016 and beyond. (this post)</li>
<li><a href="http://v4.chriskrycho.com/2017/2016-review-6.html">Part 6: Plans for 2017!</a></li>
</ul>
<hr />
<p>At a number of points over the last few years, I’ve tackled the question of productivity. I always have far more I <em>want</em> to get done than I’m able to actually get to. A few of those posts:</p>
<ul>
<li><a href="http://v4.chriskrycho.com/2014/boosting-my-productivity.html" title="Boosting My Productivity">Boosting My Productivity</a> (December, 2014)</li>
<li><a href="http://v4.chriskrycho.com/2016/a-new-schedule.html" title="A New Schedule">A New Schedule: Trying to make better use of my time toward my goals</a> (July 2016)</li>
</ul>
<p>A common theme of all productivity plans, of course, is that one can get more focused on the details of the plan than on actually being productive! I’m happy to say, however, that this <em>wasn’t</em> the case for me with these productivity approaches. First, I have never allowed myself to be slavish about them. If I need to do something different on a given day, I do something different. Second, I am generally able to remember that the point of the plan is <em>what I’m getting done</em>. So with that in mind, some comments particularly on the plan I sketched out <a href="http://v4.chriskrycho.com/2016/a-new-schedule.html" title="A New Schedule">mid-year this year</a>.</p>
<p>I fell off that wagon almost immediately. Readers who’ve stuck with me through these various updates will note that this ambitious plan preceded my disastrous 20-mile run and the ensuing bout of walking pneumonia by a matter of days. It took me until September to get back on the horse, so to speak, because even after I got over being sick, I was traveling—and nothing throws off my schedule like traveling! Happily, I got quite a bit done both during the conference trip I took and during the week I was in Colorado for my youngest sister’s wedding, but it wasn’t until after both of those that I was able to settle back into the routine I’d aimed for.</p>
<p>The major themes of that post were a detailed plan for my days, cutting out a lot of my social media, and thinking about weekends. The detailed plan for my days I kept off and on. I never consistently managed to have the block of time-for-side-projects at the end of my days, and that increasingly meant those things cut into weekends (impacting that goal as well). As for social media, that’s largely been a success: I now rarely get on Facebook, and only check Twitter from time to time. Certainly neither is much of a timesink anymore. I do continue to make heavy use of Slack outside of work, but I’ve found a good balance there (and the main communities I’m a part of have gone through their own adjustments as we’ve <em>all</em> found the need for this kind of focus and balance).</p>
<p>So it wasn’t perfect, but I did find it a very useful approach overall. I fully expect to stick with something very like it in 2017. Hopefully I won’t be pulling as many 10–11 hour days as I was in the latter half of 2016—but regardless, building this new discipline around the overall structure of each day was very helpful.</p>
<p>One <em>big</em> part of my approach to productivity that I’m definitely going to keep is the “pomodoro” technique. I first mentioned this in the <a href="http://v4.chriskrycho.com/2014/boosting-my-productivity.html" title="Boosting My Productivity">first</a> discussion I posted about this, but I’ve embraced it more and more. I work in 25-minute blocks, punctuated by 5-minute breaks. Nearly all of those 5-minute breaks entail walking, and as a result I get about 2–3 miles of walking in every day on top of my runs. That helps enormously with focus. This fall, I also embraced the <em>other</em> half of the pomodoro technique: writing down goals and outcomes for each of those 25-minute blocks. Even more than the daily goals I discussed in the opening post of this series, this lower level of tracking has proved very helpful. It has given me a sense of what I have actually accomplished each day, and it has also helped me <em>focus</em> as I’m trying to keep moving on various tasks each day. I highly recommend using the pomodoro approach (adapted as necessary to your particular circumstances, of course) as a tool for that kind of focus and productivity.</p>
<p>I’d be remiss if I didn’t also note the following <em>very</em> substantial factors in my productivity:</p>
<ul>
<li><p><strong>fitness/health:</strong> if I’m active, I focus better. People say they don’t have time to exercise; I mean it when I say I don’t have time <em>not</em> to. I keep it pretty simple: running, cycling, swimming, and body-weight strength stuff. But I do it basically every day. And we eat fairly healthily. Both of those are incredibly important.</p></li>
<li><p><strong>sleep:</strong> no matter how busy I am, I don’t pull all-nighters or anything of the sort. I get a minimum of 6 and usually 7–7½ hours of sleep every night. Even when I’m tired from pulling week after week of 10-hour work days, I can keep going because I get enough sleep.</p></li>
<li><p><strong>no commute:</strong> working remotely is awesome for a lot of reasons, but one of them is that I don’t lose the hour or three every day to the road/subway/etc. that many people I know do. That’s a <em>lot</em> of time over the course of a year. 48 working weeks means if you commute for an hour total every day, that’s 240 hours a year—that’s 30 8-hour days worth of “getting things done”.</p></li>
</ul>
<p>Perhaps at some point after I finish seminary I will expand the various things I do in productivity into a more complete series, but this gives you a good idea of what 2016 looked like, and what I expect 2017 to look like!</p>
Chris KrychoSat, 31 Dec 2016 09:30:00 -0500tag:v4.chriskrycho.com,2016-12-31:/2016/2016-review-5.htmlwritingpodcastingsoftware developmentfamilyproductivityfitness2016-in-reviewpomodoro2016 in Review, Part 4 of 6http://v4.chriskrycho.com/2016/2016-review-4.html<p><i class='editorial'>I originally drafted a single, mammoth post reflecting on this whole year—but at more than 6,000 words, that seemed like a bit much. As such, I’ve broken it into a series of posts, to be published daily through the start of the new year. Hopefully they’re a bit more digestible that way!</i></p>
<ul>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-intro.html">Introduction, or: a ridiculous year summarized</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-1.html">Part 1: Running headfirst into a wall of pneumonia.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-2.html">Part 2: So. many. words. I had no idea how many words.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-3.html">Part 3: Podcasting: Winning Slowly, New Rustacean, and more!</a></li>
<li>Part 4: Writing software for Olo and for open source. (this post)</li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-5.html">Part 5: Getting things done in 2016 and beyond.</a></li>
<li><a href="http://v4.chriskrycho.com/2017/2016-review-6.html">Part 6: Plans for 2017!</a></li>
</ul>
<hr />
<p>This year at Olo was a great year overall. I very much enjoy working with the people there, the tech stack is good and they’re paying me to do what I love, and if the product isn’t lighting my world on fire (online restaurant ordering is cool, but restaurants aren’t a passion of mine), that’s a tradeoff I can live with. Working with good people with a good tech stack on a product you find <em>fine</em> rather than <em>amazing</em> is actually pretty great. I’m grateful for previous jobs, but this one has superceded them in every possible way. I’m <em>glad</em> to start work every day—and in truth, there have been more than a few days where I would have liked nothing more than to keep writing JavaScript rather than switching over to do some reading and writing for seminary. That bodes well for my future plans: post-seminary, I expect to bump from 30 to 40 hours a week with Olo<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> and keep making our software as awesome as I can. And I expect to enjoy that!</p>
<p>Speaking of numbers: GitHub reports that I contributed +29,463/−13,726 lines of code in our new mobile web ordering experience, which I helped build nearly from scratch this year. (That “negative” is stuff I rewrote or removed entirely by finding a better implementation.)</p>
<p>Quite a bit of my <a href="http://v4.chriskrycho.com/2016/2016-review-2.html">writing</a> this year was technical, too: some ~33,000 of the words on my blog—fully a third of the things I published on this site apart from microblog posts and schoolwork—was about software. That included entries 11–18 of my <a href="http://v4.chriskrycho.com/rust-and-swift.html">Rust and Swift</a> series, but about 20,000 words were assorted discussions of JavaScript, Rust, podcasting, functional programming, etc. A fair bit of that content came out of things I worked on for Olo, either directly (as in the case of <a href="http://v4.chriskrycho.com/2016/what-is-functional-programming.html" title="What is Functional Programming? (And why should we care about it?)">this talk</a>) or indirectly (as in the case of <a href="http://v4.chriskrycho.com/2016/keyof-and-mapped-types-in-typescript-21.html" title="keyof and Mapped Types in TypeScript 2.1">this discussion of TypeScript 2.1</a>) That’s a good mix, and I hope to continue putting out material that’s useful to others as well as interesting to me. (I do get tweets now and again confirming that the content is helpful, and I <em>don’t</em> run analytics on the site at all—so if you like something I write, please tell me. It’s encouraging. And that goes for <em>any</em> author you read, as a rule.)</p>
<p>Finally, I actually did a little bit of open-source contributing this year. Not as much as I’d like, but a little. And I also count New Rustacean as a pretty substantial contribution to the Rust community. The fact that it isn’t code doesn’t diminish what it’s doing. If you’re feeling like code is the only thing that <em>really</em> counts, recognize that all the code in the world isn’t that useful without explanations of how to use it, helping people become interested in the first place, and so on. Speaking of non-code contributions, the open-source contribution I’m <em>most</em> proud of is certainly the <a href="https://github.com/rust-lang/rfcs/pull/1636">Rust RFC</a> I wrote and which was recently accepted and merged. It proposed (and it is now the official policy of the Rust project) that no new features may be added to the (stable version of the) language or the standard library without first being documented. This is a big deal for the language, and it was also a big deal for me, in that it was another place where—despite being far too busy to write a lot of Rust code this year—I could make a real difference in a community I’m passionate about. And one of my goals for next year is a direct follow-on from that: <a href="https://github.com/rust-lang/rust/issues/38643">actually implementing the requirement</a>!</p>
<p>The other big thing going on for me in the software world is that I started work on <a href="https://github.com/chriskrycho/lightning-rs">Lightning</a>, a new static site generator in Rust. (There’s another such project, <a href="http://cobalt-org.github.io">Cobalt</a>, which is already usable.) I’ve been pushing up against the limits of <a href="http://docs.getpelican.com/en/stable/">Pelican</a>, my current generator, for a while. And I’ve looked around time and again, and never found a CMS or SSG that does everything my peculiar publishing needs require (<em>especially</em> in a way that I like!). And my needs are indeed peculiar, though probably not wholly unique; for most people, any one of <a href="https://staticsitegenerators.net"><em>many</em> other site generators</a> would work just fine. So I’m doing what I’ve been thinking about doing for years, and building my own. My immediate goals are mostly just to have something that is super speedy and which checks off all my needs from a CMS/site generator. My longer-term goals include getting some good foundational knowledge I’ll need for <a href="http://v4.chriskrycho.com/2016/ulysses-byword-and-just-right.html">my <em>next</em> project</a>. I’m a thousand lines in, and have some pieces working. I hope very much to move off of Pelican and onto Lightning (and get a freshened theme for this site) in 2017!</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Yes, Olo has been incredibly generous and hired me as a full-time employee at 30-hours-a-week with pro-rated salary. Like I said: amazing company.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 30 Dec 2016 07:00:00 -0500tag:v4.chriskrycho.com,2016-12-30:/2016/2016-review-4.htmlwritingpodcastingsoftware developmentfamilyproductivityfitness2016-in-review2016 in Review, Part 3 of 6http://v4.chriskrycho.com/2016/2016-review-3.html<p><i class='editorial'>I originally drafted a single, mammoth post reflecting on this whole year—but at more than 6,000 words, that seemed like a bit much. As such, I’ve broken it into a series of posts, to be published daily through the start of the new year. Hopefully they’re a bit more digestible that way!</i></p>
<ul>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-intro.html">Introduction, or: a ridiculous year summarized</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-1.html">Part 1: Running headfirst into a wall of pneumonia.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-2.html">Part 2: So. many. words. I had no idea how many words.</a></li>
<li>Part 3: Podcasting: Winning Slowly, New Rustacean, and more! (this post)</li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-4.html">Part 4: Writing software for Olo and for open source.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-5.html">Part 5: Getting things done in 2016 and beyond.</a></li>
<li><a href="http://v4.chriskrycho.com/2017/2016-review-6.html">Part 6: Plans for 2017!</a></li>
</ul>
<hr />
<p>Beyond <a href="http://v4.chriskrycho.com/2016/2016-review-2.html">the written word</a>, the other “writing”-type work I had this year—some of it including <em>actual</em> writing in the form of detailed scripts—was podcasting!</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">Show</th>
<th style="text-align: center;">Episodes</th>
<th style="text-align: center;">Total time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><a href="http://www.winningslowly.org">Winning Slowly</a></td>
<td style="text-align: center;">25</td>
<td style="text-align: center;">11h 40m</td>
</tr>
<tr class="even">
<td style="text-align: center;"><a href="http://www.newrustacean.com">New Rustacean</a></td>
<td style="text-align: center;">22</td>
<td style="text-align: center;">6h 46m</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><a href="http://runwith.chriskrycho.com">Run With Me</a></td>
<td style="text-align: center;">19</td>
<td style="text-align: center;">1h 1m</td>
</tr>
<tr class="even">
<td style="text-align: center;"><a href="http://www.sap-py.com">sap.py</a></td>
<td style="text-align: center;">1</td>
<td style="text-align: center;">12m</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><strong>Total</strong></td>
<td style="text-align: center;"><strong>67</strong></td>
<td style="text-align: center;"><strong>19h 39m</strong></td>
</tr>
</tbody>
</table>
<p>Again, several of those numbers surprised me a bit. For one thing, I had to put New Rustacean on hiatus starting in October courtesy of the crunch I ended up with from the <em>Rust vs. Swift</em> project colliding with the other summer-and-fall commitments I had. For another Stephen and I paused Winning Slowly between Seasons 4 and 5 (as we usually do) and also have taken a mid-season pause on Season 5 because of end-of-semester crunches for both of us and then his wife having a baby a few weeks earlier than expected. Yet in spite of that, almost 20 hours of audio content this year! If I hit that again in 2017, I’ll be happy.</p>
<p>Whether <a href="http://www.sap-py.com">sap.py</a> will be back, I have no idea. I love making the show with Jaimie, but it’s really up to her whether she wants to keep working on Python. Of late, she’s been working on <a href="https://www.etsy.com/shop/PemberlyPrintables" title="Jaimie&#39;s printable shop on Etsy">printable art</a> instead, and that’s delightful in its own right. I’ve <a href="http://runwith.chriskrycho.com/runs/14/">just</a> gotten <a href="http://runwith.chriskrycho.com">Run With Me</a> going again in the past day; I got off track when my headphone microphone stopped working for a bit and never got back <em>on</em> track when it started working again. I’m looking forward to once again talking about running while running.</p>
<p>I expect to be publishing an even wider variety of kinds of episodes of New Rustacean in 2017. Listeners should get another couple of interviews, a lot more of the “here is a Rust concept in detail” episodes (at least one a month in general, I hope!), news episodes, undoubtedly a few bonus episodes, and a new “Crates You Should Know” format designed to highlight crates I’ve found useful in my own Rust work. I continue to find Rust a wonderful language, and I hear regularly that this is one of people’s favorite programming podcasts. I hope to keep it that way!</p>
<p>We expect to wrap up <a href="http://www.winningslowly.org/season-5.html" title="Winning Slowly Season 5: Structure and Agency">Season 5</a> of <a href="http://www.winningslowly.org">Winning Slowly</a> mid-spring, and then begin recording Season 6 mid-to-late summer. All of that is pending how things go as Stephen finishes his dissertation and likely prepares to move across the country to take a job as a professor somewhere, of course. But that’s the plan—and yes, we already know the rough shape of Season 6, even this far out. We know the season topic, and have some basic ideas of where we want to go with it. As is usually the case with our “seasons” now, it will take ideas we’ve touched on here and there and turn them into a full-blown, months-long exploration of those ideas as applied to specific issues. Winning Slowly remains one of my very favorite projects, not least because there is (to our knowledge) nothing else out there doing quite the same thing. Tackling long-term trends in technology with a distinctively (though not always overtly) Christian perspective (but <em>not</em> a reductionist one) is apparently our gap to fill. We’ll take it.</p>
<p>Two other podcasting-related bits. First, I wrote a <a href="https://mereorthodoxy.com/theses-on-podcasting/" title="32 Theses (and several more words) on Podcasting">~5,000-word piece for Mere Orthodoxy</a> explaining how the medium works, what its constraints are, and what is involved in doing it well. If podcasting is interesting to you, I think the piece is well worth your time—precisely because of, and not in spite of, its length! Second, I gave a pair of guest lectures for Stephen at N.C. State University this fall, which are both available in the <a href="http://www.winningslowly.org/season-bonus.html">bonus section</a> on <a href="http://www.winningslowly.org">Winning Slowly</a>. Those cover some of the same ground as the piece at Mere O, but they also talk a lot more about the details of finding a topic, an “authorial voice”, and an angle for your show.</p>
Chris KrychoThu, 29 Dec 2016 10:30:00 -0500tag:v4.chriskrycho.com,2016-12-29:/2016/2016-review-3.htmlwritingpodcastingsoftware developmentfamilyproductivityfitness2016-in-review2016 in Review, Part 2 of 6http://v4.chriskrycho.com/2016/2016-review-2.html<p><i class='editorial'>I originally drafted a single, mammoth post reflecting on this whole year—but at more than 6,000 words, that seemed like a bit much. As such, I’ve broken it into a series of posts, to be published daily through the start of the new year. Hopefully they’re a bit more digestible that way!</i></p>
<ul>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-intro.html">Introduction, or: a ridiculous year summarized</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-1.html">Part 1: Running headfirst into a wall of pneumonia.</a></li>
<li>Part 2: So. many. words. I had no idea how many words. (this post)</li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-3.html">Part 3: Podcasting: Winning Slowly, New Rustacean, and more!</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-4.html">Part 4: Writing software for Olo and for open source.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-5.html">Part 5: Getting things done in 2016 and beyond.</a></li>
<li><a href="http://v4.chriskrycho.com/2017/2016-review-6.html">Part 6: Plans for 2017!</a></li>
</ul>
<hr />
<p>One of my goals for 2016 was to continue writing not only on this blog but in other outlets. I did a <em>lot</em> of writing this year, but relatively little of it is published. But here’s a look at some of the numbers! Note that “This site” excludes republication of school papers, and that I don’t have an exact count for the school papers because I’ve already discarded a few of the shorter pieces, but their average length is well-known to me. More on the unpublished <em>Rust vs. Swift</em> project below.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">Category</th>
<th style="text-align: center;">Words</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><a href="http://v4.chriskrycho.com/m-div/">School</a></td>
<td style="text-align: center;">~130,500</td>
</tr>
<tr class="even">
<td style="text-align: center;"><a href="https://mereorthodoxy.com/author/chris-krycho/">Mere Orthodoxy</a></td>
<td style="text-align: center;">~6000</td>
</tr>
<tr class="odd">
<td style="text-align: center;">This site</td>
<td style="text-align: center;">~63,000<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></td>
</tr>
<tr class="even">
<td style="text-align: center;"><em>Rust vs. Swift</em> project</td>
<td style="text-align: center;">~9350</td>
</tr>
<tr class="odd">
<td style="text-align: center;"><strong>Total</strong></td>
<td style="text-align: center;"><strong>~207,850</strong></td>
</tr>
</tbody>
</table>
<p>Of the writing for school, only a small fraction of it is <a href="http://v4.chriskrycho.com/m-div/">published here</a>, unlike previous years. Roughly 75,000 words of that content is research notes I put together for an independent study I did—which was deeply profitable for me in terms of thinking through hermeneutical and theological systems, and which will hopefully be helpful for the professor for whom I prepared them, but which are not at all publishable. Another 10,000 of those words fit in a category charitably describable as “busy-work” and publishing them is <em>possible</em> but would have no <em>value</em>. The school-writing also includes the notes and manuscripts for my sermon-delivery class. You can find those sermons <a href="http://v4.chriskrycho.com/sermons/">on this site</a> as well well, with audio, video, and the manuscripts available—but the notes are not worth publishing, as they’re entirely internal. Still: they’re words, I wrote them, and there are a lot of them.</p>
<p>On the plus side, I wrote one of the papers I’m proudest of from my entire seminary career in the spring: <a href="http://v4.chriskrycho.com/2016/realism-and-antirealism.html">Realism and Antirealism—A key debate in the philosophy of science (with interesting implications for young-earth creationism)</a>. I’m happy with it not least because I wrote it in a very compressed fashion because of some family health issues that hit at the end of that semester, and it still turned out extremely well because I had <em>planned</em> it meticulously. Despite having only a single draft with one typo-level revision pass, it’s easily the best paper I’ve ever written. It turns out that doing a really careful outline helps when you’re working at this scale. I’ve not normally been a fan of outlining (and I’ve not normally found it helpful when I’ve tried it), but for any longer, more sustained argument, it’s absolutely necessary.</p>
<p>Of the content on this site (excluding republication of school papers), an astounding ~14,000 of those words are in my “microblog” content. It’s amazing how much those little posts add up. That said, I’m surprised to see that I’ve put out as many <em>other</em> words as I have this year on this site, and the total there is rather staggering. Writing on this site includes everything from <a href="http://v4.chriskrycho.com/2016/ask.html" title="Ask: a short story">fiction</a> and <a href="http://v4.chriskrycho.com/2016/to-paint-god-as-a-man.html" title="To paint God as a man: an Advent poem">poetry</a> to <a href="http://v4.chriskrycho.com/2016/a-simple-childrens-catechism.html">a simple children’s catechism</a> to <a href="http://v4.chriskrycho.com/2016/what-is-functional-programming.html">an introduction to functional programming</a>. I’m exceptionally pleased in retrospect to see how this came out, and I look forward to writing on equally varied terms in the year ahead.</p>
<p>Some 13,000 of the words I wrote for this site were in my <a href="http://v4.chriskrycho.com/rust-and-swift.html">Rust and Swift</a> series, a project I’ve enjoyed enormously since starting it in 2015 and would like to get back to in 2017. It went on hold because I was offered, and accepted, a contract to write a 30–40 page report for O’Reilly comparing the two languages, which was intended to come out this fall. Unfortunately, somewhere along the way some wires got crossed and my pitch and what they wanted didn’t end up being the same. Once that became clear (at the beginning of October), they opted to drop the project. This was a huge disappointment to me: it was a small hit financially, but a big one time-wise, as I sunk a <em>lot</em> of hours into it in what was an already-very-busy fall; the project was over ¾ done when it was dropped.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<p>A few big lessons I learned from this:</p>
<ol type="1">
<li><p>Don’t overcommit. Even if the project had gone through without issue, it would have been more on my plate than I could reasonably handle. The fact that it was canceled after having done a lot of the work meant it was also <em>financially</em> frustrating, but I had overcommitted regardless. Won’t do that again.</p></li>
<li><p>Be <em>even more</em> clear up-front about the terms and goals of a project. I don’t know how we ended up with the crossed wires we did, but it was extremely frustrating.</p></li>
<li><p>If you can get an advance, get an advance. Just saying.</p></li>
</ol>
<p>In general, I’m quite pleased with the <em>volume</em> of my output in 2016 (who wouldn’t be, right?). I’d definitely like a lot more of that to be public-facing in 2017, even if it’s lower in overall volume. I hope to take the material from that canceled <em>Rust vs. Swift</em> project, expand it slightly, and self-publish it. I also hope to put together at least one substantive essay for Mere Orthodoxy next year. And of course there will probably be thousands of words in this space, too—inevitably more than I even realize.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Note as well that this excludes all the <a href="https://github.com/chriskrycho/newrustacean.com/tree/589cd13225cde91f92bfca93f6679f2395d78886/docs">podcast scripts</a> I wrote this year! Those would add well over 10,000 more words to this count.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Yes, that number includes these posts!<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>They wanted an analysis of when you’d choose each language; I pitched a comparison along similar lines to my blog series, looking at the language design choices as a view into software engineering tradeoffs. When the mismatch became clear, I pointed out that “when to choose Rust vs. Swift” is, generally speaking, a roughly two-sentence answer: “Choose Rust for cross-platform, high-performance/low-level code. Choose Swift if you’re writing apps on an Apple platform.” This was not, apparently, obvious to everyone else involved. In the words of the internet: <span style="whitespace: nowrap">¯\_(ツ)_/¯</span><a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoWed, 28 Dec 2016 07:00:00 -0500tag:v4.chriskrycho.com,2016-12-28:/2016/2016-review-2.htmlwritingpodcastingsoftware developmentfamilyproductivityfitness2016-in-review2016 in Review, Part 1 of 6http://v4.chriskrycho.com/2016/2016-review-1.html<p><i class='editorial'>I originally drafted a single, mammoth post reflecting on this whole year—but at more than 6,000 words, that seemed like a bit much. As such, I’ve broken it into a series of posts, to be published daily through the start of the new year. Hopefully they’re a bit more digestible that way!</i></p>
<ul>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-intro.html">Introduction, or: a ridiculous year summarized</a></li>
<li>Part 1: Running headfirst into a wall of pneumonia. (this post)</li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-2.html">Part 2: So. many. words. I had no idea how many words.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-3.html">Part 3: Podcasting: Winning Slowly, New Rustacean, and more!</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-4.html">Part 4: Writing software for Olo and for open source.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-5.html">Part 5: Getting things done in 2016 and beyond.</a></li>
<li><a href="http://v4.chriskrycho.com/2017/2016-review-6.html">Part 6: Plans for 2017!</a></li>
</ul>
<hr />
<p><em>Wait, hold on,</em> you say. <em>Go back. How did you get walking pneumonia?</em> This is a fun story, and it’s a huge part of what made the other parts of the latter half of 2016 go the way they did.</p>
<p>I went for what I expected to be a 15–16 mile long run as part of training for the half-marathon I signed up for this year. The previous week <a href="http://runwith.chriskrycho.com/runs/12/" title="Run summary on runwith.chriskrycho.com">I’d done a 14-mile run</a>, so 15–16 would have been no problem. I was feeling <em>awesome</em> on the run, so decided to extend it to 17. This was right at the edge of what makes good sense for a week-over-week increase in mileage; you generally want to stick with ~10% increases and max out at 20%; but 17 is right at that limit relative to 14. So I turned right to cut through another nearby town instead of left to head directly home when I was at roughly the 11-mile mark.</p>
<p>Then, where I <em>did</em> cut back toward home, I took a wrong turn out of a five-way intersection. (You can see on the north end of the map, in Youngsville, <a href="https://www.strava.com/activities/644619792" title="Run overview on Strava">here</a>). I realized this half a mile on, but figured there would be a spot to cut over. There is not. So I got back to where I had taken the wrong turn, filled up my water bottle and hit the bathroom, and made my way home. But at this point, I was already at ~15 miles, and ~4 miles from home. As I got back into our town, I decided: why not just go ahead and extend out to 20 miles?</p>
<p>And the truth is, that extra three quarters of a mile probably didn’t matter a bit. 19.25 vs. 20 miles? Same difference in its effect on my immune system, which is to say: it completely crashed it. A 42% week over week increase in mileage is no joke. The little cold I picked up from my 2-year-old daughter turned into borderline bronchitis. Yay.</p>
<p>What with a busy spring preceding—I had no idea how much busier I would be taking 2 classes and working 30 hours a week than I had been taking 3 classes and working 20 hours a week—I didn’t manage a triathlon. I had contented myself with the thought that I’d likely set another PR in my half marathon, but after weeks of recovery from walking pneumonia, that thought fell apart as well. I lost about a minute per mile in my pace, and my mileage was shot as well. I never got it back—not least because of a writing project which went south on me. I ended up being sick off and on all fall, and I’m only now getting my feet back under me. Sad to say, one of those times I got sick was the week of the half marathon I signed up for, and I’d been getting loud, clear signals from my body on previous runs that I was pushing too hard. So no race <em>at all</em> this year. But better that than pushing and injuring myself.</p>
<p>The year also saw a so-far unreversed weight gain that I find incredibly frustrating. In the first six months of 2016, I gained about ten pounds—despite keeping up the same basic activity level. I attribute this to a combination of factors: metabolic shifts in my late 20s, shifting back to doing almost purely running rather than a mix of running, swimming, and cycling, and the impact of acclimation to a workout load. I’m far from overweight, but I’m also slower and generally a bit flabbier as a result.</p>
<p>Here’s hoping 2017 is <em>much</em> better in all these regards! I plan to do a sprint-length triathlon and a full marathon. And I hope to lose those ten pounds again and get back to that healthier overall weight. That combo seems like the thing to do the year I turn thirty and graduate seminary.</p>
Chris KrychoTue, 27 Dec 2016 17:00:00 -0500tag:v4.chriskrycho.com,2016-12-27:/2016/2016-review-1.htmlwritingpodcastingsoftware developmentfamilyproductivityfitness2016-in-review2016 in Review, Introductionhttp://v4.chriskrycho.com/2016/2016-review-intro.html<p><i class='editorial'>I originally drafted a single, mammoth post reflecting on this whole year—but at more than 6,000 words, that seemed like a bit much. As such, I’ve broken it into a series of posts, to be published daily through the start of the new year. Hopefully they’re a bit more digestible that way! This first day, you’re getting two posts; the rest of the year, one (at least: in this series!).</i></p>
<ul>
<li>Introduction, or: a ridiculous year summarized (this post)</li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-1.html">Part 1: Running headfirst into a wall of pneumonia.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-2.html">Part 2: So. many. words. I had no idea how many words.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-3.html">Part 3: Podcasting: Winning Slowly, New Rustacean, and more!</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-4.html">Part 4: Writing software for Olo and for open source.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/2016-review-5.html">Part 5: Getting things done in 2016 and beyond.</a></li>
<li><a href="http://v4.chriskrycho.com/2017/2016-review-6.html">Part 6: Plans for 2017!</a></li>
</ul>
<hr />
<p>2016 was a long, difficult, strange, sometimes wonderful and sometimes dreadful year for me. It was one of the most professionally and scholastically enjoyable and rewarding years of my life, and also one of the most exhausting. As I often do at years-end, I am taking stock publicly of what went well, what went poorly, and what I might do different in a variety of categories—here, mostly in terms of my public-facing endeavors. This year’s summing-up post will also (for, I think, the first time) include some numbers! But first, a few comments on the big picture.</p>
<p>At the end of 2015, I <a href="http://v4.chriskrycho.com/2015/thoughts-on-2015-and-2016.html">offered a similar set of reflections</a>. At the end of it, I laid out some plans for 2016:</p>
<blockquote>
<p>I am going to set a single goal in each of five major categories in my life:</p>
<ul>
<li><strong>spiritual:</strong> everything in my walk with God, including my own personal devotions, my involvement in the life of the church, and my “ministry” actions in general</li>
<li><strong>family:</strong> both quantity and quality time spent with my wife and my quickly-growing-up little girls</li>
<li><strong>personal:</strong> podcasting, blogging, and writing for <a href="http://mereorthodoxy.com/author/chris-krycho/">other outlets</a></li>
<li><strong>professional:</strong> working in my new job and as a consultant, and carrying on toward the conclusion of my M. Div.</li>
<li><strong>health/fitness:</strong> continuing to stay healthy, including eating well and continuing to stay fit by running and doing triathlon work</li>
</ul>
</blockquote>
<p>Early in the year, I made the habit of writing these out formally on a day-by-day basis—and I did this off and on. If you were to look at my little (Moleskine-branded and delightful-to-me) daily planner, you’d see streaks of weeks where I noted specific tasks and whether I hit them or not, punctuated by weeks and months where I did nothing of the sort. I have always found it difficult to stick with these kinds of things, in part because I usually have a pretty good idea what I need to do on any given day without writing it down somewhere. (I use <a href="https://www.omnigroup.com/omnifocus/" title="OmniFocus">other tools</a> for tracking mid- and long-term deadlines for school.) In July, I started mashing this idea up with <a href="http://bulletjournal.com" title="Bullet Journal site">bullet journaling</a>, and I found that I (a) really like the system and (b) also didn’t stick with it consistently. A lot of that came down to the fact that I got thrown off—horribly—by getting a mild-but-still-utterly-debilitating case of walking pneumonia in July. (On which, more in a moment.)</p>
<p>So much for last year’s ideas about <em>how</em> I was going to hit those goals. How did I actually do at addressing them? The answer is: <em>okay</em>. 2016 was not an amazing year. It was not a terrible year. But it had as many downs as ups.</p>
<p>My own walk with God remains <em>steady</em>. Nothing amazing to report here, but I’m more than okay with that. I will perhaps say more on this in another post, but the older I get the more convinced I am that emotional highs are a trap. Sentiment and true religion are <em>not</em> the same thing; and Scripture calls us to <em>faithfulness</em>, not <em>spiritual feelings</em>. As such, in a year with this many bumps, I am glad to say that I had no horrible falls, and I read my Bible nearly every day and prayed every single day.</p>
<p>Our family learned some Bible verses, and started working on the Heidelberg Catechism. We shared the gospel with people as we were able, and met faithfully with our church. We were not extraordinary, and we were far from flawless, but I think we did <em>well</em>. I hope and pray in God’s grace we are able to continue in faithfully doing well in the years to come. Certainly if there is one thing I hope to do more of in 2017 it is spend time with my girls. I am not a huge “kid person,” but these years are precious and go by quickly; far better to spend more time with them and have a podcast episode or a writing project go out later (or not at all) than to miss these little years.</p>
Chris KrychoTue, 27 Dec 2016 16:00:00 -0500tag:v4.chriskrycho.com,2016-12-27:/2016/2016-review-intro.htmlwritingpodcastingsoftware developmentfamilyproductivityfitness2016-in-reviewThe Itchhttp://v4.chriskrycho.com/2016/the-itch.html<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—over and over again—<em>familiar</em>. Strange to say, but it’s true.</p>
<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>—i.e., <em>mappable</em> types. I’ve 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’m not alone in that. There’s 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’t</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’s something there.</p>
<p>And reading this post on functors, it struck me what that “something” is: object types are, in principle, functors. Maybe it doesn’t make sense to have a single <code>map</code> implementation for every <code>Object</code> instance out there. But they’re perfectly mappable. I didn’t have a word for this before tonight, but now I do. Over and over again, this is my experience with functional programming.</p>
<p>There’s this familiar feeling of frustration I’m slowly coming to recognize—a mental sensation which is a little like the intellectual equivalent of an itch in a spot you can’t quite reach. You’re reaching for an abstraction to express an idea, but you don’t even know that there <em>is</em> an abstraction for it. You want to map over objects, and you don’t know why that seems so reasonable, but it does. And then someone explains functors to you. It scratches the itch.</p>
<p>Another example. Since I started programming eight and a half years ago, I’ve 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>
<p>Then I read <a href="https://gumroad.com/l/maybe-haskell/"><em>Maybe Haskell</em></a>, a book I’ve mentioned often on this blog because it was so revelatory for me. This is what I had been reaching for all those years—and 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—finally.</p>
<p>I can still feel that itch. It’s shifted a little, but it’s still there: reaching for higher abstractions to let me tell the machine more clearly what I intend. Half a dozen times this year, I’ve realized: <em>Here</em> is where dependent types would be useful. They’re far beyond me, but close enough now I can see. I’m sure a year from now, I’ll have find some tools to scratch <em>these</em> itches, only to discover a few more.</p>
Chris KrychoMon, 19 Dec 2016 21:45:00 -0500tag:v4.chriskrycho.com,2016-12-19:/2016/the-itch.htmlsoftware developmentfunctional programmingRustJavaScriptkeyof and Mapped Types In TypeScript 2.1http://v4.chriskrycho.com/2016/keyof-and-mapped-types-in-typescript-21.html<p>In the last few months, I’ve 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—basically, a form of <a href="https://en.wikipedia.org/wiki/Gradual_typing">gradual typing</a> for JS.</p>
<p>Although TypeScript’s 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’s 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’ve 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’s now a <em>very</em> compelling language in its own right—not to mention a great tool for writing better JavaScript. So I thought I’d 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>
<hr />
<p><i>Some readers may note that what I’m 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>
<hr />
<section id="plain-old-javascript" class="level3">
<h3>Plain old JavaScript</h3>
<p>Let’s 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>
<pre class="javascript"><code>function nextState(state) {
switch(state) {
case &#39;Pending&#39;: return &#39;Started&#39;;
case &#39;Started&#39;: return &#39;Completed&#39;;
case &#39;Completed&#39;: return &#39;Completed&#39;;
default: throw new Error(`Bad state: ${state}`);
}
}</code></pre>
<p>This will work, and it’ll even throw an error if you hand it the wrong thing. But you’ll find out at runtime if you accidentally typed <code>nextState('Pednign')</code> instead of <code>nextState('Pending')</code>—something I’ve done more than once in the past. You’d have a similar problem if you’d accidentally written <code>case 'Strated'</code> instead of <code>case 'Started'</code>.</p>
<p>There are many contexts like this one in JavaScript—perhaps 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’s 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>
<pre class="javascript"><code>const STATE = {
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
};</code></pre>
<p>Once you’ve 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>
<pre class="javascript"><code>function nextState(state) {
switch(state) {
case STATE.Pending: return STATE.Started;
case STATE.Started: return STATE.Completed;
case STATE.Completed: return STATE.Completed;
default: throw new Error(`Bad state: ${state}`);
}
}</code></pre>
<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’ll 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—especially if you’re 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’t pass our test suite!).</p>
<p>This is about as good a setup as you can get in plain-old JavaScript. As long as you’re 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’re back to blowing up at runtime. Hopefully your test suite catches that.</p>
</section>
<section id="typescript-to-the-rescue" class="level3">
<h3>TypeScript to the rescue</h3>
<p>TypeScript gives us the ability to <em>guarantee</em> that the contract is met (that we’re 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>
<p>Let’s 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’ll 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>
<pre class="typescript"><code>// TODO: figure out how to define `State`
function nextState(state: State): State {
// the same body...
}</code></pre>
<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>
<pre class="typescript"><code>type State = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;</code></pre>
<p>Unfortunately, you can’t 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’s actual type-checking, but you don’t get <em>any</em> help with autocompletion. Can we get the benefits of both?</p>
<p>Yes! (This would be a weird blog post if I just got this far and said, “Nope, sucks to be us; go use Elm instead.”)</p>
<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>
<pre class="typescript"><code>const STATE = {
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
};
type StateFromKeys = keyof typeof STATE;</code></pre>
<p>Then you can use that type any place you need to constrain the type of a variable, or a return, or whatever:</p>
<pre class="typescript"><code>const goodState: StateFromKeys = STATE.Pending;
// error: type &#39;&quot;Blah&quot;&#39; is not assignable to type &#39;State&#39;
const badState: StateFromKeys = &#39;Blah&#39;;
interface StateMachine {
(state: StateFromKeys): StateFromKeys;
}
const nextState: StateMachine = (state) =&gt; {
// ...
}</code></pre>
<p>The upside to this is that now you can guarantee that anywhere you’re 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’ll get an actual error—just 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’s a significant step forward beyond what we had even with the best linting rules in pure JavaScript.</p>
</section>
<section id="going-in-circles" class="level3">
<h3>Going in circles</h3>
<p>But wait, we can do more! TypeScript 2.1 <em>also</em> came with a neat ability to define “mapped types,” 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’s interesting to us here is that you can write a type like this:</p>
<pre class="typescript"><code>type StateAsMap = {
[K in keyof typeof STATE]: K
}</code></pre>
<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>
<pre class="typescript"><code>type StateAsMap = {
[K in StateFromKeys]: K
}</code></pre>
<p>We’ve now defined an object type whose <em>key</em> has to be one of the items in the <code>State</code> type.</p>
<p>Now, by itself, this isn’t 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’d 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>…</p>
<pre class="typescript"><code>const STATE: StateAsMap = {
Pending: &#39;Pending&#39;,
Active: &#39;Active&#39;,
Completed: &#39;Completed&#39;,
}
type StateFromKeys = keyof typeof STATE;
type StateAsMap = {
[K in StateFromKeys]: K
}</code></pre>
<p>You end up with multiple compiler errors here, because of the circular references. This approach won’t work. If we take a step back, though, we can work through this (and actually end up someplace better).</p>
</section>
<section id="join-forces" class="level3">
<h3>Join forces!</h3>
<p>First, let’s start by defining the mapping generically. After all, the idea here was to be able to use this concept all over the place—e.g. for <em>any</em> Redux action, not just one specific one. We don’t 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>
<pre class="typescript"><code>type MapKeyAsValue&lt;Key extends string&gt; = {
[K in Key]: K
};</code></pre>
<p>In principle, if we didn’t have to worry about the circular references, we could use that to constrain our definition of the original <code>STATE</code> itself:</p>
<pre class="typescript"><code>const STATE: MapKeyAsValue&lt;State&gt; = {
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
};</code></pre>
<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>
<pre class="typescript"><code>// Approach 1, using an object
const STATE = {
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
};
type StateFromKeys = keyof typeof STATE;
type StateObjectKeyToValue = {
[K in StateFromKeys]: K // &lt;- K is just the keys!
};
// Approach 2, using unions
type StateUnion = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;
type StateUnionKeyToValue = {
[K in StateUnion]: K // &lt;- K is also just the keys!
};</code></pre>
<p>Notice that, unlike the <code>StateObjectKeyToValue</code> version, <code>StateUnionKeyToValue</code> doesn’t 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>
<pre class="typescript"><code>type StateUnion = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;
type StateUnionKeyToValue = {
[K in StateUnion]: K
};
const STATE: StateUnionKeyToValue = {
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
};</code></pre>
<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’s variants. Second, we know that the key and value are the same, and that they map to the union’s 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>
<p>Now we can make this generic, so it works for types besides just this one set of states—so that it’ll 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 “union,” where we had <code>StateUnion</code> before.</p>
<pre class="typescript"><code>type UnionKeyToValue&lt;U extends string&gt; = {
[K in U]: K
};</code></pre>
<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>
<pre class="typescript"><code>type State = &#39;Pending&#39; | &#39;Started&#39; | &#39;Completed&#39;;
// Use `State` as the type parameter to `UnionKeyToValue`.
const STATE: UnionKeyToValue&lt;State&gt; = {
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
}</code></pre>
<p>If any of those don’t have <em>exactly</em> the same value as the key name, you’ll 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>
<pre class="typescript"><code>const BAD_STATE: UnionKeyToValue&lt;State&gt; = {
Pending: &#39;pending&#39;, // look ma, no capitals
Started: &#39;Strated&#39;, // St-rated = whuh?
Completed: &#39;Complete&#39;, // so tense
};</code></pre>
<p>You’ll see a compiler error that looks something like this:</p>
<blockquote>
<div class="line-block">[ts]<br />
Type ‘{ Pending: “pending”; Started: “Strated”; Completed: “Complete” }’ is not assignable to type ‘UnionKeyToValue<State>’.<br />
Types of property ‘Pending’ are incompatible.<br />
Type ‘“pending”’ is not assignable to type ‘“Pending”’.</div>
</blockquote>
<p>Since the key and the name don’t match, the compiler tells us we didn’t keep the constraint we defined on what these types should look like. Similarly, if you forget an item from the union, you’ll get an error. If you add an item that isn’t in the original union, you’ll 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’t 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>
<p>And the TypeScript language service—which you can use from a <em>lot</em> of editors, including VS Code, Atom, Sublime Text, and the JetBrains IDEs—will 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>
<figure>
<video autoplay=autoplay muted=muted playsinline=playsinline loop=loop>
<source type='video/mp4' src='https://f001.backblazeb2.com/file/chriskrycho-com/images/completion.mp4'>
</video>
<figcaption>
TypeScript live code completion of the mapped type
</figcaption>
</figure>
<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—errors prevented, and speed of writing the code in the first place increased as well.</p>
<p>Yes, it’s 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>
<figure>
<video autoplay=autoplay muted=muted playsinline=playsinline loop=loop>
<source type='video/mp4' src='https://f001.backblazeb2.com/file/chriskrycho-com/images/change-union.mp4'>
</video>
<figcaption>
Updating a union
</figcaption>
</figure>
<p>So it’s a lot more work than it would be in, say, Elm. But it’s also a lot more guarantees than I’d get in plain-old-JavaScript, or even TypeScript two months ago.</p>
<p>I’ll call that a win.</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>it’s no surprise that Microsoft’s developer tooling is stronger than Facebook’s<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>along with all the other ML-descended languages I’ve played with, including Haskell, F<sup>♯</sup>, PureScript, and Elm.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<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>
<pre class="javascript"><code>const STATE = Object.freeze({
Pending: &#39;Pending&#39;,
Started: &#39;Started&#39;,
Completed: &#39;Completed&#39;,
})</code></pre>
<p>Both convention and linters make it unlikely you’ll modify something like this directly—but impossible is better than unlikely.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
<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>—but the feature is entirely undocumented.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li>
<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">↩</a></p></li>
<li id="fn6" role="doc-endnote"><p>For namespacing in a more general sense, you should use… <a href="http://www.typescriptlang.org/docs/handbook/namespaces.html">namespaces</a>.<a href="#fnref6" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn7" role="doc-endnote"><p>It would be great if we could get these benefits without the duplication—maybe someday we’ll have better support in JS or TS natively.<a href="#fnref7" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 17 Dec 2016 23:25:00 -0500tag:v4.chriskrycho.com,2016-12-17:/2016/keyof-and-mapped-types-in-typescript-21.htmljavascripttypescriptsoftware developmentprogramming languagesRust development using VS Code on OS X, debugging includedhttp://v4.chriskrycho.com/2016/rust-development-using-vs-code-on-os-x-debugging-included.html<p><a href="https://medium.com/@royalstream/rust-development-using-vs-code-on-os-x-debugging-included-bc10c9863777#.wgjbgie5a">Super handy guide for getting a debugging/IDE environment set up for Rust.</a></p>
Chris KrychoFri, 18 Nov 2016 20:48:00 -0500tag:v4.chriskrycho.com,2016-11-18:/2016/rust-development-using-vs-code-on-os-x-debugging-included.htmlsoftware developmentrustlinksUsing Rust for ‘Scripting’http://v4.chriskrycho.com/2016/using-rust-for-scripting.html<p><i class=editorial><strong>Edit</strong>: fixed some typos, cleaned up implementation a bit based on feedback around the internet.</i></p>
<p><i class=editorial>A lightly edited version of this post was syndicated in <a href="https://hackerbits.com/chris-krycho-using-rust-for-scripting/">Hacker Bits, Issue 13</a>.</i></p>
<hr />
<section id="i.-using-rust-instead-of-python" class="level2">
<h2>I. Using Rust Instead of Python</h2>
<p>A friend asked me today about writing a little script to do a simple conversion of the names of some files in a nested set of directories. Everything with one file extension needed to get another file extension. After asking if it was the kind of thing where he had time to and/or wanted to learn how to do it himself (always important when someone has expressed that interest more generally), I said, “Why don’t I do this in Rust?”</p>
<p>Now, given the description, you might think, <i class=thought>Wouldn’t it make more sense to do that in Python or Perl or even just a shell script?</i> And the answer would be: it depends—on what the target operating system is, for example, and what the person’s current setup is. I knew, for example, that my friend is running Windows, which means he doesn’t have Python or Perl installed. I’m not a huge fan of either batch scripts or PowerShell (and I don’t know either of them all that well, either).</p>
<p>I could have asked him to install Python. But, on reflection, I thought: <i class=thought>Why would I do that? I can write this in Rust.</i></p>
<p>Writing it in Rust means I can compile it and hand it to him, and he can run it. And that’s it. As wonderful as they are, the fact that languages like Python, Perl, Ruby, JavaScript, etc. require having the runtime bundled up with them makes just shipping a tool a lot harder—<em>especially</em> on systems which aren’t a Unix derivative and don’t have them installed by default. (Yes, I know that <em>mostly</em> means Windows, but it doesn’t <em>solely</em> mean Windows. And, more importantly: the vast majority of the desktop-type computers in the world <em>still run Windows</em>. So that’s a big reason all by itself.)</p>
<p>So there’s the justification for shipping a compiled binary. Why Rust specifically? Well, because I’m a fanboy. (But I’m a fanboy because Rust often gives you roughly the feel of using a high-level language like Python, but lets you ship standalone binaries. The same is true of a variety of other languages, too, like Haskell; but Rust is the one I know and like right now.)</p>
<p><i class=editorial><strong>Edit the second:</strong> this is getting a lot of views from Hacker News, and it’s worth note: I’m not actually advocating that everyone stop using shell scripts for this kind of thing. I’m simply noting that it’s <em>possible</em> (and sometimes even <em>nice</em>) to be able to do this kind of thing in Rust, cross-compile it, and just ship it. And hey, types are nice when you’re trying to do more sophisticated things than I’m doing here! Also, for those worried about running untrusted binaries: I handed my friend the code, and would happily teach him how to build it.</i></p>
</section>
<section id="ii.-building-a-simple-script" class="level2">
<h2>II. Building a Simple “Script”</h2>
<p>Building a “script”-style tool in Rust is pretty easy, gladly. I’ll walk through exactly what I did to create this “script”-like tool for my friend. My goal here was to rename every file in a directory from <code>*.cha</code> to <code>*.txt</code>.</p>
<ol type="1">
<li><p><a href="https://www.rust-lang.org/en-US/downloads.html">Install Rust.</a></p></li>
<li><p>Create a new binary:</p>
<pre class="sh"><code>cargo new --bin rename-it</code></pre></li>
<li><p>Add the dependencies to the Cargo.toml file. I used the <a href="https://doc.rust-lang.org/glob/glob/index.html">glob</a> crate for finding all the <code>.cha</code> files and the <a href="https://clap.rs">clap</a> crate for argument parsing.</p>
<pre class="toml"><code>[package]
name = &quot;rename-it&quot;
version = &quot;0.1.0&quot;
authors = [&quot;Chris Krycho &lt;chris@chriskrycho.com&gt;&quot;]
[dependencies]
clap = &quot;2.15.0&quot;
glob = &quot;0.2&quot;</code></pre></li>
<li><p>Add the actual implementation to the <code>main.rs</code> file (iterating till you get it the way you want, of course).</p>
<pre class="rust"><code>extern crate clap;
extern crate glob;
use glob::glob;
use std::fs;
use clap::{Arg, App, AppSettings};
fn main() {
let path_arg_name = &quot;path&quot;;
let args = App::new(&quot;cha-to-txt&quot;)
.about(&quot;Rename .cha to .txt&quot;)
.setting(AppSettings::ArgRequiredElseHelp)
.arg(Arg::with_name(path_arg_name)
.help(&quot;path to the top directory with .cha files&quot;))
.get_matches();
let path = args.value_of(path_arg_name)
.expect(&quot;You didn&#39;t supply a path&quot;);
let search = String::from(path) + &quot;/**/*.cha&quot;;
let paths = glob(&amp;search)
.expect(&quot;Could not find paths in glob&quot;)
.map(|p| p.expect(&quot;Bad individual path in glob&quot;));
for path in paths {
match fs::rename(&amp;path, &amp;path.with_extension(&quot;txt&quot;)) {
Ok(_) =&gt; (),
Err(reason) =&gt; panic!(&quot;{}&quot;, reason),
};
}
}</code></pre></li>
<li><p>Compile it.</p>
<pre class="sh"><code>cargo build --release</code></pre></li>
<li><p>Copy the executable to hand to a friend.</p></li>
</ol>
<p>In my case, I actually added in the step of <em>recompiling</em> it on Windows after doing all the development on macOS. This is one of the real pieces of magic with Rust: you can <em>easily</em> write cross-platform code. The combination of Cargo and native-compiled-code makes it super easy to write this kind of thing—and, honestly, easier to do so in a cross-platform way than it would be with a traditional scripting language.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>But what’s really delightful is that we can do better. I don’t even need to install Rust on Windows to compile a Rust binary for Windows.</p>
</section>
<section id="iii.-cross-compiling-to-windows-from-macos" class="level2">
<h2>III. Cross-Compiling to Windows from macOS</h2>
<p>Once again, let’s do this step by step. Three notes: First, I got pretty much everything other than the first and last steps here from WindowsBunny on the <a href="https://botbot.me/mozilla/rust/">#rust</a> <abbr>IRC</abbr> channel. (If you’ve never hopped into #rust, you should: it’s amazing.) Second, you’ll need a Windows installation to make this work, as you’ll need some libraries. (That’s a pain, but it’s a one-time pain.) Third, this is the setup for doing in on macOS Sierra; steps may look a little different on an earlier version of macOS or on Linux.</p>
<ol type="1">
<li><p>Install the Windows compilation target with <code>rustup</code>.</p>
<pre class="sh"><code>rustup target add x86_64-pc-windows-msvc</code></pre></li>
<li><p>Install the required linker (<a href="http://lld.llvm.org"><code>lld</code></a>) by way of installing the LLVM toolchain.</p>
<pre class="sh"><code>brew install llvm</code></pre></li>
<li><p>Create a symlink somewhere on your <code>PATH</code> to the newly installed linker, specifically with the name <code>link.exe</code>. I have <code>~/bin</code> on my <code>PATH</code> for just this kind of thing, so I can do that like so:</p>
<pre class="sh"><code>ln -s /usr/local/opt/llvm/bin/lld-link ~/bin/link.exe</code></pre>
<p>(We have to do this because the Rust compiler <a href="https://github.com/rust-lang/rust/blob/master/src/librustc_trans/back/msvc/mod.rs#L300">specifically goes looking for <code>link.exe</code> on non-Windows targets</a>.)</p></li>
<li><p>Copy the target files for the Windows build to link against. Those are in these directories, where <code>&lt;something&gt;</code> will be a number like <code>10586.0</code> or similar (you should pick the highest one if there is more than one):</p>
<ul>
<li><code>C:\Program Files\Windows Kits\10\Lib\10.0.&lt;something&gt;\ucrt\x64</code></li>
<li><code>C:\Program Files\Windows Kits\10\Lib\10.0.&lt;something&gt;\um\x64</code></li>
<li><code>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64</code></li>
</ul>
<p>Note that if you don’t already have <abbr>MSVC</abbr> installed, you’ll need to install it. If you don’t have Visual Studio installed on a Windows machine <em>at all</em>, you can do that by using the links <a href="http://landinghub.visualstudio.com/visual-cpp-build-tools">here</a>. Otherwise, on Windows, go to <strong>Add/Remove Programs</strong> and opting to Modify the Visual Studio installation. There, you can choose to add the C++ tools to the installation.</p>
<p>Note also that if you’re building for 32-bit Windows you’ll want to grab <em>those</em> libraries instead of the 64-bit libraries.</p></li>
<li><p>Set the <code>LIB</code> environment variable to include those paths and build the program. Let’s say you put them in something like <code>/Users/chris/lib/windows</code> (which is where I put mine). Your Cargo invocation will look like this:</p>
<pre class="sh"><code>env LIB=&quot;/Users/chris/lib/windows/ucrt/x64/;/Users/chris/lib/windows/um/x64/;/Users/chris/lib/windows/VC_lib/amd64/&quot; \
cargo build --release --target=x86_64-pc-windows-msvc</code></pre>
<p>Note that the final <code>/</code> on each path and the enclosing quotation marks are all important!</p></li>
<li><p>Copy the binary to hand to a friend, without ever having had to leave your Mac.</p></li>
</ol>
<p>To be sure, there was a little extra work involved in getting cross-compilation set up. (This is the kind of thing I’d love to see further automated with <code>rustup</code> in 2017!) But what we have at the end is pretty magical. Now we can just compile cross-platform code and hand it to our friends.</p>
<p>Given that, I expect not to be using Python for these kinds of tools much going forward.</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Again: you can do similar with Haskell or OCaml or a number of other languages. And those are great options; they are in <em>some</em> ways easier than Rust—but Cargo is really magical for this.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoMon, 14 Nov 2016 22:00:00 -0500tag:v4.chriskrycho.com,2016-11-14:/2016/using-rust-for-scripting.htmlrustsoftware developmentprogramming languagesWhat is Functional Programming?http://v4.chriskrycho.com/2016/what-is-functional-programming.html<p><i class='editorial'>The following is a script I wrote for a tech talk I gave on functional programming. The recording isn’t (and won’t be) publicly available; but a script is often easier to reference anyway!</i></p>
<p><i class='editorial'><strong>Edit:</strong> updated with corrected performance characterstics.</i></p>
<hr />
<p>Hello, everyone. Today, we are going to talk about functional programming—asking what it is, and why we should care.</p>
<section id="clearing-the-table-functional-programmings-reputation" class="level2">
<h2>Clearing the Table: Functional Programming’s Reputation</h2>
<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>
<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’t 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’t require you to know what an <em>applicative functor</em> is to be able to use it. (And, gladly, there’s a lot of increasingly-solid teaching material out there about functional programming which <em>doesn’t</em> lean on math concepts.)</p>
<p>On the other side, functional programming does give us some real and serious benefits, and that’s what I’m going to spend the first third or so of this talk looking at. But of course, it’s still just a tool, and even though it is a very helpful and very powerful tool, it can’t keep us from writing bugs. Still, every tool we can add to our belt for writing correct software is a win.</p>
<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>
<ul>
<li>Functor</li>
<li>Applicative</li>
<li>Monoid</li>
<li>Monad</li>
</ul>
<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—what are the <abbr>SOLID</abbr> principles?</p>
<ul>
<li>Single reponsibility</li>
<li>Open/closed</li>
<li>Liskov substitution</li>
<li>Interface segregation</li>
<li>Dependency inversion</li>
</ul>
<p>You may not remember what it felt like the first time you encountered <abbr>SOLID</abbr>, but suffice it to say: “Liskov substitution principle” isn’t any more intuitive or obvious than “Monad”. You’re just familiar with one of them. The same is true of “applicative” and “Visitor pattern”. 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>
<p>So, with that out of the way, what <em>is</em> functional programming?</p>
</section>
<section id="what-is-functional-programming" class="level2">
<h2>What is functional programming?</h2>
<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’ll define all of those terms in a moment, but first…</p>
<section id="why-do-we-care" class="level3">
<h3>Why do we care?</h3>
<p>We care, frankly, because <em>we’re not that smart</em>. Let’s think about some of the kinds of things we’re 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’m sure a missed some non-trivial pieces, too. And if all of that is <em>stateful</em>, that’s a lot of state to hold in your head.</p>
<p>Let me be a bit provocative for a moment. Imagine you were reading a JavaScript module and it looked like this:</p>
<pre class="js"><code>var foo = 12;
var bar = &#39;blah&#39;;
var quux = { waffles: &#39;always&#39; };
export function doSomething() {
foo = 42;
}
export function getSomething() {
bar = quux;
quux.waffles = &#39;never&#39;;
return bar;
}</code></pre>
<p>Everyone watching would presumably say, “No that’s bad, don’t do that!” Why? Because there is <em>global state</em> being changed by those functions, and there’s nothing about the functions which tells you what’s 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>
<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’t do this anymore.</em></p>
<p>But really, what’s different about this?</p>
<pre class="js"><code>class AThing {
constructor() {
this.foo = 12;
this.bar = &#39;blah&#39;;
this.quux = { waffles: &#39;always&#39; };
}
doSomething() {
this.foo = 42;
}
getSomething() {
this.bar = this.quux;
this.quux.waffles = &#39;never&#39;;
return this.bar;
}
}</code></pre>
<p>We have some “internal” 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’s 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—understanding the state involved—it’s the same. It’s global, mutable state. Now it’s not global like attaching something to the <code>window</code> object in JavaScript, and that’s good, but still: at the module or class level, it’s just global mutable state, with no guarantees about how anything works. And this is normal—endemic, even—in object-oriented code. We encapsulate our state, but we have <em>tons</em> of state, it’s all mutable, and as far as any given class method call is concerned, it’s all global to that class.</p>
<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’s 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>
<p>When you call a method, you have no idea what it will do. JavaScript, TypeScript, C<sup>♯</sup>, it doesn’t matter. You have literally no idea. And that makes things <em>hard</em>.</p>
<ul>
<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>
<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’re trying to do.</li>
</ul>
<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’t break something seemingly unrelated, hard to see how the pieces fit together—hard, in a phrase you’ll often hear from functional programming fans, hard to reason about.</p>
<p>So, how do we solve these problems? With functional programming!</p>
</section>
<section id="what-is-functional-programming-1" class="level3">
<h3>What <em>is</em> functional programming?</h3>
<p>Functional programming is basically combining four bigs ideas:</p>
<ol type="1">
<li>First class functions</li>
<li>Higher-order functions</li>
<li>Pure functions</li>
<li>Immutable data</li>
</ol>
<p>The combination of these things leads us to a <em>very</em> different style of programming than traditional <abbr>OOP</abbr>. Let’s define them.</p>
<section id="first-class-functions-and-higher-order-functions" class="level4">
<h4>First class functions and higher-order functions</h4>
<p>We’ll start by looking at the things that are probably most familiar to you if you’re a JavaScript developer (even if you haven’t necessarily heard the names): first-class functions and higher-order functions.</p>
<p>When we talk about <em>first class functions,</em> we mean that functions are just data—they’re 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’s 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>
<p>Higher-order functions, in turn, are functions which take other functions as parameters or return them as their values. We’ll see this in detail in a worked example in a few, but for right now, let’s just use a really simple example that will be familiar to anyone who’s done much JavaScript: using <code>map</code>.</p>
<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>
<pre class="js"><code>const initialValues = [1, 2, 3];
const doubledValues = initialValues.map(value =&gt; value * 2);</code></pre>
<p>We did it there with a function explicitly, but we could just as easily extract the function like this:</p>
<pre class="js"><code>const double = value =&gt; value * 2;
const initialValues = [1, 2, 3];
const doubledValues = initialValues.map(double);</code></pre>
<p>This is possible because <em>functions are just data</em>—they’re first-class members of the language—and therefore <em>functions can be arguments or return values</em>—the language supports higher-order functions.</p>
</section>
<section id="pure-functions" class="level4">
<h4>Pure functions</h4>
<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’s a really weird antipattern to use effectful functions with <code>map</code>! Don’t do that! Use <code>forEach</code> if you must have an effect). Here are a few more super simple examples:</p>
<pre class="js"><code>const add = (a, b) =&gt; a + b;
const toString = (number) =&gt; `The value is ${number}`;
const toLength = (list) =&gt; list.length;</code></pre>
<p>Here are some examples of straightforward functions which are <em>not</em> pure:</p>
<pre class="js"><code>const logDataFromEndpoint = (endpoint) =&gt; {
fetch(endpoint).then(response =&gt; {
console.log(response);
});
};
let foo = 42;
const setFoo = (newValue) =&gt; {
foo = newValue;
};
const getFoo = () =&gt; foo;</code></pre>
<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>
<p>And of course, you can’t 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’t to write <em>only</em> pure functions. It’s to write <em>mostly</em> pure functions and to <em>isolate</em> all impure functions.</p>
<p>What this gets us is two things:</p>
<ol type="1">
<li>A much smaller list of things to worry about when we’re looking at a given function.</li>
<li>The ability to <em>compose</em> functions together more easily.</li>
</ol>
<p>We have fewer things to keep in our heads when we look at any given pure function, because we don’t 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’s it. Compare these two things in practice.</p>
<p>Here’s a traditional <abbr>OOP</abbr> approach:</p>
<pre class="js"><code>class Order {
constructor() {
this.subTotal = 0.0;
this.taxRate = 0.01;
}
getTotal() {
return this.subTotal * (1 + this.taxRate);
}
}
const order = new Order();
order.subTotal = 42.00;
const total = order.getTotal();</code></pre>
<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’s a bug in it, we need to make sure we’ve made all the appropriate transformations to the object ahead of time. That’s no big deal here; the <code>total</code> getter is incredibly simple (and in fact, we’d 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’s a bug without first doing some object setup.</p>
<p>Now, here’s a functional approach.</p>
<pre class="js"><code>const order = {
subTotal: 42.0,
taxRate: 0.01
}
const getTotal = (subTotal, taxRate) =&gt; subTotal * (1 + taxRate);
const total = getTotal(order.subTotal, order.taxRate);</code></pre>
<p>Note that the object is <em>just data</em>. It’s 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>
<p>This makes it easily testable, for free. Want to make sure different tax rates get the correct output? Just… pass in a different tax rate. You don’t 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’s no other state to think about, because there’s no state at all here from the perspective of the function: just inputs and outputs.</p>
<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’s attached to an object instance and (b) it’s dependent on other things about that object. You can’t just substitute it in, or freely move it around, when you’re doing a refactor. <em>Maybe</em> you can, but you’d 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’ll always get the same thing back.</p>
<p>This is just like math: if you say, <span class="math inline"><em>x</em> = 5</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’s 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’s true for <span class="math inline"><em>f</em>(<em>x</em>)</span> as well. When we use pure functions, it’s true for programming, too! That makes refactoring much easier.</p>
<p>As we’ll 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>
</section>
<section id="immutable-data" class="level4">
<h4>Immutable data</h4>
<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>
<p>You’re 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’t need to reuse the <em>exact</em> same data because we’re transforming it. However, as we’ll see below, in languages which don’t have native support for immutability, it can impose a performance penalty. Gladly, there are ways to work around this!</p>
<hr />
</section>
</section>
</section>
<section id="a-worked-example" class="level2">
<h2>A Worked Example</h2>
<p>Let’s get down to a real example of these ideas. This is a ‘code kata’ I do every so often. In this particular kata, you get a list of burger orders which looks like this:</p>
<pre class="js"><code>[
{ condiments: [&#39;ketchup&#39;, &#39;mustard&#39;, &#39;pickles&#39;] },
{ condiments: [&#39;tomatoes&#39;] },
{ condiments: [&#39;mustard&#39;, &#39;ketchup&#39;] },
// etc...
]</code></pre>
<p>You’re 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>
<pre class="js"><code>const getBurgers = () =&gt;
fetch(&#39;http://files.example.com/burgers.json&#39;)
.then(request =&gt; request.json());</code></pre>
<p>And we’ll print our results (which will always end up in the same format) like this:</p>
<pre class="js"><code>const descAndCountToOutput = descAndCount =&gt; `${descAndCount[0]}: ${descAndCount[1]}`;</code></pre>
<p>This is actually a perfect case to demonstrate how functional programming ideas can help us solve a problem.</p>
<section id="imperative" class="level3">
<h3>Imperative</h3>
<p>First, let’s look at what I think is a <em>relatively</em> reasonable imperative approach. Our basic strategy will be:</p>
<ol type="1">
<li>Convert condiments to descriptions.
<ol type="1">
<li>Convert the objects to just their lists of condiments.</li>
<li>Sort those strings.</li>
<li>Turn them into descriptions by joining them with a comma.</li>
</ol></li>
<li>Build up a mapping from description to count.</li>
<li>Sort that by count.</li>
<li>Get the top 10.</li>
<li>Print out the results.</li>
</ol>
<pre class="js"><code>getBurgers().then(burgers =&gt; {
let totals = {};
// 2. Build up a mapping from description to count.
for (let burger of burgers) {
// 1. Convert condiments to descriptions.
// 1.1. Convert the objects to just their lists of condiments.
const condiments = burger.condiments;
// 1.2. Sort those strings.
condiments.sort();
// 1.3. Turn them into descriptions by joining them with a comma.
const description = condiments.join(&#39;, &#39;);
// 2. Build up a mapping from description to count.
const previousCount = totals[description];
totals[description] = previousCount ? previousCount + 1 : 1;
}
// 3. Sort that by count.
const sortableCondiments = Object.entries(totals);
sortableCondiments.sort((a, b) =&gt; b[1] - a[1]);
// 4. Get the top 10.
const topTen = sortableCondiments.slice(0, 10);
// 5. Print out the results.
for (let descAndCount of topTen) {
console.log(descAndCountToOutput(descAndCount));
}
});</code></pre>
<p>That’s pretty well-factored. But it’s pretty wrapped up on the specific details of this problem, and there’s basically nothing here I could reuse. It’s also relatively hard to test. There aren’t 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’d 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>
<p>And this is where functional programming really does give us a better way.</p>
</section>
<section id="functional" class="level3">
<h3>Functional</h3>
<p>Instead of thinking about the specific details of <em>how</em> to get from A to B, let’s 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>
<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>
<ol type="1">
<li>Convert condiments to descriptions.
<ol type="1">
<li>Convert the objects to just their lists of condiments.</li>
<li>Sort those strings.</li>
<li>Turn them into descriptions by joining them with a comma.</li>
</ol></li>
<li>Build up a mapping from description to count.</li>
<li>Sort that by count.</li>
<li>Get the top 10.</li>
<li>Print out the results.</li>
</ol>
<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’s see what that might look like. First, what are our transformations?</p>
<p>The step 1 transformations are all quite straightforward:</p>
<pre class="js"><code>// 1. Convert condiments to descriptions.
// 1.1. Convert the objects to just their lists of condiments.
const toCondiments = burger =&gt; burger.condiments ? burger.condiments : [];
// 1.2. Sort those strings.
const toSortedCondiments = condiments =&gt; condiments.concat().sort();
// 1.3. Turn them into descriptions by joining them with a comma.
const toDescriptions = condiments =&gt; condiments.join(&#39;, &#39;);</code></pre>
<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>
<pre class="js"><code>// 2. Build up a mapping from description to count.
const toTotals = (totals, description) =&gt; {
const previousCount = totals[description];
const count = previousCount ? previousCount + 1 : 1;
totals[description] = count;
return totals;
};
// 3. Sort that by count.
const byCount = (a, b) =&gt; b[1] - a[1];</code></pre>
<p>We’ll see how to get just 10 in a moment; for now, let’s also wrap up the output:</p>
<pre class="js"><code>// 5. Print it out
const output = value =&gt; { console.log(value); };</code></pre>
<p>These are our base building blocks, and we’ll re-use them in each of the approaches I cover below. Note that we’ve now taken those same basic steps from our imperative approach and turned them into standalone, testable functions. They’re small and single-purpose, which always helps. But more importantly, (with two exceptions we’ll talk about in a minute) all of those transformations are <em>pure functions</em>, we know that we’ll 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>
<pre class="js"><code>describe(&#39;toCondiments&#39;, () =&gt; {
it(&#39;returns an empty list when there is no `condiments`&#39;, () =&gt; {
toCondiments({}).should.deepEqual([]);
});
it(&#39;returns the list of condiments when it is passed&#39;, () =&gt; {
const condiments = [&#39;ketchup&#39;, &#39;mustard&#39;];
toCondiments({ condiments }).should.deepEqual(condiments);
});
})</code></pre>
<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’t depend on anything else. It doesn’t have <em>any knowledge</em> of how we’re going to use it. It doesn’t know that it’s 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’ll hand you back the array attached to that property.</p>
<p>The result is that, with all of these functions, we don’t 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, “That’s 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?” 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’s best practice anyway! We’re just codifying it. We’ll see what that looks like in practice in just a minute.</p>
<p>Now, while we’re 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’s <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>
<pre class="js"><code>const toSortedCondiments = condiments =&gt; condiments.concat().sort();</code></pre>
<p>Similarly, we <em>could</em> define the <code>toTotals</code> to return a new object every time, like this:</p>
<pre class="js"><code>const toTotals = (totals, description) =&gt; {
const previousCount = totals[description];
const count = previousCount ? previousCount + 1 : 1;
const update = { [description]: count };
return Object.assign({}, totals, update);
};</code></pre>
<p>Unfortunately, given the amount of data we’re dealing with, that’s prohibitively expensive. We end up spending a <em>lot</em> of time allocating objects and garbage-collecting them. As a result, it’s 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—returning copies every time—takes ~53s. And if you profile it, almost all of that time is spent in <code>assign</code> (52.95s).</p>
<p>This takes us to an important point, though: it’s actually not a particularly big deal to have this particular data changed in place, because we’re 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—precisely because it’s perfectly safe to do so, because we’re the only ones who have access to this data. We’re 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>
<p>In other words, when we’re talking about a <em>pure function</em>, we don’t really care about internal mutability (though of course, that can bite us if we’re not careful). We’re 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’t have to care how we got that result.</p>
<p>Now let’s see how we use these functions.</p>
<section id="pure-javascript" class="level4">
<h4>Pure JavaScript</h4>
<p>First, here’s a pure-JavaScript approach, but a more functional one instead of an imperative one:</p>
<pre class="js"><code>getBurgers().then(burgers =&gt; {
const descriptionToCount = burgers
.map(toCondiments)
.map(toSortedCondiments)
.map(toDescriptions)
.reduce(toTotals, {})
const entries = Object.entries(descriptionToCount);
[...entries]
.sort(byCount)
.slice(0, 10) // 4. Get the top 10.
.map(descAndCountToOutput)
.forEach(output);
});</code></pre>
<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>
<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>
<p>When we’re 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’re stuck if the object type doesn’t have the method we need. We’re kind of trying to mash together the imperative and functional styles, and it’s leaving us in a little bit of a weird spot.</p>
<p>There’s another issue here, though, and it’s the way that using the method-style calling convention obscures something important. When we call <em>most</em> of those methods, we’re doing something quite different from what most <em>methods</em> do. A method normally is an operation on an object. These methods—most of them—are operations that return <em>new</em> objects. So it’s nice from a syntax perspective, but if we’re not <em>already</em> familiar with the behavior of a given method, it won’t be clear at all that we’re actually generating a bunch of totally new data by calling those methods.</p>
<p>And… 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>
</section>
<section id="lodash" class="level4">
<h4>Lodash</h4>
<p>The first step away from this problem is to use a tool like <a href="https://lodash.com">Lodash</a>.</p>
<pre class="js"><code>// More functional, with _:
// We tweak how a few of these work slightly to play nicely.
const _toDescriptions = condiments =&gt; _.join(condiments, &#39;, &#39;);
const _byCount = _.property(1);
getBurgers().then(burgers =&gt; {
const condiments = _.map(burgers, toCondiments);
const sortedCondiments = _.map(condiments, toSortedCondiments);
const descriptions = _.map(sortedCondiments, _toDescriptions);
const totals = _.reduce(descriptions, toTotals, {});
const totalPairs = _.toPairs(totals);
const sortedPairs = _.sortBy(totalPairs, _byCount);
const sortedPairsDescending = _.reverse(sortedPairs);
const topTen = _.take(sortedPairsDescending, 10);
const forOutput = _.map(topTen, descAndCountToOutput)
_.forEach(forOutput, output);
});</code></pre>
<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>
<p>One way around this is to use Lodash’s <code>_.chain</code> method. That would have let us write it like this:</p>
<pre class="js"><code>getBurgers().then(burgers =&gt; {
const foo = _.chain(burgers)
.map(toCondiments)
.map(toSortedCondiments)
.map(_toDescriptions)
.reduce(toTotals, {})
.toPairs()
.sortBy(_byCount)
.reverse()
.take(10)
.map(descAndCountToOutput)
.value()
.forEach(output);
});</code></pre>
<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’d have a much harder time doing that in Java or C<sup>♯</sup>!)</p>
<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’t be asking otherwise.</p>
</section>
<section id="with-ramda." class="level4">
<h4>With Ramda.</h4>
<p>But we can actually go a bit further, and end up in a spot where we don’t need to modify the object prototype at all. We can just do this with a series of standalone functions which don’t 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>
<pre class="js"><code>const getTop10Burgers = R.pipe(
R.map(R.prop(&#39;condiments&#39;)),
R.map(R.sortBy(R.toString)),
R.map(R.join(&#39;, &#39;)),
R.reduce(toTotals, {}),
R.toPairs,
R.sortBy(R.prop(1)), // will give us least to greatest
R.reverse,
R.take(10),
R.map(descAndCountToOutput)
);
return getBurgers()
.then(getTop10Burgers)
.then(R.forEach(output));</code></pre>
<p>Notice the difference between here and even where we started with Lodash: we’re no longer dependent on a specific piece of data being present. Instead, we’ve created a standalone function which can operate on that data, simply by “piping” together—that is, <em>composing</em>—a bunch of other, smaller functions. The output from each one is used as the input for the next.</p>
<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>
<p>Here’s 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’s build those into meaningful functions for each step:</p>
<pre class="js"><code>// 1. Convert condiments to descriptions.
const burgerRecordsToDescriptions = R.pipe(
R.map(R.prop(&#39;condiments&#39;)),
R.map(R.sortBy(R.toString)),
R.map(R.join(&#39;, &#39;)),
);
// 2. Build up a mapping from description to count.
const descriptionsToUniqueCounts = R.pipe(
R.reduce(toTotals, {}),
R.toPairs,
);
// 3. Sort that by count.
const uniqueCountsToSortedPairs = R.pipe(
R.sortBy(R.prop(1)),
R.reverse,
);
// For (4), to get the top 10, we&#39;ll just use `R.take(10)`.
// We could also alias that, but it doesn&#39;t gain us much.
// 5. Print it out
const sortedPairsToConsole = R.pipe(
R.map(descAndCountToOutput),
R.forEach(output)
);</code></pre>
<p>Then we can put those together into another, top-level function to do <em>exactly</em> our steps.</p>
<pre class="js"><code>const getTop10Burgers = R.pipe(
burgerRecordsToDescriptions, // (1)
descriptionsToUniqueCounts, // (2)
uniqueCountsToSortedPairs, // (3)
R.take(10) // (4)
);
getBurgers()
.then(getTop10Burgers)
.then(sortedPairsToConsole); // (5)</code></pre>
<p>Notice that, because each step is just composing together functions, “refactoring” is easy. And, to be sure, you have to be mindful about what comes in and out of each function. But that’s true in the imperative approach, too: you always have to keep track of the state of the object you’re building up, but there you’re doing it in the middle of a loop, so you’re 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’s true even in JavaScript, but it goes double if we’re in a typed language like F<sup>♯</sup>, Elm, etc., where we can specify those types for the function as a way of designing the flow of the program. (That’s such a helpful way of solving problems, in fact, that I may also do a talk on type-driven design in the future!)</p>
<p>Note, as well, that we’ve 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’re going to print it to the console when we finish.</p>
<hr />
<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>
<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 “functional” JavaScript versions we wrote.</p>
<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—consequences we’ve talked about all along the way, but which you’ve now seen in practice:</p>
<ol type="1">
<li><p>Those pieces are easy to test. If something isn’t 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>
<li><p>Because they’re 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’re doing in those examples is not even something we wrote ourselves. They’re also <em>really</em> basic building blocks, available in basically every standard library.</p></li>
</ol>
<p>One last thing: if you’re curious about performance… you should know that it does matter for data at scale. In my tests (which are admittedly extremely unscientific; unfortunately, I couldn’t 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>
<ul>
<li>The imperative version, unsurprisingly, was the fastest, taking ~16–17ms.</li>
<li>After that, the chained lodash version and the pure-<abbr>JS</abbr> version were comparable, at ~32–36ms, or around twice as long to finish as the imperative version.</li>
<li>The plain lodash version was consistently a <em>little</em> slower yet, at ~38–43ms.</li>
<li>Ramda is <em>slow</em>: both variations consistently took over 90ms to finish.</li>
</ul>
<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>
<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’t. Ramda is likely slower because of the way it curries every function—something that works well in languages with native support for it, e.g. F<sup>♯</sup> or Elm or Haskell, but imposes a penalty in languages which don’t… like JavaScript. That said, if you’re not in the habit of processing tens of thousands of records, you’re probably okay using any of them.</p>
</section>
</section>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<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">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 11 Nov 2016 22:30:00 -0500tag:v4.chriskrycho.com,2016-11-11:/2016/what-is-functional-programming.htmlsoftware developmentfunctional programmingjavascriptWhy Everything is Brokenhttp://v4.chriskrycho.com/2016/why-everything-is-broken.html<p>It’s something of a joke among many of the software developers I know to wonder aloud how <em>anything</em> works. We’re all very painfully aware of how hard it is to write correct code, of how hard it is to account for all the corner cases that will arise, and of how hard it is to write user interfaces (of any sort) that make good sense to the user.</p>
<p>And our assumptions are broken in weird ways, but we don’t even realize it. Our paradigms for computing are built on decisions made 40–50 years ago, and in many cases there is no <em>good</em> reason to continue doing things that way in a vacuum. But we’re not in a vacuum, and we have incredible resources built on top of those existing paradigms, and rewriting everything form scratch in a saner way with the lessons we’ve learned in the intervening years seems impossible.</p>
<p>All of this came home to me again this evening in one of those startlingly painful moments of realization at how ridiculous this stack of cards we’ve built really is.</p>
<p>I was helping a colleague, a designer who’s been learning HTML and CSS, figure out why his page wasn’t displaying properly on GitHub Pages. The site was loading, and the image assets were loading, but the style sheets weren’t. In fairly short order, I pulled up the site, noticed that the paths were to <code>/css/style.css</code>, glanced at the source and noted that the actual content was at <code>/CSS/style.css</code>, and said: “Oh, you just need to make the case of these match!” I explained: the URL proper (everything up through <code>.com</code> or whatever domain ending) is case-insensitive, but everything after that is case-sensitive.</p>
<p>There are reasons for that, some historical and some having to do with the fact that you can just serve a web page directly from a server, so the paths on your file system map to the paths on the web. And if your file system is case-sensitive, then the URL has to respect that.</p>
<p>That is, in a word, <em>dumb</em>. Don’t get me wrong: again, I see the perfectly defensible technical reasons why that is so. But it’s a leaky abstraction. And when you look closely at them, nearly <em>all</em> of our abstractions leak, and badly.</p>
<p>The pain of that moment was realizing, that like so many other things in tech, this particular thing is still broken for two reasons:</p>
<ol type="1">
<li>It’s too hard or too painful to change it. (That’s a big one here; the web has a pretty firm commitment to absolute backwards compatibility forever, <em>modulo</em> a few things like killing Flash.)</li>
<li>We get used to it, and just come to accept the ten thousand papercuts as normal, and eventually even forget about them until something comes up again and <em>forces</em> us to see them. Usually in the form of someone learning for the first time.</li>
</ol>
<p>We can’t necessarily do a lot about (1). We don’t have infinite time or money, and reinventing everything really is impossible. We can do wacky experiments, and iterate toward better solutions that can gradually replace what was there originally.</p>
<p>But (2) is the bigger one. We need to stop accepting the papercuts as just part of how things are—and especially, stop seeing our acclimation to them as a badge of honor to be earned—and start treating them as rough edges that ought to be sanded off over time wherever possible. Notice the things that trip up new learners, and if you can, <em>get rid of them</em>. If you can’t get rid of them, make note so that you are sure to cover it when you’re helping someone in the future. And explain the <em>whys</em> for those little edge cases: even worse than not knowing them, in some ways, is knowing them but not understanding them—having a bag of little tricks you can use but never being able to progress because you can’t see how they fit together.</p>
<p>Making our tech better starts, in many ways, with recognizing the problems we have. It requires us not to accept (much less embrace or revel in) the status quo, and always to push ourselves to do better. So iterate like made to get away from (1) and to fix (2).</p>
Chris KrychoTue, 01 Nov 2016 20:45:00 -0400tag:v4.chriskrycho.com,2016-11-01:/2016/why-everything-is-broken.htmlsoftware developmentRust vs. React Native—What?http://v4.chriskrycho.com/2016/rust-vs-react-native-what.html<p><i class=editorial>I was recently discussing some thoughts I’ve 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 “React + JS is eating the world right now” and that “Rust as awesome for if you want to write a JS vm, or something like that… or a compiler… anything involving lots of speed and stability.” What follows is my response, lightly edited to remove details specific to that friend and to add a few further thoughts.</i></p>
<hr />
<blockquote>
<p>Here’s the thing: I don’t <em>care</em> what’s eating the world today, for three reasons:</p>
<ol type="1">
<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’t. Heck, even if you just want killer performance <em>in browsers</em>, our future includes things like Rust-to-WebAssembly, and that’s a good thing.</li>
<li>What was eating the world five years ago? Ten? Is it still eating the world today? I don’t feel obliged to follow those trends (not least because, not being a consultancy, following those trends doesn’t buy me anything for the things I want to do; your tradeoffs and mine look way different).</li>
<li>I’m 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’t see browsers catching up to what you can do with e.g. Cocoa (Touch). Sure, that doesn’t 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’s not a <em>necessary</em> decision, and you can (and should) go after the same degree of ease-of-extensibility that Atom has had—perhaps even using things like HTML and CSS for skinning!—while 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’m looking for ways to change that.</li>
</ol>
<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’s!) 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’re likely to be delivering. Don’t 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’t be dismissed simply because it’s a very different world from doing Ruby or Elixir or JavaScript.</p>
</blockquote>
<hr />
<p><i class=editorial>So much for my initial response. On reflection, I wanted to expand it a bit. So here’s another few hundred words!</i></p>
<p>Beyond this, I think there’s a bit of a false dichotomy here: the idea that “lots of speed and stability” <em>aren’t</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’t really care how you get at those goals, whether it’s 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’re used to when writing languages like Python or Ruby and so much of the power you get in languages like OCaml or F♯.<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’re often shipping apps that are slower and more finicky.</p>
<p>But I have this dream of a world where apps aren’t needlessly power-hungry or memory-intensive, where every swipe and or click or scroll results in buttery-smooth responses. We won’t get there by saying, “You know, Facebook is doing <em>x</em> so that’s good enough for me.”</p>
<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’re primarily shipping web applications, investing in Elixir and React with React Native for your apps is a very sensible move. Most of your clients’ 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>
<p>But let’s 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’t dismiss Rust (or Swift, or F♯) out of hand.</p>
<p>Equally importantly, we need to stop assuming that just because something is eating the world today means it’s also the future. Betting big on Flash in the mid-2000s wasn’t a <em>bad</em> move by a long shot. But its massive popularity then wasn’t 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’t believe me, look at the actual open-source records of both of those companies! What’s 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>
<p>My friend gets that, for what it’s worth. He’s making the right moves for his business as the owner of a consultancy. I just want him—and lots of other people—to see where languages like Rust and Swift and F♯ might be worth considering. And speed and stability matter in a lot of places besides just compilers and VMs.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I’m aware that React-Native ultimately binds down to native widgets. It’s still not quite the same.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<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">↩</a></p></li>
<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’t</em> ship core functionality in Swift for Android or Windows.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 07 Oct 2016 08:20:00 -0400tag:v4.chriskrycho.com,2016-10-07:/2016/rust-vs-react-native-what.htmlJavaScriptRustSwiftF Sharpsoftware developmentConsistency in User Interfaceshttp://v4.chriskrycho.com/2016/consistency-in-user-interfaces.html<p>People sometimes ask what I mean when I say Git’s UI is maddeningly inconsistent. Here’s a concrete example: what are the commands to list tags, branches, and stashes?</p>
<ul>
<li><code>git tag --list</code></li>
<li><code>git branch --list</code></li>
<li><code>git stash list</code></li>
</ul>
<p>Follow that up by noticing the difference in meaning for the <code>-v</code> flag between the commands:</p>
<ul>
<li><code>git branch -v</code>: <em>verbose</em> mode: list the hash with an abbreviated commit summary</li>
<li><code>git tag -v</code>: <em>verify</em> a tag against its GPG signature</li>
<li><code>git stash list -v</code>: no-op, completely ignored</li>
</ul>
<p>This is <em>disastrously</em> bad user interface design, and there is literally no reason for it except that the developers of Git, led by Linus Torvalds, don’t care about designing for end users. They hack in whatever commands seem to make the most sense right here and right now, and call it good—and then imply or directly state that anyone who has a problem with it is stupid or lazy.</p>
<p>But users are neither stupid nor lazy, and it is not stupid or lazy to want a system to behave in a a consistent way. Imagine if the buttons on you car’s media dashboard (a plastic one where the labels stay the same) did different things depending on whether you were in <em>Drive</em> or <em>Reverse</em>. Or if the light switches in your house behaved differently if you were using your toaster than if you were vacuuming, “on” and “off” labels notwithstanding.</p>
<p>Good user interface design is no less applicable to a command-line utility than to a pretty iOS app. Don’t let Linus Torvalds or anyone else tell you otherwise.</p>
Chris KrychoFri, 15 Jul 2016 10:37:00 -0400tag:v4.chriskrycho.com,2016-07-15:/2016/consistency-in-user-interfaces.htmlgitsoftware developmentY Combinators, how do they even work?http://v4.chriskrycho.com/2016/y-combinators-how-do-they-even-work.html<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—and, 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’s exactly what you’ll find below; this is basically <em>commentary</em> on Might’s original post.</i></p>
<p><i class=editorial>A few other prefatory notes:</i></p>
<ol type="1">
<li><i class=editorial>Since this is commentary, I’m not focusing on explaining combinators in general. For a very helpful explanation, though, both of what combinators are and why you’d ever want to use them, <a href="http://programmers.stackexchange.com/a/117575">read this</a>.</i></li>
<li><i class=editorial>The Y Combinator itself isn’t 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’s why I was reading about it and trying to figure out what was going on in Might’s original post.</i></li>
<li><i class=editorial>This didn’t actually all make sense to me until I also read Might’s post, <a href="http://matt.might.net/articles/python-church-y-combinator/">“Equational derivations of the Y combinator and Church encodings in Python”</a>. Which is a crazy post. But kind of fun. </i></li>
</ol>
<hr />
<p>Note for background (this was new to me today): <span class="math inline"><em>λ</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>
<pre class="js"><code>const λv_e = v =&gt; e</code></pre>
<p>The Y Combinator is a higher-order functional: it is a function which takes a functional/higher-order function. Quoting from Might:</p>
<blockquote>
<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>
</blockquote>
<p>And a “fixed point” 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>) = <em>x</em></span>. He uses the example <span class="math inline"><em>x</em> = <em>x</em><sup>2</sup> − 1</span>, which has two solutions, two <em>fixed points</em>.</p>
<p>He starts out with the total recursion form—also known as the “crash all the things!” form—of the Y-combinator. (I’m using letters to denote the version of the combinator; this is Y-naive.)</p>
<pre class="js"><code>const Yn = (F) =&gt; F(Yn(F)) // all the recursing!</code></pre>
<p>“Crash all the things”… because of one pesky little detail: it calls itself immediately, and so recurses infinitely. Which is actually kind of a problem.</p>
<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’re doing, so:</p>
<figure>
<span class="math inline"><em>Y</em>(<em>F</em>) = <em>F</em>(<em>λ</em><em>x</em>.(<em>Y</em>(<em>F</em>))(<em>x</em>))</span>
</figure>
<p>(I haven’t done this kind of thing since undergraduate math work I did for physics, but as I was thinking about it, it made sense. I’m used to trying to <em>remove</em> extraneous variables when dealing with software, but in this case we’re using it as a tool for transforming the equation into a form that is <em>equivalent</em> but <em>expressed differently</em>.)</p>
<p>And <span class="math inline"><em>λ</em><em>x</em>.(<em>Y</em>(<em>F</em>))(<em>x</em>)</span> is equivalent to the fixed point. It’s 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>) = <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>
<p>Here’s my implementation, using modern JS; note that it still recurses. (I’m calling this updated Y-transformed, so <code>Yt</code>.)</p>
<pre class="js"><code>const Yt = (F) =&gt; F((x) =&gt; Yt(F)(x))</code></pre>
<p>His version:</p>
<pre class="js"><code>function Y(F) { return F(function(x) { return Y(F)(x); }); }</code></pre>
<p>Mine and his are equivalent; here’s his version transformed to modern JS:</p>
<pre class="js"><code>const Y = (F) =&gt; F((x) =&gt; Y(F)(x))</code></pre>
<p>Might then says:</p>
<blockquote>
<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>
</blockquote>
<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’t skip how the U combinator works or what transformations he applies, because then he jumps to this form:</p>
<figure>
<span class="math inline"><em>Y</em> = (<em>λ</em><em>h</em>.<em>λ</em><em>F</em>.<em>F</em>(<em>λ</em><em>x</em>.((<em>h</em>(<em>h</em>))(<em>F</em>))(<em>x</em>)))(<em>λ</em><em>h</em>.<em>λ</em><em>F</em>.<em>F</em>(<em>λ</em><em>x</em>.((<em>h</em>(<em>h</em>))(<em>F</em>))(<em>x</em>)))</span>
</figure>
<p>Writing this out in JS is going to be a real bear. More to the point, I don’t know how he got to it; now I need to go look up the U Combinator it seems.</p>
<p>…which I’ve <a href="http://www.ucombinator.org">now done</a>. So:</p>
<blockquote>
<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>) = <em>f</em>(<em>f</em>)</span>, or equivalently, <span class="math inline"><em>U</em> = <em>λ</em><em>f</em>.<em>f</em>(<em>f</em>)</span>.</p>
</blockquote>
<ul>
<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>) = <em>f</em>(<em>f</em>)</span>—you 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’s also there in the <span class="math inline"><em>h</em>(<em>h</em>)</span> calls.</li>
<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>
</ul>
<p>I’ll return to that in a moment. First, writing up the JS. The innermost term is (repeated) <span class="math inline"><em>λ</em><em>x</em>.((<em>h</em>(<em>h</em>))(<em>F</em>))(<em>x</em>)</span>, so we’ll start by writing this out.</p>
<pre class="js"><code>const λ_inner = (x) =&gt; (h(h)(F))(x)</code></pre>
<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>λ</em><em>h</em>.<em>λ</em><em>F</em>.<em>F</em>(<em>λ</em><sub><em>i</em></sub><em>n</em><em>n</em><em>e</em><em>r</em>)</span> (where we’re substituting the <code>λ_inner</code> we just wrote to make this a bit easier to get our heads around).</p>
<p>Remembering that each “.” in the equation represents a mapping, i.e. a JS function call, we have this (writing it with function definitions starting new lines to clarify):</p>
<p>Here’s what I came up with as a fairly direct translation into JS:</p>
<pre class="js"><code>const Y = (
(h) =&gt;
(F) =&gt; F((x) =&gt; (h(h)(F))(x)) // substituting λ_inner from above
) (
(h) =&gt;
(F) =&gt; F((x) =&gt; (h(h)(F))(x)) // substituting λ_inner from above
)</code></pre>
<p>His (note that things are aligned as they are so that it’s clear which functions match up):</p>
<pre class="js"><code>var Y = function (F) {
return (function (x) {
return F(function (y) { return (x(x))(y);});
})
(function (x) {
return F(function (y) { return (x(x))(y);});
}) ;
} ;</code></pre>
<p>His transformed to modern JS:</p>
<pre class="js"><code>const Y = (F) =&gt; (
(x) =&gt; F((y) =&gt; x(x)(y))
) (
(x) =&gt; F((y) =&gt; x(x)(y))
)</code></pre>
<p>His and mine are not <em>quite</em> the same (though I know they’re equivalent because they both work). I really wish he’d explained how he got <em>this</em> substitution as well! More importantly, I wish he’d been consistent in his notation; changing variable names is… frustrating when you’re trying to follow someone’s work.</p>
<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>
<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’t recursive. But with the Y Combinator, it builds a function which is <em>not</em> recursive; it doesn’t reference itself anywhere. It just needs the right kind of “factory”: a function which returns <em>another</em> funtion which itself <em>is</em> recursive. Here’s a standard recursive factorial implementation (identical to the one Might supplies, though modernized):</p>
<pre class="js"><code>const FactGen =
(fact) =&gt;
(n) =&gt; n === 0 ? 1 : n * fact(n - 1)</code></pre>
<p>You call that like this:</p>
<pre class="js"><code>Y(FactGen)(5) // 120</code></pre>
<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>
<pre class="js"><code>const factorial = Y(FactGen)
factorial(5) // 120</code></pre>
<p>But I’m still not sure how his and mine are equivalent.</p>
<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>
<p>So in his Y combinator, the substitution goes like this:</p>
<pre class="js"><code>const Y = (F) =&gt; ( // F is FactGen
// x is the identical function passed as argument below
(x) =&gt;
// Run FactGen by taking the function below as its `fact`
// argument.
F(
// `y` is the argument passed to the result of Y, e.g.
// `fact(5)`. Recall that `x` is the function below; we
// call it with itself. Calling x(x) will get the actual
// factorial function returned by `FactGen`.
(y) =&gt; x(x)(y)
)
// We close the *expression* which defines the outer function,
// and call it with this next expression as an argument.
) (
// and x here is the same function, passed as argument
(x) =&gt;
// Again, run `FactGen` with this function as its argument.
F(
// `y`, again, will be the integer. `x(x)` again will be
// the actual factorial function.
(y) =&gt; x(x)(y)
)
)</code></pre>
<p>This is pretty funky! But it works; the two anonymous functions call <em>each other</em> rather than recursing directly.</p>
<p>In mine, it goes like this, instead:</p>
<pre class="js"><code>const Ymine = (
// Where in Might&#39;s example, the `x` function was where the
// U Combinator was applied, here (because I followed the
// original notation he gave) it&#39;s `h`. So it&#39;s `h` which is
// the same function handed back and forth as argument
// to itself.
(h) =&gt;
// `h` takes a functional, which takes `FactGen` as its
// parameter. This is similar to the outermost function in
// Might&#39;s version.
(F) =&gt;
// As in Might&#39;s version, we call `FactGen` here.
F(
// The form is *similar* but not identical to his,
// because of the extra call structure. `h(h)(F)` is the
// factorial function.
//
// Note that then he has `y` where I have `x`; my `x`
// and his `y` are just the result of the computation
// (in this case, the integer factorial).
(x) =&gt; (h(h)(F))(x))
) (
// This is identical to the above; it&#39;s using the U Combinator.
(h) =&gt; (F) =&gt; F((x) =&gt; (h(h)(F))(x))
)</code></pre>
<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>
<p>I still couldn’t <em>do</em> the simplification he did myself. It’ll take more practice using and thinking about combinators and combinatorial logic before I get there, but that’s okay. That’s how learning works.</p>
<p>And that’s enough playing with combinatorials for now. (Except that I’m kind of tempted to see if I can go implement the U or Y combinators—or both—in Rust.)</p>
<hr />
<p><i class=editorial>If you’re curious how I worked this out… I expanded the JS representations of the final forms (<a href="//v4.chriskrycho.com/extra/ycombinator.js">here’s 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’s fascinating, and well worth your time.</i></p>
Chris KrychoSun, 19 Jun 2016 09:20:00 -0400tag:v4.chriskrycho.com,2016-06-19:/2016/y-combinators-how-do-they-even-work.htmljavascriptsoftware developmentprogramming languagesTesting Ember.js Mixins (and Helpers) With a Containerhttp://v4.chriskrycho.com/2016/testing-emberjs-mixins-with-a-container.html<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>
<hr />
<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’re shipping at Olo, and I ran into an interesting problem when trying to test it.</p>
<p>When you’re testing mixins (or helpers), you’re 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’t 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>
<pre class="js"><code>import Ember from &#39;ember&#39;;
import BarMixin from &#39;foo/mixins/bar&#39;;
import { module, test } from &#39;qunit&#39;;
module(&#39;Unit | Mixin | bar&#39;);
// Replace this with your real tests.
test(&#39;it works&#39;, function(assert) {
let BarObject = Ember.Object.extend(BarMixin);
let subject = BarObject.create();
assert.ok(subject);
});</code></pre>
<p>Note two things:</p>
<ol type="1">
<li>It uses the basic Qunit <code>module</code> setup, not the ember-qunit <code>moduleFor</code> setup.</li>
<li>It assumes you’re generating a new object instance for every single test.</li>
</ol>
<p>Both of those assumptions are fine, <em>if you don’t need to interact with the container</em>. In many cases, that’s perfectly reasonable—I’d go so far as to say that most mixins and helpers probably <em>shouldn’t</em> have any dependency on the container.</p>
<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’s 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’t normally have the container set up.)</p>
<p>We start by switching from the basic <code>qunit</code> helpers to using the <code>ember-qunit</code> helpers.</p>
<pre class="js"><code>// Replace this...
import { module, test } from &#39;qunit&#39;;
module(&#39;Unit | Mixin | bar&#39;);
// with this:
import { moduleFor, test } from &#39;ember-qunit&#39;;
moduleFor(&#39;mixin:bar&#39;, &#39;Unit | Mixin | Bar&#39;);</code></pre>
<p>The <code>moduleFor()</code> helper has two things going for it—one of which we <em>need</em>, and one of which isn’t strictly <em>necessary</em>, but has some nice functionality. In any case, this will help when registering a container. Those two features:</p>
<ol type="1">
<li>It does support the use of the container. In fact, it’s 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>
<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>
</ol>
<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>
<pre class="js"><code>const BarObject = Ember.Object.extend(BarMixin);</code></pre>
<p>Then, in each test, I created instances of this to use:</p>
<pre class="js"><code>test(&#39;test some feature or another&#39;, function(assert) {
const subject = BarObject.create();
// ...do stuff and test it with `assert.ok()`, etc.
});</code></pre>
<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’s injected into the mixin like this in <code>foo/app/mixins/bar.js</code>:</p>
<pre class="js"><code>import Ember from &#39;ember&#39;;
export default Ember.Mixin.create({
quux: Ember.inject.service()
});</code></pre>
<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>
<pre><code>test(&#39;it uses quux somehow&#39;, function(assert) {
const subject = BarObject.create();
const quux = subject.get(&#39;quux&#39;); // throws Error
});</code></pre>
<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>
<p>Taking advantage of the two <code>ember-qunit</code> features, though, we can handle all of this.</p>
<pre class="js"><code>import Ember from &#39;ember&#39;;
import { moduleFor, test } from &#39;ember-qunit&#39;;
const { getOwner } = Ember;
moduleFor(&#39;mixin:bar&#39;, &#39;Unit | Mixin | bar&#39;, {
// The `needs` property in the options argument tells the test
// framework that it needs to go find and instantiate the `quux`
// service. (Note that if `quux` depends on other injected
// services, you have to specify that here as well.)
needs: [&#39;service:quux&#39;],
// Again: any object we create in this options object will be
// available on the `this` of every `test` function below. Here,
// we want to get a &quot;test subject&quot; which is attached to the
// Ember container, so that the container is available to the
// test subject itself for retrieving the dependencies injected
// into it (and defined above in `needs`).
subject() {
BarObject = Ember.Object.extend(BarMixin);
// This whole thing works because, since we&#39;re in a
// `moduleFor()`, `this` has the relevant method we need to
// attach items to the container: `register()`.
this.register(&#39;test-container:bar-object&#39;, BarObject);
// `Ember.getOwner` is the public API for getting the
// container to do this kind of lookup. You can use it in lots
// of places, including but not limited to tests. Note that
// that because of how the dependency injection works, what we
// get back from the lookup is not `BarObject`, but an
// instance of `BarObject`. That means that we don&#39;t need to
// do `BarObject.create()` when we use this below; Ember
// already did that for us.
return getOwner(this).lookup(&#39;test-container:bar-object&#39;);
}
});
test(&#39;the mixin+service does what it should&#39;, function(assert) {
// We start by running the subject function defined above. We
// now have an instance of an `Ember.Object` which has
// `BarMixin` applied.
const subject = this.subject();
// Now, because we used a test helper that made the container
// available, declared the dependencies of the mixin in `needs`,
// and registered the object we&#39;re dealing with here, we don&#39;t
// get an error anymore.
const quux = subject.get(&#39;quux&#39;);
});</code></pre>
<p>So, in summary:</p>
<ol type="1">
<li>Use the <code>ember-qunit</code> helpers if you need the container.</li>
<li>Define whatever dependencies you have in <code>needs</code>, just as you would in any other test.</li>
<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’re off to the races!</li>
</ol>
<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’s a reason that the tests generated by Ember CLI don’t use <code>moduleFor()</code> by default. It’s a quiet but clear signal that you should reevaluate whether this <em>is</em> in fact the correct approach.</p>
<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>
<p>But if not, and you <em>do</em> need a mixin which injects a service, now you know how to do it!</p>
<hr />
<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’m guessing I’m not the only one.</p>
<p>When this happens, <em>write it up</em>. I’ve been guilty of this too often in the past few months: learning something new that I couldn’t find anywhere online, and then leaving it stored in my own head. It doesn’t take a particularly long time to write a blog post like this, and if you’re stuck, chances are <em>very</em> good someone else is too.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>If you’re not familiar with the “container”, 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">↩</a></p></li>
<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’re my Ember.js documentation team friend and you’re reading this… it’s coming. 😉<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoThu, 09 Jun 2016 20:35:00 -0400tag:v4.chriskrycho.com,2016-06-09:/2016/testing-emberjs-mixins-with-a-container.htmlemberjsjavascriptsoftware developmentUlysses, Byword, and “Just Right”http://v4.chriskrycho.com/2016/ulysses-byword-and-just-right.html<p>I’m trying out Ulysses again, as it’s been updated substantially since I last used it. I think the main thing to say about it is that it’s gorgeous and a really great editor, and that there is nonetheless something about it which makes it feel not quite as <em>fluid</em> as Byword always has.</p>
<p>Neither of them quite <em>nails</em> it for my purposes, though:</p>
<ul>
<li>Neither is quite there for text that includes a lot of code samples. (Basically: neither supports the GitHub variations on Markdown, which are incredibly important for <a href="http://v4.chriskrycho.com/rust-and-swift.html">a lot of my writing</a></li>
<li>Neither has the ability to do things like autocompletion of citations from something like BibLatex. (No standalone app does, to my knowledge.)</li>
<li>Ulysses’ most powerful features only work in its iCloud bucket. And they’re not standard: rather than embracing <a href="http://criticmarkup.com">CriticMarkup</a> for comments, they have their own. The same is true of e.g. their code blocks.</li>
<li>Ulysses <em>converts</em> any other Markdown documents to its own custom variant when you open them. Had those documents formatted a way you liked (e.g. with specific kinds of link or footnote formatting)? Don’t expect them to still be that way.</li>
<li>Byword really does one thing well: opening and writing single documents. It does this extremely well, but it also has none of the library management that is useful for larger projects.</li>
</ul>
<p>Both of these apps are really wonderful in many ways, and I think it’s fair to say that they’re <em>perfect</em> for many writers. <a href="http://jaimiekrycho.com/">My wife</a>, for example, does nearly all her fiction writing in Ulysses; it works wonderfully for her. But for the kinds of writing I do—usually technical in one way or another—it is limited in its utility. That’s not really a critique of the apps. It’s more the recognition that I have some pretty unusual requirements of my writing apps.</p>
<p>That said, I don’t think I’m the only person out there who has these particular needs. I am, for example, hardly the only person working with citations and academic text, or writing Markup with lots of code samples in it. And as much as you can bend general-purpose text editors like <a href="https://atom.io">Atom</a> to your will,<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> it’s not the same as a dedicated writing app that focuses—in the ways that Ulysses and Byword both do—on just being a great tool for <em>writing</em>. Writing and writing <em>code</em> are not the same, after all. A tool that’s really well-optimized for the latter isn’t necessarily well-optimized for the former.</p>
<p>Keep your ears open. You might just be hearing more about this in the future.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Trust me, I have: I have Zen mode installed, a custom Byword-like theme I use when I just want to write, and even a citation autocompletion package integrated with it. It’s not bad. But I still don’t love it as a first-choice <em>writing</em> tool.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 26 Mar 2016 08:00:00 -0400tag:v4.chriskrycho.com,2016-03-26:/2016/ulysses-byword-and-just-right.htmldesignsoftware developmentwritingThe Future of JavaScripthttp://v4.chriskrycho.com/2016/the-future-of-javascript.html<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’t get to cover everything I wanted—I would have liked very much to cover modules, and to cover fat-arrow-functions in more depth than I did. I’ll 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’d 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>
<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>
Chris KrychoWed, 02 Mar 2016 12:30:00 -0500tag:v4.chriskrycho.com,2016-03-02:/2016/the-future-of-javascript.htmltalkssoftware developmentprogramming languagesjavascriptStatic Site Generators and Podcastinghttp://v4.chriskrycho.com/2016/static-site-generators-and-podcasting.html<p>Presently, I publish both <a href="http://www.winningslowly.org/">Winning Slowly</a> and <a href="http://www.newrustacean.com/">New Rustacean</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> using what is admittedly a bit of a quirky approach. It works well for me, and I think it’s worth documenting for other nerdy types out there, but if you’re just getting going with podcasting and you’re looking for the easy way to do it, let me warn you: <em>this isn’t it</em>. Something like <a href="https://soundcloud.com/for/podcasting">SoundCloud</a> and a blog for show notes, or <a href="https://wordpress.org">WordPress</a> with <a href="https://wordpress.org/plugins/powerpress/">Blubrry PowerPress</a> is what you want instead. This approach works <em>extremely</em> well for statically-generated sites, however, and I imagine a few people out there might find it useful.</p>
<section id="the-short-version" class="level2">
<h2>The short version</h2>
<ul>
<li>Generate the feeds with <a href="http://reinventedsoftware.com/feeder/">Feeder</a>.</li>
<li>Generate the site statically with something else (and it <em>really</em> doesn’t matter what).</li>
<li>Copy the feed into the generated site.</li>
</ul>
</section>
<section id="the-long-version" class="level2">
<h2>The long version</h2>
<p>I generate the sites themselves with <a href="http://docs.getpelican.com/en/3.6.3/">Pelican</a> and <a href="http://www.newrustacean.com/show_notes/e001/index.html"><code>cargo doc</code></a>, respectively. I was already comfortable with Pelican because it’s what I use to generate <em>this</em> site (with a few <a href="https://github.com/chriskrycho/chriskrycho.com/blob/master/pelicanconf.py">tweaks</a> to the standard configuration, especially using <a href="http://pandoc.org/">Pandoc</a> rather than the Python Markdown implementation), so I ran with it for building the Winning Slowly site, and it has worked quite well for building the site itself. It just gets built locally and deployed via <a href="https://pages.github.com/">GitHub Pages</a>.</p>
<p>However, it does not have built-in support for generating <a href="https://en.wikipedia.org/wiki/RSS_enclosure">podcast feeds</a>, even just the general case with enclosures. <a href="https://itunespartner.apple.com/en/podcasts/overview">iTunes podcast support</a> would have taken a lot of work to add.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> Instead, I chose to build the RSS feed semi-manually. <em>Semi</em>-manually, because doing it totally manually is a recipe for making mistakes. XML is many things, but “easy to write correctly by hand” is not one of them. I use <a href="http://reinventedsoftware.com/feeder/">Feeder</a> to manage the feeds, and <em>it</em> makes sure that the enclosure and iTunes elements are set correctly.</p>
<p>The biggest upside to this is that I can use Pelican without modification to how it generates feeds (apart from optionally turning them off entirely). It just <a href="https://github.com/WinningSlowly/winningslowly.org/blob/master/pelicanconf.py#L99">copies</a> the feed I generate to the output file during its normal build process. As suggested above, I also <em>don’t</em> generate the other feeds which Pelican supports, as we have no need for them; we only care about the podcast feed.</p>
<p>This process works equally well, with very little modification, for New Rustacean. In that case, I’m generating the content by running Rust’s documentation tool, <code>cargo doc</code><a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> to render the “API docs” which serve as show notes. Notice the family resemblance between <a href="http://www.newrustacean.com/show_notes/">my “show notes”</a> and, say, the <a href="http://sgrif.github.io/diesel/diesel/index.html">Diesel docs</a>, which are both generated the same way. This is <em>not</em> a normal way of building a podcast website; you can hear me explain why I did it this way in <a href="http://www.newrustacean.com/show_notes/e001/index.html">New Rustacean e001: Document all the things!</a> In any case, I just take the show note-relevant parts of the documentation and put it in Feeder, generate the feed, and <a href="https://github.com/chriskrycho/newrustacean.com/blob/master/Makefile#L32">copy that as part of the build process</a>.</p>
<p>That’s it!</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>And, incidentally, <a href="http://www.sap-py.com">Sap.py</a> and my <a href="http://v4.chriskrycho.com/sermons.xml">sermons</a> feed.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>If I stick with Pelican long-term, I might look into adding it anyway, but honestly, I don’t love Pelican. The reasons have little to do with Pelican for itself, and a lot more to do with my particular and somewhat peculiar needs. That’s a post for another day. In any case, I’m likelier to use another generator—even one I write myself!—than to do the work to make Pelican do what I want.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>Technically, Rust’s documentation tool is <code>rustdoc</code>, which <code>cargo doc</code> wraps around. I never actually use <code>rustdoc</code> directly, though.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSun, 28 Feb 2016 12:50:00 -0500tag:v4.chriskrycho.com,2016-02-28:/2016/static-site-generators-and-podcasting.htmlsoftware developmentpodcastingpythonrustRust and Swift (xii)http://v4.chriskrycho.com/2016/rust-and-swift-xii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<p><i class="editorial">A note on publication: I had this drafted in early January and simply forgot to publish it. Whoops!</i></p>
<hr />
<ul>
<li><p>As noted in <a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html">my discussion of the product types in Rust and Swift</a>, Swift distinguishes between classes and structs, with the former being reference types and the latter being value types. All structs are value types in Rust. (That you can wrap them in a pointer for heap-allocation with one of the smart pointer types, e.g. <code>Box</code> or <code>Rc</code> or <code>Arc</code>, doesn’t change this fundamental reality.) This underlying difference gives rise to one the big difference between Swift classes and Rust structs: a constant <code>class</code> instance in Swift can still have its fields mutated; not so with a Rust <code>struct</code> instance. But also not so with a <em>Swift</em> <code>struct</code> instance, as it turns out! There isn’t a straightforward way to do this with <code>Box&lt;T&gt;</code> in Rust; you <em>could</em> do it with something like an <code>Rc&lt;T&gt;</code> or <code>Arc&lt;T&gt;</code>, though.</p></li>
<li><p>Swift’s <code>lazy</code> keyword, and associated delayed initialization of properties has, as far as I know, no equivalent whatsoever in Rust. And while I can see the utility in principle, I’m hard-pressed to think of any time in my working experience where the behavior would actually be useful. Rather than having <code>lazy</code> properties, I would be far more inclined to separate the behavior which should be initialized at a later time into its own data structure, and supplying it via <em>inversion of control</em> if it is necessary for an actions taken by other data structures. (This seems—at first blush at least—to be a way of supporting the un- or partially-initialized data types possible in Objective C?)</p></li>
<li><p>Swift has computed properties, a concept familiar to Python developers (and relatively recently introduced in JavaScript). These can be quite handy, as they let you define a property to be accessed like any other (<code>someInstance.theProperty</code>) while being defined with functions which compute the value dynamically. A common, trivial example: if you defined a <code>Person</code> with <code>firstName</code> and <code>lastName</code> members, you could define a computed property, <code>fullName</code>, which was built using the existing values.</p></li>
<li><p>Rust doesn’t have computed properties at all. This is because of its design decision to deeply separate <em>data</em> from <em>behavior</em>, essentially stealing a page from more pure-functional languages (Haskell etc.). This is (one reason) why you don’t define the implementation of a <code>struct</code> method in the same block as the members of the struct. See an excellent explanation <a href="https://www.reddit.com/r/rust/comments/2uvfic/why_doesnt_rust_have_properti%20es/cocmunq">here</a>.</p></li>
<li><p>It’s also closely related the way Rust favors composition over inheritance (by making the latter impossible, at least for now!). By separating <code>impl</code> from <code>struct</code> and <code>enum</code>, Rust makes it not only straightforward but <em>normal</em> to define new behavior for a given item separately from the data description. This, combined with the use of traits (like Swift’s protocols) as the primary way of sharing behavior between objects, means that you don’t have to worry about conforming to some interface when you define a given type; it can always<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> be defined later, even by entirely other modules or even other crates (packages).</p></li>
<li><p>In any case, the result is that it’s not at all Rustic<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> to have something like getters or setters or computed properties. It makes sense to have them in Swift, though, which has a more traditionally object-oriented type system (though with some neat additions in the form of its <code>protocol</code> type classes, which are analogous to Rust’s <code>trait</code>s—but we’ll come to those in a future post). This is a wash: it’s just a function of the slightly different approaches taken in object design in the two systems. If you have a Swift-style type system, you should have computed properties. If you have a Rust-like type system, you shouldn’t.</p></li>
<li><p>I’m shocked—utterly shocked!—to find that Swift provides a default <code>newValue</code> argument for setters for computed properties, and shorthand for defining read-only properties. By which I mean: I find this kind of thing entirely unsurprising at this point in Swift, but I don’t like it any better. Making so much implicit just rubs me the wrong way. Once you know the language, it’s fine of course: you’ll recognize all the patterns. It just seems, in an interesting way, to add cognitive load rather than reducing it. That may just be me, though!</p></li>
<li><p>Interestingly, Swift also allows you to set watchers on given properties—functions called with the new or the removed value whenever the value of the computed property is updated or touched for any reason. It has two of these built in: <code>willSet</code> and <code>didSet</code>. You can override these to get custom behavior when a normal property is about to change. (You can of course just implement the desired behavior yourself in the <code>set</code> method for a computed property.)</p></li>
<li><p>Since Rust doesn’t have properties, it doesn’t have anything analogous. I can’t think of a particularly straightforward way to implement it, either, though you might be able do some chicanery with a trait. Of course you can always define a setter method which takes a value and optional callbacks for actions to take before and after setting the value; the thing that’s nice in Swift is that it gives you these as built-in capabilities within the language itself. (Now I’m wondering if or how you could implement an <code>Observable</code> trait, though! Might have to play with that idea more later.) It’s worth remembering , in any case, that Rust doesn’t have these <em>because it doesn’t have properties</em>.</p></li>
<li><p>Curiously, Swift provides the same functionality for “global” and “local” variables in a given context. In both cases, this is suggestive of the underlying object model for both modules and functions in Swift.</p></li>
<li><p>Now I’m curious what the representation of a module is in Swift; is it part of the general object system in some way?</p></li>
<li><p>This likewise gets me asking: what <em>is</em> a module in Rust? It’s a block item, clearly, and accordingly defines a scope (as do functions, if and match expressions, and so on). It’s <em>not</em> a compilation unit (as it is in C or C++). What other machinery is attached to it?</p></li>
<li><p>Both of these questions can be answered by reading the source code for the languages (<a href="https://github.com/rust-lang/rust">Rust</a>, <a href="https://github.com/apple/swift">Swift</a>), of course. Putting that on my to-do list.</p></li>
<li><p>Swift also has <em>type properties</em>: values common to all instances of a given type. These are directly analogous to <em>class properties</em> (or <em>class attributes</em>) in Python or prototype properties in JavaScript.</p></li>
<li><p>Rust doesn’t have anything like this to my knowledge. You could accomplish something similar using a module-level variable with a <code>'static</code> lifetime,<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> much as you could in C—but that wouldn’t be an item on the type itself, of course.</p></li>
<li><p>The <code>static</code> declaration of item in Swift suggests what a possible implementation might look like in Rust: defining a member like <code>a_static_long: 'static i64</code>. There might be some interesting challenges around that, though; I don’t know enough to comment meaningfully. At the least, it seems like it would be an odd fit with the rest of the memory management approach Rust takes, and it would make it a bit harder to reason correctly about the behavior of data in a given type. (There are certainly issues there around mutability guarantees and lifetime checking!)</p></li>
<li><p>Because of the differences in underlying approach to data types and implementation, this is one of the areas where the superficially (and sometimes actually) similar languages diverge <em>a lot</em>.</p></li>
</ul>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xi.html"><strong>Previous:</strong> Hopes for the next generation of systems programming.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xiii.html"><strong>Next:</strong> Methods, instance and otherwise.</a></li>
</ul>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>leaving aside details about <code>trait</code> specialization <a href="https://github.com/aturon/rfcs/blob/impl-specialization/text/0000-impl-specialization.md">still being hashed out</a> in Rust<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>This is now my preferred term for “idiomatic Rust”—directly analogous to “Pythonic,” but with the upside of being an actual word, and one with pleasantly evocative connotations to boot.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>There’s nothing analogous to Rust’s concept of explicit lifetimes in Swift, as far as I can tell. The <code>static</code> keyword in Swift, like that in C, Objective-C, and C++, is <em>sort of</em> like Rust’s <code>'static</code> lifetime specifically, for variables at least—but Rust’s lifetime is substantially more sophisticated and complex than that analogy might suggest.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 27 Feb 2016 22:30:00 -0500tag:v4.chriskrycho.com,2016-02-27:/2016/rust-and-swift-xii.htmllisticlessoftware developmentrustswiftrust-and-swift“I Don't Know When I'd Use That”http://v4.chriskrycho.com/2016/i-dont-know-when-id-use-that.html<p>I was reading an interesting Stack Overflow <a href="http://stackoverflow.com/questions/21170493/when-are-higher-kinded-types-useful">discussion</a> of the value of <a href="http://stackoverflow.com/questions/6246719/what-is-a-higher-kinded-type-in-scala">higher-kinded types</a> (hereafter <abbr>HKTs</abbr>), and noted someone repeatedly commenting, “But when would you use this in a <em>real app</em>?” To put it the way another <a href="https://m4rw3r.github.io/rust-and-monad-trait/">blog post</a> about <abbr>HKTs</abbr> (in Rust), they are “a feature people do not really know what to do with.”</p>
<p>Don’t get me wrong: I’m sympathetic to that desire for concrete examples. I’m interested in these kinds of things not primarily for their intellectual value but for their pragmatic value (though I don’t think those two are as distinct as many people do). I’d <em>also</em> love to see some more real-world examples in those discussions. All too often, the discussions of types in Haskell end up being quite abstract and academic—no surprise, given the language’s origin. But I’m also aware that quite often it’s difficult to see how a given kind of abstraction is useful without jumping into a language which has that abstraction available and <em>using</em> it.</p>
<p>People often get turned off by Haskell (and other similarly high-abstraction languages like Scala) because of challenging terms like <em>monad</em>, <em>applicative</em>, <em>functor</em>, and so on. And again: I get that. To grok Haskell, you need to wrap your head around a lot of <em>math</em> ideas—mainly various properties of <em>sets</em>.</p>
<p>But I remember feeling the same way six years ago when I started playing with JavaScript and jQuery and every tutorial out there simply assumed existing familiarity and comfort with functions as arguments or return values. Coming from the world of Fortran and C, my head ached for weeks as I tried to make sense of what I was seeing. Even when I finally got it, <em>I didn’t like it</em>. Over the last several years, though, I’ve become increasingly comfortable and even reliant on closures, composition of functions to transform data, and so on as I worked regularly in Python and JavaScript.</p>
<p>That experience has taught me that my current inability to see the utility of a given abstraction means little about the abstraction. It’s primarily an indicator of my own inexperience.</p>
<p>To the question of the utility <abbr>HKTs</abbr> in general—in Haskell, Rust, or somewhere else—I don’t have the knowledge myself (yet) to supply a good answer. Heck, I can’t even <em>explain</em> them very well. (<a href="http://adriaanm.github.io/research/2010/10/06/new-in-scala-2.8-type-constructor-inference/">Other people can, though!</a>) But I can say that reading <a href="https://gumroad.com/l/maybe-haskell"><em>Maybe Haskell</em></a> showed me clearly that such things can be very useful. Even if I am not yet comfortable using that tool, I see how learning to use it would be profitable in the long-term. And like any good tool, even if you don’t need it every day… when you want it, you <em>really</em> want it.</p>
Chris KrychoSun, 17 Jan 2016 10:00:00 -0500tag:v4.chriskrycho.com,2016-01-17:/2016/i-dont-know-when-id-use-that.htmlsoftware developmentprogramming languagesrusthaskellRust and Swift (xi)http://v4.chriskrycho.com/2016/rust-and-swift-xi.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<hr />
<p>I’ve still been (slowly) working through the Swift book and comparing Swift and Rust; I have another draft started which I’ll hopefully finish this week. And I still find the comparison deeply profitable. The two languages continue to evolve in interesting ways, and the comparison is all the more interesting <a href="https://github.com/apple/swift">now that Swift is open-source</a> and its future <a href="https://github.com/apple/swift-evolution">open for community input</a> (just as <a href="https://github.com/rust-lang/rfcs">Rust is</a>).</p>
<p>Something I’ve been thinking about for several months, and which the <a href="https://overcast.fm/+CdSzsTIY/1:16:42">brief discussion of Swift, Go, and Rust</a> at the end of the latest <a href="http://atp.fm/episodes/151">Accidental Tech Podcast</a> brought back to my mind, is the question of what the next generation of systems-level programming language should be. And my answer is: there shouldn’t be <em>just one</em>. The best possible thing for the space, in many ways, is for there to be a healthy diversity of options and lots of competition in the space. We don’t want to have <em>ten</em> different systems programming languages to deal with, I think—but three or four or five would be <em>much</em> preferable to having one or two (closely related) as we have in the decades of C and C++ dominance.</p>
<p>Don’t get me wrong: both languages (and perhaps especially C) do many things exceptionally well. For all that they are (justly) maligned for some of their problems, the longevity of both C and C++ has a great deal to do with how well they fit the problem domain, and how much they’ve empowered developers to accomplish within that space (which is very, <em>very</em> large).</p>
<p>The problem, though, at least as I see it, is that the existence of only two really serious systems programming languages for the last several decades has led a lot of developers to think that C and C++‘s ways of solving problems are the <em>only</em> way to solve problems. The languages we use shape the way we think about possible solutions, and when a given language doesn’t recognize entire classes of different approaches, that deeply limits developers’ ability to tackle certain issues. (See also the interesting CppCast <a href="http://cppcast.com/2015/10/andrei-alexandrescu/">interview with D’s Andrei Alexandrescu</a> in which he makes similar points.)</p>
<p>The most obvious thing missing from both is the ability to do truly functional-style programming. C of course is also lacking classes and thus is much more difficult to use for any sort of object-oriented programming.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> Neither has anything remotely like Rust’s traits or Swift’s extensions; C++ has only gotten lambdas recently.</p>
<p>All of this comes out to mean that the set of <em>tools</em> available to systems programmer has necessarily been missing any number of things available in languages outside that context. In some cases, this may be a necessary consequence of the kinds of programming being done: when you need totally deterministic memory and compiler behavior, dynamic typing and a non-trivial runtime are simply not options. But in many cases, they are simply a function of the history of the languages’ development and history. Being an ALGOL descendant, and especially a C descendant, means there are some fundamental choices about the language which will differ from those made in a language descended from ML.</p>
<p>All of which is to say: C and C++ have been really useful tools in many ways, but having <em>only</em> C and C++ available for serious systems programming work over the last decades has left many developers blind to or simply unaware of the real advantages other paradigms might offer them.</p>
<p>So going forward, I don’t want there to be <em>a winner</em> in the systems programming space. I’d rather see D, Rust, Swift, Go, and maybe even a few other contenders all stay strong—finding their own niches and continually pushing each other and learning from each other. That will give us a space in which different languages are free to try out different approaches to the same problems, without being tied to the specific constraints faced by other languages. Built-in greenthreading? Go! Hindley-Milner types, memory safety, and zero runtime? Rust! Something in beween, highly expressive and with different type systems and tradeoffs around memory management, etc.? Swift, or D!</p>
<p>Having a robust, thriving set of competitors in the market will be good for the languages themselves. But it will also be good for developers. It will take off some of the blinders that come from a single language (or a pair of very closely related languages) dominating the ecosystem. It will make it likelier that people will be more familiar with different programming paradigms. And that can only be a good thing, as far as I’m concerned.</p>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html"><strong>Previous:</strong> Classes and structs (product types), and reference and value types.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xii.html"><strong>Next:</strong> Properties: type and instance, stored and computed.</a></li>
</ul>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>It is of course entirely possible to do non-classical OOP; the point is that C entirely lacks <em>language-level</em> facilities for OOP, inheritance, etc.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSun, 10 Jan 2016 10:00:00 -0500tag:v4.chriskrycho.com,2016-01-10:/2016/rust-and-swift-xi.htmlsoftware developmentrustswiftrust-and-swiftprogramming-languagesRust and Swift (x)http://v4.chriskrycho.com/2015/rust-and-swift-x.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<hr />
<ul>
<li><p>Swift and Rust both have “product types” as well as the <code>enum</code> “sum types.” In Rust, these are <code>struct</code> types; Swift splits them into <code>class</code>es and <code>struct</code>s.</p></li>
<li><p>“Product types” will be much more familiar to programmers coming from a C-like background, or indeed most object-oriented programming languages: these are the same basic kind of thing as classes, structs, and objects in other languages. These include <em>all</em> the value types which compose them, unlike sum types—<code>enum</code>—which have <em>only one</em> of the value types which compose them.</p></li>
<li><p>Right off the bat, I note the Swift book’s somewhat amusing reticence to call out C and C-descended languages:</p>
<blockquote>
<p>Unlike other programming languages, Swift does not require you to create separate interface and implementation files for custom classes and structures.</p>
</blockquote>
<p>Because there’s such a long list of languages not directly descended from C which do that, right? 😉</p></li>
<li><p>Rust differs not only from Swift but from every other modern language I have used in not having a constructor <em>syntax</em> for its instantiations. Whereas C++ has <code>new NameOfType()</code> and Python and Swift both have <code>NameOfType()</code>, “constructors” for Rust <code>struct</code>s are just functions which return an instance constructed using literal syntax, by convention <code>NameOfType::new()</code>.</p></li>
<li><p>Let’s make a <code>struct</code> defining a location in a plane, you might do this in Swift (leaving aside initializer values; I’ll come back to those later). These definitions look <em>very</em> similar. Swift:</p>
<pre class="swift"><code>struct Point {
var x: Double var y: Double
}</code></pre>
<p>Rust:</p>
<pre class="rust"><code>struct Point {
x: f64,
y: f64,
}</code></pre></li>
<li><p>Creating the types looks a little different, though. Here’s a constructor in Swift:</p>
<pre class="swift"><code>let point = Point(x: 0, y: 0)</code></pre>
<p>And the two ways we could construct the type in Rust, a literal constructor (fairly similar to constructing <code>dict</code> literals in Python or object literals in JavaScript):</p>
<pre class="rust"><code>let point = Point { x: 0.0, y: 0.0 };</code></pre>
<p>Or a constructor method, <code>new</code>:</p>
<pre class="rust"><code>// &quot;Constructor&quot;
impl Point {
fn new(x: f64, y: f64) -&gt; Point {
Point { x: x, y: y }
}
}
let another_point = Point::new(0, 0);</code></pre>
<p>Observe: these two things in Rust are the same under the covers (though if <code>Point</code>s had non-public internals, they would be non-trivially different: you couldn’t construct it with its private members externally). As usual, Rust opts to keep the language relatively small in these core areas. Given the plethora of ways you can construct something in e.g. C++, I count that a big win.</p></li>
<li><p>Another difference: Swift has <em>syntax</em> for default values; Rust uses a <code>trait</code> instead. In Swift, you simply supply the default value in the definition of the <code>struct</code> or <code>class</code>:</p>
<pre class="swift"><code>struct Point {
var x = 0.0 var y = 0.0
}
let point = Point()</code></pre>
<p>In Rust, you use <code>std::default::Default</code>, which provides a standard value for a given type, and for simple types can be supplied by the compiler even for custom types. Here is the equivalent Rust code:</p>
<pre class="rust"><code>use std::default::Default;
#[derive(Default)]
struct Point {
x: f64,
y: f64,
}
let point = Point::default();</code></pre>
<p>This is reasonable enough, but we can also supply our own custom implementation if we so desire:</p>
<pre class="rust"><code>use std::default::Default;
struct Point {
x: f64,
y: f64,
}
impl Default for Point {
fn default() -&gt; Point {
Point { x: 0.0, y: 0.0 }
}
}
let point = Point::default();</code></pre>
<p>Of course, this is trivial for this type, but you can see how it could be useful for more complex types.</p></li>
<li><p>The tradeoffs here are our usual suspects: Rust’s re-use of an existing concept/tool within the language (<code>trait</code>) vs. Swift’s use of syntax. Rust is slightly more explicit, making it obvious that a default value is being created—but Swift is perfectly readable and the syntax is consistent with many other languages, and it <em>is</em> shorter.</p></li>
<li><p>Both languages use <code>.</code> syntax for member access. Swift:</p>
<pre class="swift"><code>println(&quot;The point is: \(point.x), \(point.y)&quot;)</code></pre>
<p>Rust:</p>
<pre class="rust"><code>println!(&quot;The point is {:}, {:}&quot;, point.x, point.y);</code></pre></li>
<li><p>Swift lets you define items <em>within</em> a struct as mutable or constant. So you can create a variable struct instance, with some of its items immutable:</p>
<pre class="swift"><code>struct PointOnZAxis {
var x: Double var y: Double let z = 0.0
}
var point = PointOnZAxis(x: 4.0, 5.0)
point.x = 5.0 point.y = 6.0
// This wouldn&#39;t compile, though:
// point.z = 1.0</code></pre>
<p>This is pretty handy for a lot of object-oriented programming approaches.</p></li>
<li><p>And Rust doesn’t have it. There are ways to accomplish the same thing; this isn’t the end of the world. Still, it’s an interesting omission, and it’s very much by design. Rust <em>used</em> to have this feature, and dropped it—and for good reason. Say you had a mutable field in a mutable struct, and then an immutable reference to it; should the mutable field be mutable, or immutable, with that reference?</p></li>
<li><p>The Rusty way to do this is to differentiate between public and private data. The above examples don’t make the public/private distinction particularly clear, because they assume everything is within the same module. However, many times, this will not be the case.</p>
<pre class="rust"><code>mod geometry {
pub struct Point {
x: f64,
pub y: f64,
}
impl Point {
pub fn new() -&gt; Point {
Point { x: 0.0, y: 0.0 }
}
pub fn set_x(&amp;mut self, x: f64) {
self.x = x;
}
}
}
fn main() {
// Won&#39;t compile: the `x` field is private.
// let mut p = geometry::Point { x: 0.0, y: 0.0 };
// Will compile: the `new` method is public.
let mut p = geometry::Point::new();
// Won&#39;t compile: `x` isn&#39;t public.
// p.x = 4.0;
// You can use the setter, though:
p.set_x(4.0);
// You *can* set `y` directly, though, because it&#39;s public.
p.y = 14.0;
// You can&#39;t set fields either way if the instance is immutable.
let q = geometry::Point::new();
// This fails because `set_x` requires a mutable reference, but `q` is
// immutable.
// q.set_x(4.0);
// This fails because `q` is immutable, and so all its fields are, too.
// q.y = 14.0;
}</code></pre></li>
<li><p>This is an interesting way of handling this issue. Rust takes the fairly standard use of information hiding (one of the basic principles of most object-oriented programming techniques) and combines it with the language’s normal mutability rules to make it so that the mutability of any given instance data is quite clear: all public members are just as mutable as the struct. If a member isn’t potentially publicly mutable, it isn’t publicly accessible. I really like this, though it took some mental readjustment.</p></li>
<li><p>There’s one other difference here, and it’s actually one of the areas Swift and Rust diverge substantially. Rust has <code>struct</code> for all product types; Swift splits them into <code>struct</code> types and <code>class</code> types.</p></li>
<li><p>Swift <code>class</code>es have inheritance; there is presently <em>no</em> inheritance in Rust.</p></li>
<li><p>Additionally, whereas Rust determines whether to use pass-by-reference or-value depending on details of the type (whether it implements the <code>Copy</code> <code>trait</code>) and expected arguments to a function, Swift makes that distinction between <code>class</code> (pass-by-reference) and <code>struct</code> (pass-by-value) types. Quirky.</p></li>
<li><p>Not bad, <em>per se</em>. But quirky.</p>
<p><strong>Edit:</strong> I recently bumped into some discussion of data types in C♯ along with C, C++, and Java (<a href="http://joeduffyblog.com/2015/12/19/safe-native-code/">here</a>) and discovered that Swift is stealing this idea from C♯, which <a href="https://msdn.microsoft.com/en-us/library/0taef578.aspx">makes the same copy/reference distinction</a> between <code>struct</code> and <code>class</code>.</p></li>
<li><p>One consequence of this: in Rust, you’re always rather explicit about whether you’re accessing things by value vs. by reference. Not so in Swift; you have to remember whether the item you’re touching is a <code>struct</code> type or a <code>class</code> type, so that you can <em>remember</em> whether a given assignment or function call results in a reference or a copy. This is necessary because Swift doesn’t let you make that explicit (trying to hide the memory management from you). And it’s not alone in that, of course; many other high-level languages obscure that for convenience but still require you to think about it in certain circumstances. I’ve been bitten in the past by the value/reference distinction when thinking through the behavior of Python objects, for example, so that’s not a critique of Swift. Moreover, having the distinction between <code>struct</code> and <code>class</code> types does let you be <em>more</em> explicit than you might in e.g. Python about how given data will be handled.</p></li>
<li><p>I won’t lie, though: I like Rust’s approach better. (Shocking, I know.)</p></li>
<li><p>All that nice initializer syntax for Swift <code>struct</code> types is absent for its <code>class</code> types, which seems strange to me.</p></li>
<li><p>Swift supplies some syntax for object identity, since it’s useful to know not only whether two <code>class</code> instances have the same data, but are in fact the same instance. You can use <code>===</code> and <code>!==</code>. Handy enough. To get at this kind of equivalence in Rust, you have to use raw pointers (which are often but not always <code>unsafe</code>; you can do this specific comparison <em>without</em> being <code>unsafe</code>, for example) to check whether the memory addresses are the same.</p></li>
</ul>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-ix.html"><strong>Previous:</strong> Sum types (<code>enum</code>s) and more on pattern matching.</a></li>
<li><a href="http://v4.chriskrycho.com/2016/rust-and-swift-xi.html"><strong>Next:</strong> Hopes for the next generation of systems programming.</a></li>
</ul>
Chris KrychoSun, 06 Dec 2015 11:25:00 -0500tag:v4.chriskrycho.com,2015-12-06:/2015/rust-and-swift-x.htmllisticlessoftware developmentrustswiftrust-and-swiftRust and Swift (ix)http://v4.chriskrycho.com/2015/rust-and-swift-ix.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<hr />
<ul>
<li><p>Right off the bat when looking at the definitions for Swift’s and Rust’s <code>enum</code> types, a difference pops out: the use of the keyword <code>case</code> to introduce an enum member in Swift. In one sense, this overloads that keyword, but in another sense it’s fine: pattern matching and enums go hand in hand, so the use in both cases is fairly natural. Rust doesn’t have any special syntax to designate the elements of an enum; they’re just separated by commas.</p></li>
<li><p>I am not at all shocked to find that Swift has a variant syntax for its unit type case declarations, where a single <code>case</code> keyword precedes a list of comma-separated cases defined on a single line. (At this point, I would be more surprised <em>not</em> to find a variant syntax for something in Swift!)</p></li>
<li><p>Something truly wonderful about both Rust and Swift: enumerated types aren’t just wrappers around integer values. They’re real types of their own. This is powerful.</p></li>
<li><p>Rust and Swift also share in having enumerated types that can hold values. The most prominent of these so far in the Swift book are optionals, the <code>Optional</code> enum type, corresponding very closely to Rust’s <code>Option</code> type. Having had these for a bit in playing with Rust, and having gotten familiar with the utility of types like these while reading <a href="https://gumroad.com/l/maybe-haskell"><em>Maybe Haskell</em></a>—a delightful book which introduces Haskell and functional programming using Haskell’s <code>Maybe</code> type—I now miss them profoundly in languages which don’t have them. (Which is to say: every language I use on a regular basis professionally: C, C++, Python, JavaScript, etc.).</p></li>
<li><p>Swift’s enum types don’t have integer values <em>by default</em>—but they can have them if you define a type and assign a value to each enum case at the definition. These “raw values” are distinct from the “associated values” noted just above. I expect these exist primarily for ease of interoperation with Objective-C.</p></li>
<li><p><del>Rust doesn’t have anything like this, at least that I can think of. The main place it would be useful would be for foreign function interfaces (as in Swift), and this is one of several such gaps in Rust,</del> along with the lack of a straightforward way to map to C’s <code>union</code> types. <del>There are trade offs in terms of adding the functionality to the language, though, as it substantially increases the complexity of what an enum value can be, I think.</del></p>
<p><strong>Edit:</strong> This was incorrect. From the <a href="https://doc.rust-lang.org/reference.html">Rust Reference</a> section on <a href="https://doc.rust-lang.org/reference.html#enumerations">Enumerations</a>:</p>
<blockquote>
<p>Enums have a discriminant. You can assign them explicitly:</p>
<pre class="rust"><code>enum Foo {
Bar = 123,
}</code></pre>
<p>If a discriminant isn’t assigned, they start at zero, and add one for each variant, in order.</p>
<p>You can cast an enum to get this value:</p>
<pre class="rust"><code>let x = Foo::Bar as u32; // x is now 123u32</code></pre>
<p>This only works as long as none of the variants have data attached. If it were <code>Bar(i32)</code>, this is disallowed.</p>
</blockquote></li>
<li><p>Initialization of Swift’s raw-valued enum type is quite similar, and pleasantly so, to Python’s initialization of enums.</p></li>
<li><p>In a surprising change from the usual, Swift’s syntax for binding variable names when pattern matching against an enum is <em>more</em> verbose than Rust’s, requiring the use of either a leading <code>let</code> on the <code>case</code> statement if all the elements are of the same type, or a <code>let</code> in front of each element otherwise:</p>
<pre class="swift"><code>var matchedValue: String
let matchee = 3.14159
switch matchee {
case 3.14159:
matchedValue = &quot;pi&quot;
case _:
matchedValue = &quot;not pi&quot;
}</code></pre>
<p>In Rust, a matched pattern can simply bind its value directly:</p>
<pre class="rust"><code>let matchee = 3.14159;
let matchedValue = match matchee {
3.14159 =&gt; &quot;pi&quot;.to_string(),
_ =&gt; &quot;not pi&quot;.to_string()
};</code></pre></li>
<li><p>Swift has the ability to do recursive enumerations with its <code>indirect</code> type. This is conceptually interesting, but off the top of my head I can’t think of a time when this would have been useful at any point since I started programming seven and a half years ago. The book’s example of a recursive function aliasing arithmetic expressions is fine, but not particularly illuminating to me. I suspect, though, that it might make more sense if I were more familiar with pure functional programming paradigms.</p>
<p><strong>Edit:</strong> a friend <a href="https://alpha.app.net/jws/post/65990633">points out</a>:</p>
<blockquote>
<p>Indirect enums are useful for recursive types in general. There are a lot of these: Lists, trees, and streams are the big ones that come to mind.</p>
</blockquote></li>
<li><p>All those same lines: Rust does <em>not</em> have the ability to have recursive enumerations at present (or recursive <code>struct</code> types, for that matter), at least without heap-allocating with <code>Box</code> along the way. You <em>can</em> construct such a type, in other words, but you have to be explicit about how you’re handling the memory, and it can’t be stack-allocated.</p>
<ul>
<li><p>For an example of a recursive enumeration type (as well as an interesting/hilarious example of how you can easily confuse the compiler if you do this wrong), see <a href="https://users.rust-lang.org/t/recursive-enum-types/2938">this Rust forum post</a>.</p></li>
<li><p>For some discussion on stack- and heap-allocated memory in Rust, I’ll shamelessly promote my Rust podcast, <a href="http://www.newrustacean.com">New Rustacean</a>: take a listen to <a href="http://www.newrustacean.com/show_notes/e005/index.html">e005: Allocate it where?</a></p></li>
</ul></li>
</ul>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-viii.html"><strong>Previous:</strong> Functions, closures, and an awful lot of Swift syntax.</a></li>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-x.html"><strong>Next:</strong> Classes and structs (product types), and reference and value types.</a></li>
</ul>
Chris KrychoMon, 09 Nov 2015 22:20:00 -0500tag:v4.chriskrycho.com,2015-11-09:/2015/rust-and-swift-ix.htmlsoftware developmentlisticlesrustswiftrust-and-swiftCSS Fallback for OpenType Small Capshttp://v4.chriskrycho.com/2015/css-fallback-for-opentype-small-caps.html<p><i class=editorial>I wrote this up as <a href="http://stackoverflow.com/questions/24846264/css-fallback-for-opentype-small-caps/25172932#25172932">a question on Stack Overflow</a> a bit over a year ago. It has continued to get a fair bit of traffic, so I’ve republished it here and cleaned it up a bit.</i></p>
<section id="the-problem" class="level2">
<h2>The Problem</h2>
<p>Over the last year, I’ve worked on <a href="//holybible.com">a site</a> where small caps are important: setting the text of the Bible. In the Old Testament the name of God is transliterated as <code>Lord</code> but in small caps—not “LORD” but <span class="divine-name">Lord</span> (RSS readers will want to click through and see this on my site). However, the state of OpenType small caps support at the moment is… less than optimal. Safari (even up through Safari 9 on El Capitan, from which I am typing this) still doesn’t support the <code>-webkit-font-feature-settings: 'smcp'</code> option, and a lot of the hits for this website will be coming from mobile.</p>
<p>Unfortunately, “graceful degradation” is problematic here: if you specify both <code>font-variant: small-caps</code> and <code>font-feature-settings: 'smcp'</code> in a browser that supports the latter (e.g. Chrome), the <code>font-variant</code> declaration overrides it, so the horribly ugly old-style version still comes into play. (Note: this is as it should be per the <a href="http://www.w3.org/TR/css-fonts-3/#feature-precedence">spec</a>: the <code>font-variant</code> declaration has a higher priority than the <code>font-feature-settings</code> declaration). Given the current implementations of <code>font-variant: small-caps</code>, though—shrunken capitals rather than actual small capitals—the result is that using <code>font-variant: small-caps</code> realists in not-so-gracefully degrading <em>everyone’s</em> reading experience.</p>
<p>In the past, I have exported the small caps as a distinct webfont and specified them directly; see <a href="http://v4.chriskrycho.com/2014/learning-qml-part-1.html">this post</a> for a simple example: the first line of each paragraph is specified that way.</p>
<p>While I <em>can</em> do the same thing here (and at least in theory could deliver a pretty small typeface, since I really only need three characters: <code>o</code>, <code>r</code>, and <code>d</code>), I’d prefer simply to enable sane fallbacks. As noted above, however, that’s not possible. I am <em>open to</em> but would very much prefer to avoid server-side solutions (browser detection, etc.) as a point of complexity that is better to minimize, especially given how rapidly browsers change. How else might one solve this problem, and especially are there existing solutions for it?</p>
<p>In the future, <code>font-variant: small-caps</code> will handle this nicely, as per <a href="http://www.w3.org/TR/css3-fonts/#small-caps">the spec</a> it should display a small-capitals-variant of the typeface if the typeface supplies it. However, at present, <em>no browser supports this</em> (at least, none that I can find!). This means that instead, they all render fake small capitals simply by scaling down actual capitals. The result is typographically unpleasant, and unacceptable on this project.</p>
</section>
<section id="the-solutions" class="level2">
<h2>The Solution(s)</h2>
<p>I spent a considerable amount of time researching this and wrestling with it. After digging around as best I could, the top solutions for now are:</p>
<section id="supports" class="level3">
<h3><code>@supports</code></h3>
<p>Take advantage of the <code>@supports</code> rule in browsers. This is what I initially opted to do on this project.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> You use the rule this way:</p>
<pre class="css"><code>.some-class {
font-variant: small-caps;
}
@supports(font-feature-settings: &#39;smcp&#39;) {
.some-class {
font-variant: normal;
font-feature-settings: &#39;smcp&#39;;
}
}</code></pre>
<p>(I’ve simplified by leaving out the prefixed versions; you’ll need to add the <code>-webkit-</code> and <code>-moz-</code> prefixes to get this actually working.) This has the advantage that support for real small caps and support for the <code>@supports</code> rule are very similar:</p>
<ul>
<li><code>@supports</code>: <a href="http://caniuse.com/#feat=css-featurequeries">Can I Use Feature Queries?</a>: Chrome 31+, Firefox 29+, Opera 23+, Android 4.4+, Safari 9+, Edge 12+, Chrome for Android</li>
<li><code>font-feature-settings</code>: <a href="http://usabilitypost.com/2014/05/10/using-small-caps-and-text-figures-on-the-web/">Using Small Caps &amp; Text Figures on the Web</a>: Chrome, Firefox, IE10+</li>
</ul>
<p>This isn’t perfect: since IE10/11 don’t implement <code>@supports</code>, you miss one browser—sort of. At this point, IE is a legacy browser, and Edge has had <code>@supports</code> available from the start. Thus, this gets you most of the way there, and it should be future-facing: this should progressively enhance the site nicely. The normal (bad, but functional) small caps are displayed in the meantime, and when browsers eventually get around to using OpenType small caps by default for <code>font-variant: small-caps</code>, this will continue to work just fine. It’s “progressive enhancement” and it’ll work nicely for most purposes.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
</section>
<section id="typeface-subsetting" class="level3">
<h3>Typeface subsetting</h3>
<p>As mentioned above, one can create a subset of the typeface that includes only small capitals. This is what I have done for the small caps on this site; see the example in the first paragraph.</p>
<p>To pull this off, you’ll need to start by subsetting the typeface. You can do this manually with a font tool, or (the simpler way) you can use FontSquirrel’s custom subsetting tool in their <a href="http://www.fontsquirrel.com/tools/webfont-generator">webfont generator</a>. (<strong><em>Note:</em></strong> You <em>must</em> check the license and confirm that the typeface in question allows this kind of modification. See below.) In the web font generator, first upload the file you wish to modify. Then choose the <strong>Expert</strong> radio button. Most of the settings you can leave as they are; they’re good sane defaults. Midway down the page you’ll see <strong>OpenType Flattening</strong> options. Here, select only “Small Caps”. Run the generator. The result will be a complete replacement of the normal lowercase letters with the small caps set.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<p>In that case, you can simply apply a style to the elements you want to have small capitals, e.g.:</p>
<pre class="css"><code>.divine-name {
font-family: &#39;my_typeface_smcp&#39;, &#39;my_typeface&#39;, serif;
}</code></pre>
<p>The major advantage to this approach is consistency: that typeface is going to display on every browser out there, back to IE5.5, as long as you deliver it correctly using the various hooks required by <code>@font-face</code>.</p>
<p>There are a few disadvantages to this approach, though:</p>
<ol type="1">
<li><p>It means delivering another font file. In my case, this would be an acceeptably low size (since I actually only need four characters), but it’s still something to consider in general. It is in any case another HTTP request, which is going to further slow the page load time or at least give you some flash of unstyled text when it reloads.</p></li>
<li><p>It may violate the licenses of the typefaces in question. For at least one of the fonts I used on this project, it <em>does</em>: the license explicitly forbids rebuilding the font using tools like FontSquirrel. (FontSquirrel was the tool I used for this approach before, and it works quite well.) This is a make-or-break issue for using a subset of a typeface to accomplish the goal. That being said, if you have a good reason to do it, you may be able to get support from the vendor (especially if they’re a small shop). For the project that prompted this question, I was able to do just that with a nice email—the designer is a great guy.</p></li>
</ol>
<p>The other major reason not to do it this way is that it has a significantly higher maintenance cost. If at any point you need to change or update the typeface, you have to go through the subsetting process all over again. By contrast, the first option will simply <em>work</em>, though admittedly not as pleasantly as one might hope, and will not only continue to work but will actually improve over time as browsers increase their implementation of the CSS3 standard.</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2>Conclusion</h2>
<p>I opted for the second solution on HolyBible.com—typography was one of the driving differentiators for the site, so I prioritized it and did the necessary legwork for it. In general, though, the first option should work well for most sites. In any case, both ways work, though the first one is a <em>better</em> example of progressive enhancement. And we can all look forward to the day when true small-caps support is available on every browser, right?</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>For various reasons (especially see note 2 below), I actually opted for the second approach outlined here, which is the same approach I was trying to avoid. Alas.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Issues remain: even in the latest Chrome (46 as of the time of this post), using the <code>font-feature-settings: 'smcp'</code> approach has some issues. For example, if you turn on <code>letter-spacing</code> (a fairly common <a href="http://practicaltypography.com/letterspacing.html">recommendation</a> for small caps), the small caps will revert to normal lowercase letters.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>From the FontSquirrel blog post that introduced the feature:</p>
<blockquote>
<p>If you have a font with OpenType features, you can now flatten some of them into your webfont. For instance, some fonts have small caps built in, but they are completely inaccessible in a web browser. By selecting the “Small Cap” option, the Generator will replace all the lowercase glyphs with the small cap variants, giving you a small cap font. Please note that not all OpenType features are supported and if the font lacks OpenType features, using these options won’t create them.</p>
</blockquote>
<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></li>
</ol>
</section>
Chris KrychoMon, 19 Oct 2015 20:00:00 -0400tag:v4.chriskrycho.com,2015-10-19:/2015/css-fallback-for-opentype-small-caps.htmldesignsoftware developmenttypographyRust and Swift (viii)http://v4.chriskrycho.com/2015/rust-and-swift-viii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past few months. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<hr />
<ul>
<li><p>Rust and Swift handle function definition fairly similarly, at least for basic function definitions. In fact, for most basic functions, the only difference between the two is the keyword used to indicate that you’re declaring a function: <code>fn</code> in Rust and <code>func</code> in Swift.</p></li>
<li><p>Likewise, both return an empty tuple, <code>()</code>, called the <em>unit type</em> in Rust or <code>Void</code> in Swift. Note, however, that this unit/<code>Void</code> type is <em>not</em> like C(++)’s <code>void</code> or Java’s <code>null</code>: you cannot coerce other types to it; it really is an empty tuple.</p></li>
<li><p>Type declarations on functions are basically identical for simple cases, though they vary into the details as you get into generics and constraints in generics.</p></li>
<li><p>I have no idea why the Swift team chooses to represent function names like this: <code>function_name(_:second_param:third_param:&lt;etc.&gt;)</code>. Perhaps it’s a convention from other languages I’m simply unfamiliar with, but it seems both odd and unhelpful: eliding the first parameter name obscures important information. Also, why use colons for the delimiter?</p>
<p><strong>Edit:</strong> I’m informed via Twitter and App.net that this reflects how function names work in Objective C, and derives ultimately from Smalltalk.</p></li>
<li><p>Being able to name the items in a returned type in Swift is quite handy; it’s something I have often wanted and had to work around with dictionaries or other similar types in Python.</p></li>
<li><p>We’ll see how I feel once I’ve been writing both for a while, but initially I <em>strongly</em> prefer Rust’s more-obvious (if also somewhat longer) <code>-&gt; Option&lt;i32&gt;</code> to return an optional integer to Swift’s <code>-&gt; Int?</code>. I am quite confident that I’ll miss that trailing <code>?</code> somewhere along the way.</p></li>
<li><p>I’m sure there’s a reason for Swift’s internal and external parameter names and the rules about using <code>_</code> to elide the need to use keyword arguments (but automatically eliding the first one) and so on… but I really can’t see the utility, overall. It seems like it would be better just to have Python-like args and keyword args.</p></li>
<li><p>That’s doubly so given that Swift’s rules for default-valued parameters map exactly to Python’s: they need to go at the end, after any parameters which don’t have default values.</p></li>
<li><p>Swift’s variadic parameters are nice—though of course limited, since if you have more than one, the compiler may not know how to resolve which destination parameter a given argument belongs with. (I imagine the compiler <em>could</em> be extended to be able to handle multiple variadic parameters as long as they were all of different types, but that’s probably not worth the work or the potential confusion it would introduce.) In any case, it’s a small nicety that I do wish Rust had.</p></li>
<li><p>Swift’s variable parameters are… interesting. I can see the utility, sort of, but (probably from years of habit with C and Python and pass-by-reference types), it’s just not a pattern that makes a lot of sense to me right now. No doubt I’ll get used to them in idiomatic Swift, but while Rust doesn’t have a similar feature, I suspect I won’t miss it.</p></li>
<li><p>In/out parameters—that is, mutable pass-by-reference types—are available in both languages. The syntax is <em>very</em> different here, as are the semantics.</p>
<p>Swift has the <code>inout</code> keyword, supplied before a parameter definition:</p>
<pre class="swift"><code>func adds4ToInput(inout num: Int) {
num += 4;
}</code></pre>
<p>Rust has instead a variation on every other type definition, declaring the type in this case to be a mutable reference:</p>
<pre class="rust"><code>fn adds_4_to_input(num: &amp;mut i32) {
num += 4;
}</code></pre>
<p>As usual, in other words, Swift opts to use new syntax (in this case, a dedicated keyword) while Rust opts to use the same syntax used everywhere else to denote a mutable reference. In fairness to Swift, though, this is something of a necessity there. From what I’ve seen so far, Swift generally doesn’t (and perhaps can’t?) do pointers or references explicitly (though of course it’s handling lots of things that way under the covers); arguments to functions are a special case, presumably present primarily for interoperability with Objective-C.</p></li>
<li><p>Swift’s function type definitions, as used in e.g. function parameter definitions, are quite nice, and reminiscent of Haskell in the best way. Rust’s are pretty similar, and add in its <code>trait</code> usage—because functions types <em>are</em> <code>trait</code>s. Once again, I really appreciate how Rust builds more complicated pieces of functionality on lower-level constructs in the language. (Swift may be doing similar under the covers, but the Swift book doesn’t say.)</p></li>
<li><p>Again, though, the downside to Rust’s sophistication is that it sometimes bundles in some complexity. Returning a function in Swift is incredibly straightforward:</p>
<pre class="swift"><code>func getDoubler() -&gt; (Int) -&gt; Int {
func doubler(number: Int) -&gt; Int {
return number * 2
}
return doubler
}
func main() {
let doubler = getDoubler()
println(&quot;\(doubler(14))&quot;) // -&gt; 28
}</code></pre>
<p>Doing the same in Rust is a bit harder, because—as of the 1.3 stable/1.5 nightly timeframe—it requires you to explicitly heap-allocate the function. Swift just takes care of this for you.</p>
<pre class="rust"><code>fn get_doubler() -&gt; Box&lt;Fn(i32) -&gt; i32&gt; {
fn doubler(number: i32) -&gt; i32 {
number * 2
}
Box::new(doubler)
}
fn main() {
let doubler = get_doubler();
println!(&quot;{:}&quot;, doubler(14)); // -&gt; 28
}</code></pre>
<p>If you understand what’s going on under the covers here, this makes sense: Rust normally stack-allocates a function in a scope, and therefore the <code>doubler</code> function goes out of scope entirely when the <code>get_doubler</code> function returns if you don’t heap-allocate it with <code>Box::new</code>.</p></li>
<li><p>In both languages, closures and “ordinary” functions are variations on the same underlying functionality (as it should be). In Rust’s case, functions and closures both implement the <code>Fn</code> trait. In Swift’s case, named functions are a special case of closures.</p></li>
<li><p>The Swift syntax for a closure is, well, a bit odd to my eye. The basic form is like this (with the same “doubler” functionality as above):</p>
<pre class="swift"><code>{ (n: Int) -&gt; Int in return n * 2 }</code></pre>
<p>For brevity, this can collapse down to the shorter form with types inferred from context, parentheses dropped and the <code>return</code> keyword inferred from the fact that the closure has only a single expression (note that this wouldn’t be valid unless in a context where the type of <code>n</code> could be inferred):</p>
<pre class="swift"><code>{ n in n * 2 }</code></pre>
<p>The simplicity here is nice, reminiscent in a good way of closures/lambdas in other languages.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> The fact that it’s a special case is less to my taste.</p></li>
<li><p>Rust’s closure syntax is fairly similar to Swift’s brief syntax. More importantly, there’s no special handling for closures’ final expressions. Remember: the final expression of <em>any</em> block is always returned in Rust.</p>
<pre class="rust"><code>|n| n * 2</code></pre>
<p>If we wanted to fully annotate the types, as in the first Swift example, it would be like so:</p>
<pre class="rust"><code>|n: i32| -&gt; i32 { n * 2 }</code></pre></li>
<li><p>There are even <em>more</em> differences between the two, because of Rust’s ownership notion and the associated need to think about whether a given closure is being borrowed or moved (if the latter, explicitly using the <code>move</code> keyword).</p></li>
<li><p>Swift has the notion of shorthand argument names for use with closures.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> The arguments to a closure get the default names <code>$0</code>, <code>$1</code>, etc. This gets you even <em>more</em> brevity, and is quite convenient in cases where closures get used a lot (<code>map</code>, <code>sort</code>, <code>fold</code>, <code>reduce</code>, etc.).</p>
<pre class="swift"><code>{ $0 * 2 }</code></pre></li>
<li><p>If that weren’t enough, Swift will go so far as to simply reuse operators (which are special syntax for functions) as closures. So a closure call could simply be <code>+</code> for a function expecting a closure operating on two numbers; Swift will infer that it needs to map back to the relevant method definition on the appropriate type.</p></li>
<li><p>The upside to this is that the code can be incredibly brief, and—once you’re used to it, at least—still fairly clear. The downside to this is yet <em>more</em> syntax for Swift, and the ever-growing list of things to remember and ways to write the same thing I expect will lead to quite a bit of instability as the community sorts out some expectations for what is idiomatic in any given instance.</p></li>
<li><p>And if that weren’t enough, there is more than one way to supply the body of a closure to a Swift function that expects it: you can supply a block (<code>{ /* closure body */ }</code>) <em>after</em> the function which expects it. Yes, this can end up looking nearly identical to the form for declaring a function:</p>
<pre class="swift"><code>someFunctionExpectingAnIntegerClosure() { n * 2 }</code></pre>
<p>But you can also drop the parentheses if that’s the only argument.</p>
<pre class="swift"><code>someFunctionExpectingAnIntegerClosure { n * 2 }</code></pre></li>
<li><p>In terms of the <em>mechanics</em> of closures, and not just the syntax, the one significant difference between Rust and Swift is the same one we’ve seen in general between the two languages: Swift handles the memory issues automatically; Rust makes you be explicit about ownership. That is, as noted above about the closures themselves, in Rust you may have to <code>move</code> ownership to get the expected behavior. Both behave basically like closures in any other language, though; nothing surprising here. Both also automatically copy values, rather than using references, whever it makes sense to do so.</p></li>
<li><p>Swift autoclosures allow for lazy evaluation, which is neat, but: <em>yet more syntax</em>! Seriously. But I think all its other closure syntaxes <em>also</em> allow for lazy evaluation. The only reason I can see to have the special attribute (<code>@autoclosure</code>) here is because they added this syntax. And this syntax exists so that you can call functions which take closures as if they <em>don’t</em> take closures, but rather the argument the closure itself takes. But of course, this leads the Swift book to include the following warning:</p>
<blockquote>
<p><strong>Note:</strong> Overusing autoclosures can make your code hard to understand. The context and function name should make it clear that the evaluation is being deferred.</p>
</blockquote>
<p>Yes, care needed indeed. (Or, perhaps, you could just avoid adding more special syntax that leads to unexpected behaviors?)</p></li>
<li><p>Good grief. I’m tired now. That’s a half-dozen variants on <em>closure syntax</em> in Swift.</p></li>
<li><p>Remember: there’s still just one way to write and use a closure in Rust.</p></li>
<li><p>This takes me back to something I noticed <a href="/2015/rust-and-swift-ii.html">early on</a> in my analysis of the two languages. In Swift, there’s nearly always more than one way to do things. In Rust, there’s usually one way to do things. Swift prefers brevity. Rust prefers to be explicit. In other words, Swift borrows more of its philosophy from Perl; Rust more from Python.</p></li>
<li><p>I’m a Python guy, through and through. Perl drives me crazy every time I try to learn it. You could guess (even if you hadn’t already seen) where this lands me between Rust and Swift.</p></li>
</ul>
<p>This post is incredibly long, but I blame that on the (frankly incredible) number of variants Swift has on the same concept.</p>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vii.html"><strong>Previous:</strong> Pattern matching and the value of expression blocks.</a></li>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-ix.html"><strong>Next:</strong> Sum types (<code>enum</code>s) and more on pattern matching.</a></li>
</ul>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Compare the closure syntaxes especially in Ruby and ES6+.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>For a similar example in another up-and-coming language, see <a href="http://elixir-lang.org/getting-started/modules.html#function-capturing">Elixir</a>, which does almost exactly the same but with <code>&amp;</code> in place of <code>$</code>.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSun, 18 Oct 2015 11:50:00 -0400tag:v4.chriskrycho.com,2015-10-18:/2015/rust-and-swift-viii.htmlsoftware developmentlisticlesrustswiftrust-and-swiftRust and Swift (vii)http://v4.chriskrycho.com/2015/rust-and-swift-vii.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<hr />
<ul>
<li><p>Both Rust and Swift have <em>pattern-matching</em>, and with what appears to be fairly similar basic behavior. (I touched on this briefly in my <a href="/2015/rust-and-swift-i.html">first post in the series</a>.) In Rust this goes under the <code>match</code> construct, with matches specified like <code>&lt;pattern&gt; =&gt; &lt;expression|statement&gt;</code>, optionally with guards specified with <code>if</code> expressions. In Swift, patterns are matched using the <code>switch</code> construct, with matches specified like <code>case &lt;pattern&gt;: &lt;expression|statement&gt;</code>, optionally with guards specified with <code>where</code> expressions. (<code>where</code> is also used in Rust, but for generic constraints, not pattern match guards.)</p></li>
<li><p>Both languages allow you to bind names to a matched pattern: Swift with <code>case let &lt;name&gt;</code> and Rust simply by using the name in a normal destructuring expression as part of the match definition.</p>
<p><strong>Edit:</strong> that’s not <em>quite</em> right. In Rust, you use the <code>@</code> operator with the variable name you want to bind in the match.</p>
<p><strong>Edit the second:</strong> I was mixed up, because Rust actually has <em>both</em> of those options. You can either match directly, e.g. when getting the value of an <code>Option</code> type: <code>Some(value)</code> as the pattern will bind <code>value</code>. But if you need to bind a specific part of more complicated data structure, the <code>@</code> operator is present to let you do it in a fairly straightforward way.</p></li>
<li><p>Both languages allow for the use of <code>_</code> as a “wildcard” in match definitions. Since match definitions in Rust use the patterns directly, the equivalent of Swift’s C-like <code>default</code> is simply a wildcard match pattern (<code>_ =&gt; &lt;-expression|statement&gt;</code>).</p></li>
<li><p>One significant difference: like its <code>if</code> blocks, Rust’s <code>match</code> blocks are expressions, so they can be assigned. I.e., you can write this:</p>
<pre class="rust"><code>let test = 5u32;
let description = match test {
0..10 =&gt; &quot;less than ten&quot;,
_ =&gt; &quot;greater than ten&quot;,
}
println!(&quot;{?:}&quot;); // &quot;less than ten&quot;</code></pre>
<p>Swift doesn’t let you do this; the same thing there would be written like this:</p>
<pre class="swift"><code>let test: UInt32 = 5
var description: String
switch test {
case 0..&lt;10:
description = &quot;less than ten&quot;
default:
description = &quot;greater than ten&quot;
}
println(&quot;\(description)&quot;)</code></pre></li>
<li><p>Both languages have <code>break</code> statements, but in Rust they’re only used in loop constructs, while Swift (like C) uses them to escape <code>case</code>s as well. The Swift book gives an example of one place they’re necessary in a <code>switch</code>: to match a case and do nothing there (e.g. <code>default: break</code>). In Rust, you would simply supply an empty block for that scenario (e.g. <code>_ =&gt; {}</code>).</p></li>
<li><p>Correctly, both languages force you to match exhaustively on relevant patterns. If you’re matching an enumerated type, for example, you must handle every enumerated value. You can of course do this with wildcard patterns or with Swift’s <code>default</code>, but the good thing is that both languages will refuse even to compile if a given pattern isn’t matched.</p></li>
<li><p>Swift’s default behavior around its <code>switch</code> statements is sane: it does <em>not</em> automatically fall through into the next statement. It does let you do this, without checking the condition on the next statement (as in C), using the <code>fallthrough</code> keyword. Rust, by contrast, simply doesn’t allow this at all.</p></li>
<li><p>Both languages supply named control statements (loops, etc.), with slightly different syntax for naming them. Rust’s, curiously, shares its syntax with lifetime definitions—more on those in a future post.</p></li>
<li><p>I don’t believe Rust has anything quite like Swift’s <code>guard</code>s, which allow you to leave normal or expected control flow in the main body of a block, with a secondary block for cases where the <code>guard</code> isn’t matched. This isn’t a huge deal, but it does fit as a nice convenience into the typical <code>if let</code> pattern in Swift. Basically, it just lets you elide an empty <code>if</code> block and supply only the <code>else</code> block.</p>
<p><strong>Edit:</strong> a friend <a href="https://alpha.app.net/jws/post/64804111">points out</a> that Swift <code>guard</code>s also require you to exit the current scope, so it’s unambiguous what you’re doing if you use them.</p></li>
</ul>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vi.html"><strong>Previous:</strong> Collection types and the difference between syntax and semantics.</a></li>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-viii.html"><strong>Next:</strong> Functions, closures, and an awful lot of Swift syntax.</a></li>
</ul>
Chris KrychoSat, 19 Sep 2015 15:00:00 -0400tag:v4.chriskrycho.com,2015-09-19:/2015/rust-and-swift-vii.htmlsoftware developmentlisticlesrustswiftrust-and-swiftRust and Swift (vi)http://v4.chriskrycho.com/2015/rust-and-swift-vi.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<hr />
<p>It kind of feels like this summarizes a <em>lot</em> of things about the overall design of Swift:</p>
<blockquote>
<p>Although the two forms are functionally identical, the shorthand form is preferred and is used throughout this guide when referring to the type of an array. —<em>The Swift Programming Language (Swift 2 Prerelease)</em></p>
</blockquote>
<p>The documentation for the various types in Rust’s <code>std::collections</code> module is hilarious and great. Highly recommended.</p>
<p>One thing that jumped out at me reading this chapter of the Swift book (though I don’t think it’s been explicitly discussed yet): Rust doesn’t have named parameters; Swift does. There are good reasons for that in both cases, but I suspect this is one of the small details I’ll miss the most in Rust. I’ve been spoiled by Python.</p>
<p>Swift’s <code>Array</code> type is analogous to Rust’s <code>Vec</code> type (usually created with the <code>vec!</code> macro), <em>not</em> its <code>Array</code> type. Rust <code>Vec</code>s and Swift <code>Array</code>s are dynamically sized and created on the heap, whereas Rust’s <code>Array</code>s are statically sized and created on the stack. Syntax for creating <code>Array</code>s in both languages is quite similar (though the results are different):</p>
<ul>
<li>Swift:
<ul>
<li>Fixed size: <code>let an_array: [Int] = [1, 2, 3]</code></li>
<li>Variable size: <code>var an_array = [1, 2, 3]</code></li>
</ul></li>
<li>Rust:
<ul>
<li>Array: <code>let an_array: [i32, 3] = [1, 2, 3];</code></li>
<li>Vector: <code>let a_vector: Vec&lt;i32&gt; = vec![1, 2, 3];</code></li>
</ul></li>
</ul>
<p>That’s the long form, of course; both languages have type inference, so you’d rarely write it like that. The usual form would be with the type in all of those cases:</p>
<ul>
<li>Swift:
<ul>
<li>Fixed size: <code>let an_array = [1, 2, 3]</code></li>
<li>Variable size: <code>var an_array = [1, 2, 3]</code></li>
</ul></li>
<li>Rust:
<ul>
<li>Array: <code>let an_array = [1, 2, 3];</code></li>
<li>Vector: <code>let a_vector = vec![1, 2, 3];</code></li>
</ul></li>
</ul>
<p>Rust also adds the concept of “slices,” which provide access to segments of arrays, and are heap-allocated as pointers to a given item in the array and a length (number of elements) included.</p>
<p><code>Array</code> operations in Swift are all pretty reasonable, and surprisingly descriptive. They remind me in a good way of Python’s <code>list</code> methods.</p>
<p>There are a <em>lot</em> of <a href="http://doc.rust-lang.org/stable/std/vec/struct.Vec.html">ways to interact with <code>Vec</code>s in Rust</a>. (That’s not a bad thing.) A bit surprising to me was the absence of an <code>enumerate</code> method, on <code>Vec</code> itself, but then I discovered that it exists in the <code>IntoIter</code> struct in the same module, which fully implements the <code>Iterator</code> <code>trait</code>. As a result, it has an <code>enumerate</code> function returning an <code>Enumerate</code> <code>struct</code> instance. (Under the covers, I suspect Swift <code>Array</code>s just implement an <code>Iterable</code> <code>protocol</code>, which is similar to this approach in some ways.)</p>
<p>This makes a point I’m coming back to fairly often: Rust doesn’t necessarily put everything on a single object definition, but rather into a set of related <code>struct</code> or <code>enum</code> types and <code>trait</code>s. This is really powerful, but it’s going to take some mental adjustment. In this way, Swift’s structure and semantics are much more like the languages I’m used to than Rust’s are (but even there, the use of <code>protocols</code> gives it considerable new flexibility).</p>
<p>Note that I said <em>semantics</em>, not syntax. Swift and Rust are a great example of how very similar syntax can mask differences in semantics. (For another such example, compare JavaScript’s syntax and semantics to Java’s: they’re superficially similar syntactically, and light years apart semantically.)</p>
<p>Swift’s <code>Set</code> type and Rust’s roughly analogous <code>HashSet</code> both have a <code>contains</code> method which behaves much like Python’s <code>in</code> keyword. Indeed, and perhaps unsurprisingly, the two types implement many of the same methods in general. This is perhaps to be expected given that the language around sets (as a mathematical concept being mapped down into a representation in a program) is quite standardized.</p>
<p>Because of their stricter typing systems, both Rust and Swift require you to specify the types used in their mapping constructs (Rust has <code>HashMap</code> and Swift has <code>Dictionary</code>), though of course both can infer this as well in certain cases. At the most basic level, you can’t use arbitrary (hashable) types as keys in mixed fashion like you can in e.g. Python’s <code>dict</code> type, but in practice this shouldn’t matter, for two reasons:</p>
<ol type="1">
<li>It’s generally inadvisable to use different types for keys in the same dictionary anyway. To me, at least, that usually indicates the need to step back and think more carefully about the types and data structures I’m using.</li>
<li>For the occasional case where it <em>is</em> appropriate, I wonder if you could declare the type as generic in either Rust or Swift. I’m putting this down as a TODO item for myself to find out!</li>
</ol>
<p>I really wish that Swift used the Python-style curly-brace delimited syntax (<code>{'key': 'value'}</code>) for its dictionary literal initializers. I can see, from a syntax reason, why it doesn’t: that would overload the block syntax (which Python can avoid because it’s white-space delimited). But it’s <em>really</em> convenient.</p>
<p>Along similar lines, I can see why the Swift designers chose to make all iterables have literal initializers using braces (<code>[...]</code>); it makes parsing fairly straightforward. However, the result is that it’s pretty difficult to see at first glance what you’re dealing with. It could quite easily be an <code>Array</code>, a <code>Set</code>, or a <code>Dictionary</code>.</p>
<p>This highlights a too-little-appreciated aspect of programming language design: <em>readability</em>. However much we programmers enjoy writing code, the reality is that we will all spend a great deal of our time—probably even a majority of it—reading it instead. Thus, while we should care about conveniences for writing code, and being overly verbose can be a pain, we should also concern ourselves with the ease of comprehending code when it is read, and the syntax and conventions a language embraces are a big part of this.</p>
<p>The <code>Dictionary</code> type in Swift is a pretty close analog to Python’s <code>dict</code>, right down to several of the method names. the same is true of Rust’s <code>HashMap</code>. That’s not a bad thing by any stretch of the imagination.</p>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-v.html"><strong>Previous:</strong> The value (and challenge) of learning languages in parallel.</a></li>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vii.html"><strong>Next:</strong> Pattern matching and the value of expression blocks.</a></li>
</ul>
Chris KrychoSat, 19 Sep 2015 09:00:00 -0400tag:v4.chriskrycho.com,2015-09-19:/2015/rust-and-swift-vi.htmlsoftware developmentrustswiftrust-and-swiftRust and Swift (v)http://v4.chriskrycho.com/2015/rust-and-swift-v.html<p><i class="editorial">I am reading through the Swift book, and comparing it to Rust, which I have also been learning over the past month. As with the other posts in this series, these are off-the-cuff impressions, which may be inaccurate in various ways. I’d be happy to hear feedback! Note, too, that my preferences are just that: preferences. Your tastes may differ from mine. <a href="/rust-and-swift.html">(See all parts in the series.)</a></i></p>
<hr />
<p>I’ve been working on learning Swift over the past couple weeks, and had spent the month prior to that doing a deep first dive on Rust. This kind of approach, learning two languages basically at the same time, is entirely new to me, and for good reason. Programming languages are not trivial to learn, and to learn them meaningfully one must practice with them a great deal.</p>
<p>I’m doing this largely of necessity. I’m hoping to build an application with a very capable, performant cross-platform core language (Rust), but planning to ship a native OS X app (first) when all is said and done. My desire to make the core libraries portable rules out Swift immediately. To be frank, so does the fact that it’s an Apple language: I am happy to use Apple’s tools on its platform, but I don’t want to shackle myself to their choices in the long run. Too, having good Rust experience is likely to be valuable in many other contexts.</p>
<p>So I need to learn both.</p>
<p>And, while I wouldn’t ordinarily recommend this course of action—indeed, unless you already have a fair bit of programming experience and already know several languages, I’d actively recommend against it—I’m finding it enormously profitable. The languages have been designed in roughly the same time frame, cite many of the same influences, and overlap substantially in terms of audience and goals. Yet they are, as this series has already highlighted, quite different languages in many ways.</p>
<p>Learning them in parallel is helping me see the trade-offs each one has made, and force me to think about <em>why</em> they differ in the ways they do. In particular, I think I have a much better idea what’s going on “under the covers” in each language and therefore know what to expect of them better. This, in turn, has dramatically deepened my grasp of the languages relative to the amount I’ve been looking at them, compared to previous language-learning efforts. (It also helps that I’ve already learned a number of languages, of course, and that I’ve been pushing my brain into the learning-programming-languages space via reading about Haskell, functional patterns in JavaScript, and so on this year.)</p>
<p>I have a long way to go in both languages, of course. Reading on nights and weekends, and the little bit of playing I’ve been able to do with each of them, is no replacement for just sinking my teeth into a project and finding the pain points. Nonetheless, I’m really glad to be learning these two languages <em>together</em>. If you’re up for a challenge, try it sometime! You’ll be surprised how much you learn.</p>
<hr />
<ul>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-iv.html"><strong>Previous:</strong> Language design tradeoffs, highlighted by string manipulation.</a></li>
<li><a href="http://v4.chriskrycho.com/2015/rust-and-swift-vi.html"><strong>Next:</strong> Collection types and the difference between syntax and semantics.</a></li>
</ul>
Chris KrychoSat, 12 Sep 2015 13:45:00 -0400tag:v4.chriskrycho.com,2015-09-12:/2015/rust-and-swift-v.htmlsoftware developmentrustswiftrust-and-swiftprogramming languagesIf-expressions in Rusthttp://v4.chriskrycho.com/2015/if-expressions-in-rust.html<p>I love the fact that all <code>if</code> statements in Rust are expressions. It gives you a great deal of expressitivity in the language.</p>
<p>Let’s contrast with Python (which I love, for the record). In Python, you can do something like this:</p>
<pre class="python"><code>some_condition = True
if some_condition:
a_value = &quot;Yeah!&quot;
else:
a_value = &quot;Oh, sads.&quot;</code></pre>
<p>Those are <em>statements</em> in the body of the <code>if</code>/<code>else</code> block; you can’t assign the block itself to <code>a_value</code>. However, like C, C++, Java, etc., Python does provide an <em>expression</em>-type conditional, a ternary expression.</p>
<p>So you can also do this:</p>
<pre class="python"><code>some_condition = True
a_value = &quot;Yeah&quot; if some_condition else &quot;Oh, sads.&quot;</code></pre>
<p>This expression form of the <code>if</code> block is what all Rust <code>if</code> blocks are. So in Rust, the normal long form is:</p>
<pre class="rust"><code>let some_condition = true;
let a_value = if some_condition {
&quot;Yeah!&quot;
}
else {
&quot;Oh, sads.&quot;
}</code></pre>
<p>(You could also write this with a <code>let mut a_value</code> and then set its value inside the conditional blocks, but that’s not at all good form in Rust.)</p>
<p>And of course, you can shorten that rather nicely where the expressions are brief enough:</p>
<pre class="rust"><code>let some_condition = true;
let a_value = if some_condition { &quot;Yeah!&quot; } else { &quot;Oh, sads.&quot; }</code></pre>
<p>But this gets really nice when you have more complicated work to do in a Rust conditional. It doesn’t matter how many things going on inside an <code>if</code> expression; it’s still an expression. As such, you can also write this:<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<pre class="rust"><code>let some_condition = true;
let a_value = if some_condition {
let the_answer = 42;
let theme = &quot;Take my love, take my land...&quot;;
&quot;Yeah!&quot; // An expression!
}
else {
let the_question = &quot;What do you get when you multiply six by nine?&quot;;
let song = &quot;You can&#39;t take the sky from me!&quot;;
&quot;Oh, sads.&quot; // An expression!
}</code></pre>
<p>Obviously this is totally contrived and silly; the point is that no matter what the internals are, <code>if</code> blocks are expressions, and their final expressions can be assigned like any other.</p>
<hr />
<p>As a note: I got here because I was originally thinking you couldn’t do a one-liner like you can in Python. As shown above, that’s totally false, and in fact the Rust version is much more capable than Python’s, because you don’t need a dedicated ternary when all <code>if</code> blocks are expressions. Rust used to have a C-style ternary (<code>&lt;condition&gt; ? &lt;value if true&gt; : &lt;value if false&gt;</code>) but it was <a href="https://github.com/rust-lang/rust/issues/1698">removed</a> during the lead-up to the 1.0 release—a decision I wholeheartedly affirm.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Note that under normal conditions the compiler won’t actually accept this because of the unused names.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 12 Sep 2015 11:05:00 -0400tag:v4.chriskrycho.com,2015-09-12:/2015/if-expressions-in-rust.htmlsoftware developmentprogramming languagesrustpythonHTML5 Location, <base>, and SVGhttp://v4.chriskrycho.com/2015/html5-location-base-and-svg.html<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>
<p>I was surprised to find the culprit: the <code>&lt;base&gt;</code> tag. If you don’t know what the <code>&lt;base&gt;</code> tag is, you’re 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>
<p>So what went wrong? How do these two things play together?</p>
<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>
<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;
&lt;symbol id=&quot;logo-shape&quot; viewBox=&quot;0 0 256 256&quot;&gt;
&lt;title&gt;Logo&lt;/title&gt;
&lt;desc&gt;The HolyBible.com logo: sunrise breaking over an open book (the Bible).&lt;/desc&gt;
&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;
&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;
&lt;/symbol&gt;
&lt;/svg&gt;
&lt;!-- somewhere else on the page --&gt;
&lt;svg&gt;
&lt;use xlink:href=&quot;#logo-shape&quot;&gt;&lt;/use&gt;
&lt;/svg&gt;</code></pre>
<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>
<pre class="html"><code>&lt;base href=&quot;/&quot;&gt;</code></pre>
<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’s 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’re at a URL that <em>isn’t</em> the base route, anchor links don’t 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—not exactly a good idea, given that it would entail an awful lot of changes if the base URL were ever changed.</p>
<p>What if, instead, we did this?</p>
<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>
<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>
<p>But… then you’ll navigate to another page, and Firefox will be back to not working.</p>
<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’d 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’s by no means obvious why you should do it this way, and certainly no mention of SVG! This might not seem odd to you… 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>
<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’s what you have to do (and therefore that’s what I’m doing).</p>
<p>Fun times, right?</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>The closest it gets is this reference:</p>
<blockquote>
<p>Links that only contain a hash fragment (e.g. <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>
</blockquote>
<p>Even this, however, only <em>hints</em> at the root of the SVG issue.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 20 Jun 2015 10:30:00 -0400tag:v4.chriskrycho.com,2015-06-20:/2015/html5-location-base-and-svg.htmlsoftware developmentangularjsjavascriptHow to Build a Single-Page App API Righthttp://v4.chriskrycho.com/2015/how-to-build-a-single-page-app-api-right.html<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—and in truth, I actually didn’t 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’t be “all right, most of the time.” It should be “really well, all the time.” 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>
<section id="the-challenge" class="level2">
<h2>The challenge</h2>
<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>
<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’t.</em> I learned this the hard way.)</p>
<section id="the-mistake" class="level3">
<h3>The mistake</h3>
<p>Here’s 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. <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>
<p>This works. It’s exactly what I did on HolyBible.com, in fact. But it’s <em>slow</em>.</p>
<p>Don’t 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’t include any content</em>.</p>
<p>I <em>hate</em> this. That’s 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>
</section>
<section id="the-solution" class="level3">
<h3>The solution</h3>
<p>Don’t 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’s 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—in fact, it matters a <em>lot</em>.</p>
<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—in 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>
<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>
<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’ve just seen why it isn’t, Moreover, if you have any logic that needs to be in place—in our example here, a Bible reference parser, for example, to decide what content should be supplied—you 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>
</section>
</section>
<section id="so-what" class="level2">
<h2>So what?</h2>
<p>This approach has two big advantages over the catch-all approach that was frequently recommended in e.g. Angular SPA tutorials I read.</p>
<ol type="1">
<li><p>It’s <em>progressive enhancement</em>. If the JavaScript fails, or the user has it disabled, or it fails to load because it’s 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>
<li><p>It’s <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’t have to wait to see something useful until the JavaScript framework spins up.</p></li>
</ol>
<p>It’s 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’s equally applicable to AngularJS with ExpressJS, Backbone with Rails, Ember with Django, Aurelia with Phoenix, or any other combination you come up with.</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<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’m writing here by doing it <em>wrong</em>.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<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’s another post for another day, though.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoTue, 09 Jun 2015 22:16:00 -0400tag:v4.chriskrycho.com,2015-06-09:/2015/how-to-build-a-single-page-app-api-right.htmlsoftware developmentjavascriptPython Enums, ctypes.Structures, and DLL exportshttp://v4.chriskrycho.com/2015/ctypes-structures-and-dll-exports.html<p>For one of my contracts right now, I’m writing a <code>ctypes</code> Python interface to existing C code. I got stuck and confused for quite a while on getting the interface to a given function to build correctly, and along the way had to try to understand the <code>from_param</code> class method. The official docs are… fine… but the examples provided don’t cover the most common/basic use case: defining a simple, <em>non-ctypes</em> data type as an argument to a DLL-exported function.</p>
<p>Let’s say you have a C function exported from a DLL; for convenience we’ll make it something rather silly but easy to understand:</p>
<pre class="c"><code>/** my_exported.h */
#include &quot;exports.h&quot;
typedef enum {
ZERO,
ONE,
TWO
} MyEnum;
MY_API int getAnEnumValue(MyEnum anEnum);</code></pre>
<p>The implementation just gives back the integer value of the function:</p>
<pre class="c"><code>int getAnEnumValue(MyEnum anEnum) {
return (int)anEnum;
}</code></pre>
<p>As I said, a <em>very</em> silly example. Note that you don’t technically need the <code>(int)</code> cast there; I’ve just put it in to be explicit about what we’re doing.</p>
<p>How would we use this from Python? Assuming we have a DLL named <code>my_dll</code> which exports the <code>getAnEnumValue</code> function, we’d load it up roughly like this:<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<pre class="python"><code>import ctypes as c
my_dll = c.cdll.LoadLibrary(&#39;my_dll&#39;)</code></pre>
<p>Then, we bind to the function like this:</p>
<pre class="python"><code>get_an_enum_value = my_dll.getAnEnumValue</code></pre>
<p>Now, when you do this, you usually also supply the <code>argtypes</code> and <code>restype</code> values for these functions. If you’re like me, you’d think, “Oh, an enum—a perfect opportunity to use the <code>Enum</code> type in Python 3.4+!” and then you’d do something like this:</p>
<pre class="python"><code>import ctypes as c
from enum import IntEnum
class MyEnum(IntEnum):
ZERO = 0
ONE = 1
TWO = 2
my_dll = c.cdll.LoadLibrary(&#39;my_dll&#39;)
get_an_enum_value = my_dll.getAnEnumValue
get_an_enum_value.argtypes = [MyEnum]
get_an_enum_value.restype = c.c_int</code></pre>
<p>That seems sensible enough, but as it is, it won’t work: you’ll get an error:</p>
<pre><code>TypeError: item 1 in _argtypes_ has no from_param method</code></pre>
<p>This is because <code>argtypes</code> values <em>have</em> to be either existing <code>ctypes</code> types<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> or supply either:</p>
<ul>
<li>a <code>from_param</code> classmethod, or</li>
<li>an <code>_as_parameter_</code> attribute</li>
</ul>
<p>You can use <code>ctypes.Structure</code> subclasses natively that way, because the <code>Structure</code> class supplies its <code>from_param</code> classmethod. The same is <em>not</em> true of our custom enum class, though. As the docs put it:</p>
<blockquote>
<p>If you have defined your own classes which you pass to function calls, you have to implement a <code>from_param()</code> class method for them to be able to use them in the argtypes sequence. The <code>from_param()</code> class method receives the Python object passed to the function call, it should do a typecheck or whatever is needed to make sure this object is acceptable, and then return the object itself, its <code>_as_parameter_</code> attribute, or whatever you want to pass as the C function argument in this case. Again, the result should be an integer, string, bytes, a <code>ctypes</code> instance, or an object with an <code>_as_parameter_</code> attribute.</p>
</blockquote>
<p>So, to make the enum type work, we need to add a <code>from_param</code> class method or an <code>_as_parameter_</code> attribute to it. Thus, either of these options will work:</p>
<pre class="python"><code>class MyEnum(IntEnum):
ZERO = 0
ONE = 1
TWO = 2
# Option 1: set the _as_parameter value at construction.
def __init__(self, value):
self._as_parameter = int(value)
# Option 2: define the class method `from_param`.
@classmethod
def from_param(cls, obj):
return int(obj)</code></pre>
<p>In the constructor-based option, the <code>value</code> argument to the constructor is the value of the <code>Enum</code> instance. Since the value of anan <code>IntEnum</code> is always the same as the integer to whcih it is bound, we can just return <code>int(value)</code>.</p>
<p>The <code>from_param</code> approach works a little differently, but with the same results. The <code>obj</code> argument to the <code>from_param</code> method is the object instance, in this case the enumerated value itself. <em>Any</em> <code>Enum</code> with an integer value can be directly cast to <code>int</code> (though it is possible for <code>Enum</code> instances to have other values, so be careful), and since we have an <code>IntEnum</code> here, we can again just return <code>int(obj)</code> directly.</p>
<p>Now, let’s say we want to apply this pattern to more than a single <code>IntEnum</code> class, because our C code defines more than one enumeration. Extracting it to be common functionality is simple enough: just create a class that implements the class method, and inherit from it.</p>
<pre class="python"><code>class CtypesEnum(IntEnum):
&quot;&quot;&quot;A ctypes-compatible IntEnum superclass.&quot;&quot;&quot;
@classmethod
def from_param(cls, obj):
return int(obj)
class MyEnum(CtypesEnum):
ZERO = 0
ONE = 1
TWO = 2</code></pre>
<p>Our final (working!) Python code, then, would be:</p>
<pre class="python"><code># Import the standard library dependencies
import ctypes as c
from enum import IntEnum
# Define the types we need.
class CtypesEnum(IntEnum):
&quot;&quot;&quot;A ctypes-compatible IntEnum superclass.&quot;&quot;&quot;
@classmethod
def from_param(cls, obj):
return int(obj)
class MyEnum(CtypesEnum):
ZERO = 0
ONE = 1
TWO = 2
# Load the DLL and configure the function call.
my_dll = c.cdll.LoadLibrary(&#39;my_dll&#39;)
get_an_enum_value = my_dll.getAnEnumValue
get_an_enum_value.argtypes = [MyEnum]
get_an_enum_value.restype = c.c_int
# Demonstrate that it works.
print(get_an_enum_value(MyEnum.TWO))</code></pre>
<p>The output will be <code>2</code>, just as you’d expect!</p>
<p>An important note: The type definition we’ve provided here will work for <code>argtypes</code> or <code>restype</code> assignments, but <em>not</em> as one of the members of a custom <code>ctypes.Structure</code> type’s <code>_fields_</code> value. (Discussing how you’d go about doing that is beyond the scope of this post; the most direct approach is just to use a <code>ctypes.c_int</code> and note that it is intended to be used with a given <code>IntEnum</code>/<code>CtypesEnum</code> type.)</p>
<hr />
<p>Thanks to <a href="https://alpha.app.net/oluseyi">@oluseyi</a> for being my <a href="http://en.wikipedia.org/wiki/Rubber_duck_debugging">rubber ducky</a> while I was working this out earlier this week!</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I’m leaving out the part where we build the DLL, and also the part where we locate the DLL, and only using the Windows convention. If you’re on a *nix system, you should use <code>'my_dll.so'</code> instead, and in any case you need to make sure the DLL is available in the search path.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>I <em>love</em> the redundancy of “<code>ctypes</code> types,” don’t you?<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoThu, 28 May 2015 18:00:00 -0400tag:v4.chriskrycho.com,2015-05-28:/2015/ctypes-structures-and-dll-exports.htmlsoftware developmentOpen Source is Neathttp://v4.chriskrycho.com/2015/open-source-is-neat.html<p>I confess: my <em>first</em> response to seeing <a href="//andrewcamenga.com/">this page</a> was a flash of anger: <em>Hey, he didn’t just learn from my site configuration, he actually stole my site </em><strong>design</strong>_!_ And then I remembered: I open-sourced the design precisely so people could do that. This was just the first time I’ve ever actually had someone reuse something I did and shared like this. It was a strange (but ultimately wonderful) feeling. I hope to have it again many more times.</p>
<p>In any case, I rather like the tweaks Andrew Comenga made to my design to make it his own; <a href="//andrewcamenga.com/">go take a look</a>!</p>
Chris KrychoSun, 17 May 2015 22:52:00 -0400tag:v4.chriskrycho.com,2015-05-17:/2015/open-source-is-neat.htmllinkssoftware developmentdesignThese Are My Peoplehttp://v4.chriskrycho.com/2015/these-are-my-people.html<p>At the end of April, I flew out to Seattle to <a href="//v4.chriskrycho.com/2015/tolle-lege.html">give a talk</a> at <a href="//bibletechconference.com">BibleTech</a>, a conference hosted by Faithlife (the company that owns Logos Bible Software). What I found was not only a bunch of interesting content—though there was certainly plenty of that, and props to the Logos/Faithlife people for putting on a great event—but also an awful lot of people <em>a lot like me</em>.</p>
<p>Those of you who know me well know this is rare. Finding people who share <em>one</em> of my primary interests <em>and approach it the same way I do</em> is relatively rare. Finding people who share an interest is not especially hard, but that qualification is extraordinarily important: I know lots of people interested in programming, and lots of people interested in theology, and not many at all who approach either the same way I do. Finding people who are interested in both software <em>and</em> theology (still less also music and linguistics and so on) has been so rare as to be a point of quiet but significant and ongoing frustration in my life.</p>
<p>And then I went to BibleTech, and met a lot of amazing people.</p>
<p>I was reflecting on the experience today—thinking about why I’ve so deeply enjoyed not only the conference itself but <a href="//bibletechnology-slack.herokuapp.com/">the community</a> that has sprung out of it—I realized: <em>These are my people.</em> They share a passion for software development, theology, linguistics, and in many cases even music. There may not be many of us in the world, but a substantial number were assembled in Seattle April 30–May 1, 2015. That’s no small thing.</p>
<p>I have no idea what the future holds for me—whether it will continue to include writing software for the Bible specifically or not—but I <em>can</em> say that this phase of my life has been enormously beneficial in this one way if in no others. It is nice to find kindred spirits in the world, and to know that, even if I am pretty strange, there are other strange people out there, too, and that we can keep working in our strange ways to make the Word of God more available and more useful to people every day.</p>
<p>Good work, BibleTech.</p>
Chris KrychoSun, 17 May 2015 22:25:00 -0400tag:v4.chriskrycho.com,2015-05-17:/2015/these-are-my-people.htmlsoftware developmentjoyA Modern Python Development Toolchainhttp://v4.chriskrycho.com/2015/a-modern-python-development-toolchain.html<p>Most of my development time these days—and especially the majority of my happiest time!—is spent working in Python. As such, I’ve experimented off and on over the last few years with the best workflow, and have settled down with a set of tools that is <em>very</em> effective and efficient for me. I’m sure I’m not the only one who’s had to wrestle with some of the issues particular to this toolchain, and I know that information like this can be valuable especially for people just starting off, so I thought I would document it all in one place.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>Note: when talking about a given program, I will italicize it, like <em>brew</em> or <em>git</em> or <em>python</em>. When talking about things to type, I will make them a code block like <code>git clone &lt;a repository&gt;</code>. For any extended samples, I will make them full-on code blocks:</p>
<pre class="python"><code>import re
def a_neat_function():
my_string = &quot;Isn&#39;t it cool?&quot;
if re.match(r&quot;i\w+&quot;, my_string, flags=re.I):
print(my_string)</code></pre>
<hr />
<p>The main tools I use are: a good text editor (I like all of <a href="//www.sublimetext.com">Sublime Text</a>, <a href="//atom.io">Atom</a>, <a href="//github.com/textmate/textmate">TextMate</a>, and <a href="//chocolatapp.com">Chocolat</a>; each has its own strengths and weaknesses) or sometimes <a href="https://www.jetbrains.com/pycharm/">a full IDE</a>, version control software (I appreciate and use both <a href="http://www.git-scm.com">Git</a> and <a href="http://mercurial.selenic.com">Mercurial</a>), and three dedicated tools to which the rest of this post is devoted: <em>pyenv</em>, <em>pip</em>, and virtual environments.</p>
<p>Everyone is going to have their own preferences for version control tools and an editor; but the recommendations I make regarding Python installations, package management, and workspaces/virtual environments should be fairly standard for anyone doing Python development on a Unix-like system in 2015.</p>
<section id="python-proper" class="level2">
<h2>Python Proper</h2>
<p>First up: Python itself. OS X ships with a built-in copy of Python 2; in the latest version of Yosemite, it’s running Python 2.7.6. The latest version of Python 2 is 2.7.9, so that isn’t <em>terribly</em> far behind—but it is still behind. Moreover, OS X does <em>not</em> ship with Python 3, and since I do all of my development in Python 3<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> I need to install it.</p>
<section id="homebrew" class="level3">
<h3>Homebrew</h3>
<p>For a long time, I managed all my Python installations with <a href="http://brew.sh"><em>homebrew</em></a>. If you’re not familiar with it, <em>homebrew</em> is a package manager that lets you installed tools on the command line, similar to what you get from <em>aptitude</em> or <em>yum</em> on Ubuntu or Fedora respectively.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> If you’re not using <em>homebrew</em> yet, I highly recommend it for installing command-line tools. (If you’re not using command-line tools yet, then the rest of this post will either bore you to death, or prove extremely enlightening!) If you haven’t started yet, now’s a good time: <a href="http://brew.sh">go install it!</a>.</p>
<p>While <em>homebrew</em> is great for installing and managing packages in general, I can’t say this loud enough: <em>don’t manage Python with homebrew</em>. It’s finicky, and really isn’t meant for all the things you have to do to manage more than one version of Python at a time.<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a> (There’s a reason there’s a whole <a href="https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Homebrew-and-Python.md">troubleshooting section</a> devoted to it.) If you think it’s crazy that I might want more than one copy of Python installed a time, well… let’s just say I suspect you’ll change your mind after doing a bit more development. (At the most basic, most people will end up wanting both Python 2 and 3 installed, and will want to upgrade them as bug fixes and the like come out.)</p>
</section>
<section id="pyenv" class="level3">
<h3>pyenv</h3>
<p>Instead of installing via <em>homebrew</em>, use it to install <a href="https://github.com/yyuu/pyenv"><em>pyenv</em></a>, and use that to manage your installations. <em>pyenv</em> is a dedicated tool for managing your “Python environment,” and it excels at that. If you were on a Mac with <em>homebrew</em> installed, your setup process to add the latest version of Python might look something like this:</p>
<pre class="shell"><code>$ brew install pyenv
$ echo &#39;eval &quot;$(pyenv init -)&quot;&#39; &gt;&gt; ~.profile
$ source ~/.profile
$ pyenv install 3.4.3</code></pre>
<p>Line by line, that (a) installs <em>pyenv</em>, (b) adds a hook to your shell profile,<a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a> (c) updates your current session using the updated profile, and (d) installs the latest version of Python (as of the time I’m writing this). Now you have a full version of Python 3.4.3 alongside the system install of Python 2.7.6. If you wanted to install 2.7.9, or 2.2.3, or the development version of PyPy3, you could easily do that as well.</p>
<p>In addition, <em>pyenv</em> lets you specify which version to use globally (<code>pyenv global &lt;name&gt;</code>) and which version to use in a given directory structure (<code>pyenv local &lt;name&gt;</code>). So if you prefer to use Python 3 in general, but need to use Python 2 on one project, you can just navigate to the root of that project and set it:</p>
<pre class="shell"><code>$ pyenv global 3.4.3
$ cd path/to/my/project
$ pyenv local 2.7.9</code></pre>
<p>This will create a simple plain text file, <code>.python-version</code>, whose contents will be just <code>2.7.9</code>—but for everything under <code>path/to/my/project</code>, typing <code>python</code> will launch Python 2.7.9, while typing it <em>outside</em> that folder will launch Python 3.4.3. (If you want, you can just create the <code>.python-version</code> file yourself manually and give it the name of a version. There’s nothing special about it all; it’s just the place <code>pyenv</code> looks to know which Python version to use.)</p>
</section>
</section>
<section id="managing-python-packages" class="level2">
<h2>Managing Python Packages</h2>
<p>There are four basic approaches to managing Python packages:</p>
<ul>
<li>installing them manually</li>
<li>using a system-level package manager like <em>homebrew</em>, <em>yum</em>, or <em>aptitude</em></li>
<li>using <em>easy_install</em></li>
<li>using <em>pip</em></li>
</ul>
<p>The vast majority of the time, the right choice is using <em>pip</em>. Over the last few years, <em>pip</em> has become the default install tool for Python packages and it now ships natively with it on every platform. Suffice it to say: if you need to install a package, do not install it not with <em>homebrew</em> (or <em>aptitude</em> or <em>yum</em>). Install it with <em>pip</em>. It integrates with Python better, it always has access both to the latest versions of Python packages (including those only available in e.g. development repositories on GitHub or Bitbucket or wherever else) and to all previously released versions, and it’s the community’s main tool for the job.</p>
<p>That said, occasionally it makes sense to install packages manually by downloading them and running <code>python setup.py install</code> or to use a system-level package manager. On the other hand, given <em>pip</em>’s ability to do everything <em>easy_install</em> does, and its ability to do quite a few more things as well, there really isn’t a time to use <em>easy_install</em>. Using the language-supplied tools keeps everything playing nicely together. Perhaps just as importantly, it is the only way to make sure everything behaves the way it should when you start using…</p>
</section>
<section id="virtual-environments" class="level2">
<h2>Virtual Environments</h2>
<p>When working with a variety of different clients, or simply on different projects, it is common not only to end up with different versions of Python but also with different sets of packages or—tricker still!—different versions of the same package required for different projects. Virtual environments provide a solution: they reuse the main Python executable (by creating links on the file system to it), but create isolated “workspaces” for the various packages you might install.</p>
<p>That way, in one workspace, you might have version 1.2 of a package installed, and in another you might have version 3.3 installed—because those are the required dependencies for something <em>else</em> you’re doing. This isn’t a hypothetical situation. For quite a while with one of my clients, we had pinned a particular version of the Python documentation package we use because it broke our use case after an update—but I still wanted to have the latest version of that tool in my <em>other</em> projects. Setting up virtual environments neatly solves that problem.</p>
<section id="venv-and-virtualenv" class="level3">
<h3>venv and virtualenv</h3>
<p>If you have Python 3.3 or later, you have a built-in tool for this called <a href="https://docs.python.org/3/library/venv.html"><em>pyvenv</em></a>; if you have Python 3.4 or later, it supports <em>pip</em> right out of the gate so you don’t have to install it yourself. If you’re on older versions, you can install <a href="https://virtualenv.pypa.io/en/latest/"><em>virtualenv</em></a> (<code>pip install virtualenv</code>) and get the same basic tooling: <em>pyvenv</em> was inspired by <em>virtualenv</em>. Then you can create virtual environments with the <code>pyvenv</code> or <code>virtualenv</code> commands, and use those to isolate different setups from each other. If you haven’t started using virtual environments yet, start now!</p>
</section>
<section id="pyenv-with-virtualenv" class="level3">
<h3>pyenv with virtualenv</h3>
<p>I know, the similarity of names for <em>pyenv</em> and <em>pyvenv</em> is unfortunate. If it helps, you can call the latter as <code>venv</code> rather than <code>pyvenv</code>. But, more importantly, one of the areas <em>pyenv</em> is much better than <em>homebrew</em> is its support for managing virtual environments. Install <a href="https://github.com/yyuu/pyenv-virtualenv"><em>pyenv-virtualenv</em></a>:</p>
<pre class="shell"><code>$ brew install pyenv-virtualenv
$ echo &#39;eval &quot;$(pyenv virtualenv-init -)&quot;&#39; &gt;&gt; ~/.profile</code></pre>
<p>Now you’re off to the races: you’ll never have to type <code>pyvenv &lt;path to a virtual environment&gt;</code>, because instead you can just type <code>pyenv virtualenv &lt;version&gt; &lt;name&gt;</code> and <em>pyenv</em> will take care of setting it up for you. Even better: all the nice tricks I listed above about setting directory-specific and global preferences for which Python version to use work equally well with virtual environments managed via <em>pyenv</em>. In other words, you can do something like this:</p>
<pre class="shell"><code>$ pyenv install 2.7.9
$ pyenv install 3.4.3
$ pyenv global 3.4.3
$ pyenv virtualenv 2.7.9 my-virtual-environment
$ cd path/to/my/project
$ pyenv local my-virtual-environment</code></pre>
<p>The <code>.python-version</code> file will contain <code>my-virtual-environment</code>. The Python version will be 2.7.9. The environment will be isolated, just as if you had run <code>pyvenv</code> to set up a virtual environment. Everything works together beautifully! Moreover, you can easily reuse virtual environments this way, because you can set the <code>local</code> value in more than one place. For example, I use the same virtual environment for this site and <a href="//www.winningslowly.org/" title="A podcast: taking the long view on technology, religion, ethics, and art.">Winning Slowly</a>, because they have slightly different site configurations but all the same Python dependencies. Creating it was simple:</p>
<pre class="shell"><code>$ pyenv install 3.4.3
$ pyenv virtualenv 3.4.3 pelican
$ cd ~/Sites/chriskrycho.com
$ pyenv local pelican
$ cd ~/Sites/winningslowly.org
$ pyenv local pelican</code></pre>
<p>I named the virtual environment after <a href="//docs.getpelican.com/">the tool I use to generate the sites</a>, and reused it in both sites. Both now have a <code>.python-version</code> file that reads <code>pelican</code>. Now, anytime I’m working anywhere under <code>~/Sites/chriskrycho.com</code> <em>or</em> <code>~/Sites/winningslowly.org</code>, I have the same tooling in place.</p>
</section>
</section>
<section id="summary" class="level2">
<h2>Summary</h2>
<p>The combination of <em>pip</em>, <em>pyenv</em> and virtual environments makes for a very simple, straightforward process to manage Python environments these days:</p>
<ul>
<li>Install Python versions with <em>pyenv</em>.</li>
<li>Install Python packages with <em>pip</em>.</li>
<li>Set up virtual environments with <em>pyenv-virtualenv</em>.</li>
</ul>
<p>If you stick to those basic rules, Python itself shouldn’t give you any trouble at all.</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>All the usual caveats apply, of course: this may or may not work well for you; it’s just what works for me, and I make no claim or warranty on the tools below—they’re working well for <em>me</em>, but I don’t maintain them, so if they break, please tell the people who maintain them! Also, because I do nearly all my development on a Mac (I test on Windows, but that’s it), the following is necessarily <em>fairly</em> specific to OS X. You can readily adapt most of it to Linux, though, or even to a <a href="https://www.cygwin.com">Cygwin</a> install on Windows—I do just that when I have cause. But my main tool is a Mac, so that’s what I’ve specialized for.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Lucky me, I know!<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>Yes, I know that those are wrappers around Debian and Arch, and I know about <em>apt-get</em> and <em>rpm</em>. No, that information isn’t especially relevant for the rest of this post.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn4" role="doc-endnote"><p>For example, if you upgrade your Python installation using homebrew and then cleanup the old version (e.g., by running the typical <code>brew update &amp;&amp; brew upgrade &amp;&amp; brew cleanup</code> sequence)—say, from 3.4.2 to 3.4.3—and you have virtual environments which depended on 3.4.2… well, you’re in a bad spot now. A <em>very</em> bad spot. Have fun getting back to a working state!<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn5" role="doc-endnote"><p>You can of course drop it directly in <code>.zshrc</code> or <code>.bash_profile</code> or wherever else. <a href="//github.com/chriskrycho/profile">My setup</a> puts all common handling in <code>.profile</code> and runs <code>source .profile</code> as the first action in any other shell configurations.<a href="#fnref5" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 16 May 2015 22:40:00 -0400tag:v4.chriskrycho.com,2015-05-16:/2015/a-modern-python-development-toolchain.htmlSoftware DevelopmentLessons Learnedhttp://v4.chriskrycho.com/2015/lessons-learned.html<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’s still a lot to wrap up, the project is <em>nearing</em> its conclusion, and I thought I’d note a few things I’ve 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’m extremely proud of the work I’ve done, and the application I’ve 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, “How I failed” but rather “How I will do this <em>even better</em> next time around.”</p>
<ol type="1">
<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>
<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’d 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>
<li><p><em>Progressive enhancement or graceful degradation are hard in web applications, but they still matter.</em> In the past, I’ve 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’t 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’m still thinking a <em>lot</em> about the best way to do this in the future.</p></li>
<li><p><em>More popular doesn’t mean better.</em> Angular has a ton of traction and uptake, and that was deceptive early on. I won’t so easily be fooled in the future. Angular is so very popular in part because Google can put serious money behind its development—and its marketing. But it’s <em>not</em> the best for many applications; if you’re not in the business of developing your own custom framework, it’s 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>
<p>How to avoid making that mistake? Well, for my part since then, I’ve 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’s), 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>
<p>I will also look at the way the community behaves. The Ember community is <em>far</em> friendlier for newcomers from what I’ve seen than the Angular community—no slam meant on the Angular crowd, but the Ember folks are just doing that really well. That matters, too. (I can’t speak for other communities, of course; these are just the groups I’ve watched the most.)</p>
<p>All in all, Ember would have been the better fit between these two (even though, as noted above, it also wouldn’t have been the <em>best</em> fit).</p></li>
<li><p><em>Unit tests really are the best.</em> I did a vast majority of this project with unit tests—the first time I’ve ever been able to do that for a whole project. In other projects, I’ve 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’t have time to write the tests, I (inevitably and predictably!) ended up spending a lot of time chasing down hard-to-isolate bugs—time 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’re 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>
<li><p><em>Unit tests <strong>really</strong> don’t 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’t believe it. Design your API and document it, <em>then</em> do test-driven development against that contract.</p></li>
<li><p><em>Sometimes ‘good enough’ is enough.</em> There is always more to be done, and inevitably you can see a thousand things that could be improved. But ‘good’ shipping code is far more valuable than ‘perfect’ code that never ships. You should never ship <em>bad</em> code, but sometimes you do have to recognize ‘good enough’ and push it out the door.</p></li>
<li><p><em>Full-stack development is fun, but it’s 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’s a lot to hold in one’s 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’s a lot of work, and now I know more clearly just how much.</p></li>
</ol>
<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>
Chris KrychoSun, 12 Apr 2015 13:49:00 -0400tag:v4.chriskrycho.com,2015-04-12:/2015/lessons-learned.htmlsoftware developmentjavascriptangularjsUnsurprisingly, In Fluxhttp://v4.chriskrycho.com/2015/unsurprisingly-in-flux.html<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’s <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>
<hr />
<ul>
<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 – React &amp; Angular – Ember – Meteor.</p></li>
<li><p>Backbone and related library Underscore are really collections of common JS tools and patterns you can use to write apps, but they’re not <em>frameworks</em>, per se. You’ll write all your own boilerplate there.</p></li>
<li><p>React and Angular supply much <em>more</em> of the functionality, but Angular is a “meta-framework” that aims to do <em>some</em> boilerplate but let you construct your own custom app framework.</p></li>
<li><p>Angular is very powerful, but it’s 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—so much so that there’s a near-standard third-party router.</p></li>
<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’s 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>
<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>
<li><p>Ember is a full framework, strongly emphasizing shared conventions (with a lot of common developers from Rails). It’s perhaps less adaptable than React or Angular, but is much more full-featured; you have very little boilerplate to do.</p></li>
<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>
<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>
<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>
<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>
<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>
<li><p>If you’re 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’re firing on all cylinders.</p></li>
</ul>
<p>Regarding Angular, <a href="https://alpha.app.net/mikehoss">@mikehoss</a> <a href="https://alpha.app.net/mikehoss/post/57105656">posted</a>:</p>
<blockquote>
<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ško is a bit of a jerk.</p>
</blockquote>
<p>I can’t speak to his comment about Miško (Miško Hevery, one of the leads on AngularJS), but I agree about Angular itself: the rewrite needs to happen. Angular 1.x is a mess—as are its docs. It’s just not a good time to be using 1.x for any new projects.</p>
<p>I’ll add to these points that I’ve 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’m looking for in a framework—but it makes sense given Angular’s goal of being a meta-framework.</p>
<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 “good enough” interface that we’re all now stuck with, Angular is being used <em>as</em> a framework, not just as a <em>meta-framework</em>, and it’s unsurprisingly not great for that.</p>
<hr />
<p><i class="editorial">Take this for what it’s worth: not the final word (by a long stretch) on JavaScript frameworks, but rather the perspective of one guy who notably <em>hasn’t used all of the frameworks</em>, but has spent some time looking at them. Moreover, I haven’t particularly edited this; it’s more a summary in the kind of short-form posts that I originally created than a detailed analysis. The only things I’ve done are expand some of the notes on Angular and React, and add the footnote on React.</i></p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I <em>really</em> don’t 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’s a bit of a pain: React’s “JSX” 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’s a substantil tradeoff there: React’s model is interesting not only academically but in practice because of the performance results it produces. It’s 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’re rolling out over the past several and future several releases.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoWed, 08 Apr 2015 16:05:00 -0400tag:v4.chriskrycho.com,2015-04-08:/2015/unsurprisingly-in-flux.htmlsoftware developmentjavascriptangularjsemberjsreactThe Joy of Good Toolshttp://v4.chriskrycho.com/2015/joy-good-tools.html<p><i class="editorial">Note: This started out as a <a href="https://alpha.app.net/chriskrycho/post/47820144">series of posts on App.net</a>, but as I realized that it was growing a bit, I decided to <a href="/2014/a-few-theses-on-blogging.html">take my own advice</a> and turn it into a short blog post. (The first four paragraphs of this post are the same as the posts that spawned it.) And then, as so often happens with my writing, it rather took on a life of its own. So much for short.</i></p>
<hr />
<p>After wrestling with Bitbucket issues again all day, I think I’ve finally hit the breaking point. Time to go ahead and drop the money on GitHub and migrate my private repos there. (Yes, GitLab is neat, but tool integrations matter, too.)</p>
<p>I think I’m also probably going to spring for a small subscription to Pivotal Tracker. It’s cheaper to do GitHub+PivotalTracker at my scale than to host GitLab and run YouTrack on a VPS. And that’s <em>not</em> counting my time.</p>
<p>The big thing with Pivotal is that I <em>need</em> the ability to estimate more effectively even than something like Trello affords (and I don’t want to spend time wrangling with Chrome plugins), and it gives me that. Totally worth the cost in saved pain.</p>
<p>And as for GitHub as compared to the free GitLab… well, honestly, the F/OSS-copycat model bothers me on a lot of levels. The fact that their strategy is “copy GitHub as closely as possible, and charge for it” is not my idea of “winning slowly”.</p>
<p>(“Winning slowly” is more than just the name of my <a href="//www.winningslowly.org">podcast</a>. In fact, it’s the opposite: we named the podcast that because it’s one of the core commitments in our lives.)</p>
<p>So I’m going to pay for Pivotal and GitHub. My time is worth something, and the quality of the tools I use matters, too. Ongoing irritation and frustration adds up over time. Good tools can make us happier. Bad tools can make work more frustrating than it needs to be. Given just how frustrating work can be anyway, the last thing in the world I want to do is unnecessarily spend my time being even more frustrated by my tools. And you know what? $7/month for each of those tools is absolutely worth more than the frustration of wrestling with tools that do the job less well.</p>
<p>I’m actually really excited by this. Pivotal Tracker will help me avoid making the painful mistake of underestimation in the future, by helping me see how long things actually take and giving me a way to plan out major projects with that data immediately available. GitHub will be simultaenously more functional and much lovelier than Bitbucket—no strategy tax holding it back!—and will be much nicer to use.</p>
<p>At the end of the day, it comes down to this: I’m happy to pay for good tools that make my work more enjoyable.</p>
<hr />
<p>To my surprise and amusement, this leads me to a closely related point I had been writing up in a separate blog post: the value of tools that <em>delight</em>. It is not merely that bad tools make work unpleasant. Good tools can make work a <em>joy</em>. Indeed, because my vocations is such a significant part of my life, few things bring me as much simple pleasure as a tool that does its job well, is pleasant to use, and is beautiful, all at once.</p>
<p>The latest example of this for me is <a href="//www.neat.io/bee/index.html">Bee</a>, a tool designed to make working with issue trackers like JIRA, GitHub Issues, and FogBugz easier and more pleasant. I use JIRA for one of my long-term contracts—I actually set it up for the company—and I have a love-hate relationship with it. JIRA’s power is great, but the web interface is slow and cluttered.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>I have used other desktop tools with JIRA before, and they were even worse than the web interface. I stumbled across Bee the other day (I cannot even remember how!), decided to try it out, and fell in love. It is simple, fast, and <em>elegant</em>. That is a killer combination. I have been using it daily for over a week, and strange though it might be to say of a desktop client for issue trackers, I get genuine pleasure out of using it. (Yes, I know: that is a bit strange.)</p>
<p>I have the same experience with a number of other tools I use—<a href="//www.git-tower.com">Tower</a>, <a href="//bywordapp.com">Byword</a>, and <a href="//www.jetbrains.com/idea/">IntelliJ IDEA</a> to name just a few. This very post is written in Byword, and I’m <em>happy</em> about it. I wish I felt that way about every tool I use.</p>
<p>And this goes beyond software. I have had the same experience driving a car. The Mazda3 I drove in and after college was a delight. The MUV<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> we drive right now is sufficient. The Chevy Malibu we rented for driving to and from Texas in December was <em>irritating</em>, with an inordinate number of small failures to consider how the thing would actually be used. I would buy another Mazda3 in a heartbeat; I would contentedly take another Lexus RX300-alike; I would avoid a Chevy Malibu like the plague.</p>
<p><em>Every</em> category of tool is like this.</p>
<p>The difference between a poor or mediocre tool and a good tool can make the difference between frustration and satisfaction. The difference between a good tool and a <em>great</em> tool can make the difference between satisfaction and delight. That inspires me: it makes me want to make things so that they do more than <em>suffice</em>—so that they <em>excel</em>, so that they delight and energize their audience. Whether that is someone using a web application I write or someone listening to a piece of music I composed, I want them to experience more than good-enough. I want them to feel joy.</p>
<hr />
<p>There is something profound here, I think, something that goes even deeper than just the experience of being happy enough with a good tool to pay money to use it. I think human beings are meant for that profound joy—meant for it in every breath. That these kinds of delights are rare, and so often marred even at their best by little failures, is a mark of the imperfection—and, in human terms at least, the <em>imperfectibility</em>—of the world in which we live. But the fact that such moments will be rare until the eschaton neither undoes nor diminishes the imperative to strive after them—especially for those of us who, as Christians, affirm the goodness and the <em>telos</em> of the created world. Quite the contrary. We have a responsibility and a charge as subcreators always to be able to say of the work we have done, “It is good.”</p>
<p>I am not there yet. I hope very much, though, that the work I do this year will be—for at least one person—a little sip from that deep well of delight. Whether I succeed or no, at least the bar is set where it ought to be.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Atlassian’s designers seem to be shooting for the kind of “flat” minimalism that is in right now… and missing the mark entirely. <em>All</em> of their tools are a cluttered mess in the UI/X department.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>A “Mom Utility Vehicle”, my wry term for “SUV”-type vehicles sitting on standard car chasses.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 09 Jan 2015 18:00:00 -0500tag:v4.chriskrycho.com,2015-01-09:/2015/joy-good-tools.htmlsoftware developmentdesignjoyGrowing Up Togetherhttp://v4.chriskrycho.com/2014/growing-up-together.html<p>A few years ago, you might have caught me in a grumpy moment grousing about JavaScript. I distinctly did <em>not</em> like writing it. Every time I sat down to deal with it, I found myself in a tangled mess of plain JavaScript, jQuery, and DOM manipulations that inevitably left me tearing my hair out.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> I found it difficult to write in the first place, and even harder to maintain in the long run. I could not come up with good ways to organize it, especially because so much of what I was doing was so thoroughly <em>ad hoc</em> in nature. Cobble this together over here; scrounge together those things over there; hope nothing collides in the middle.</p>
<p>In the last four months, I have written several thousand lines of JavaScript, and I have <em>loved</em> it.</p>
<p>For my latest major project, relaunching <a href="https://holybible.com">HolyBible.com</a>, I wrote the front end in <a href="https://angularjs.org">AngularJS</a> and the back end as an <a href="http://expressjs.com">Express</a> app (the most popular <a href="http://nodejs.org">NodeJS</a> web framework). I’ve written gobs of tests in <a href="http://jasmine.github.io">Jasmine</a> (using <a href="https://github.com/mhevery/jasmine-node">jasmine-node</a> for server-side tests) and drawn on tons of other open-source packages.</p>
<p>And I have <em>loved</em> it.</p>
<p>A small example: a moment ago, looking up the link for Jasmine, I noted that the latest version released today. My response was, “Ooh—cool!”<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<p>What changed? Well, mostly I changed, but also JavaScript changed a bit. We both grew up over the last four years. On the JavaScript side of things, a lot of good design patterns and tools have come into play in that span. I’m sure there were plenty of good, disciplined web developers writing clear, careful, well-organized client-side JavaScript four years go. But in the interval, that kind of JavaScript got a lot more prominent, in part because it has had help from the rapid rise of server-side JavaScript in the form of Node.js and its flourishing ecosystem of components and tools. Build tools like <a href="http://browserify.org">Browserify</a> and development tools like <a href="http://livereload.com">LiveReload</a> and <a href="https://incident57.com/codekit/">Codekit</a> have combined with best practices learned from those long years of jQuery/DOM-manipulation hell so that these days, good JavaScript is a lot like good programming in any other language: highly modular, carefully designed, and well-organized.</p>
<p>In the same period of time, I have matured enormously as a developer (just enough to see how far I still have to go, of course). At the point where I most hated JavaScript, I also really struggled to see the utility of callbacks. Frankly, it took me the better part of a month just to get my head around it—most of the tutorials out there just assumed you understood them already, and, well: I didn’t. Functions as first-class members of a language was new to me at that point. Fast-forward through several years of full-time Python development, lots of time spent reading about software development and some harder computer science concepts, and my perspective on JavaScript has shifted more than a little. Closures are beautiful, wonderful things now. Functions as arguments to other functions are delightful and extremely expressive. Prototypal inheritance—trip me up though it sometimes still does—is a fascinating variation on the idea of inheritance and one that I think I like rather better than classical inheritance.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<p>There are still things I don’t love about JavaScript. Its syntax owes far too much to the C family of languages to make me happy; I quite like the way that CoffeeScript borrows from Python (white-space-delimited blocks, use of equality words like <code>is</code> and boolean rules like <code>and</code> rather than <code>===</code> and <code>&amp;&amp;</code> respectively, etc.). And I am looking forward to a number of features coming in the next version of JavaScript—especially generators and the <code>const</code> and <code>let</code> keywords, which will allow for <em>much</em> saner patterns.</p>
<p>But all of that is simply to say that I am now starting to know JavaScript enough to know that its <em>real</em> issues aren’t the surface-level differences from the other languages with which I’m familiar. They’re not even the warts I noted here. They’re things like the mix of classical and prototypal inheritance in the way the language keywords and object instantiation work. But I don’t mind those. Every language has tradeoffs. Python’s support for lambdas is pretty minimal, despite the utility of anonymous functions, for example. But I <em>like</em> the tradeoffs JavaScript makes.<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<p>In other words, I discovered the same thing so many other people have over the last few years: JavaScript isn’t just a good choice for utilitarian reasons. Beneath that messy exterior is a gem of a language. I’m having a lot of fun with it.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Thus the early balding starting by my temples.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>My wife’s bemused response: “Is that <em>another</em> language?” Take that as you will.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>The couple weeks I got to spend <a href="http://v4.chriskrycho.com/2014/a-little-crazy.html">playing</a> with <a href="http://iolanguage.org">Io</a> certainly helped! Io’s prototypal inheritance is semantically “purer” than JavaScript’s, which is quite an improvement in my view. JavaScript’s <code>new</code> keyword and the pseudo-classical object pattern it brings along can go rot in a bog.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn4" role="doc-endnote"><p>Truth be told, I like them even better from the perspective of CoffeeScript, which hides a lot of the rough edges of JavaScript and, as noted above, brings in quite a few things I like from Python. For my part, I intend to write as much CoffeeScript as possible going forward.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoSat, 15 Nov 2014 00:30:00 -0500tag:v4.chriskrycho.com,2014-11-15:/2014/growing-up-together.htmlsoftware developmentA Ridiculous Situationhttp://v4.chriskrycho.com/2014/a-ridiculous-situation.html<p>One of the pieces of code I’m maintaining has an <em>absurd</em> situation in its build structure—honestly, I’m not sure how it ever compiled. For simplicity’s sake, let us assume the four following files:</p>
<ul>
<li><code>main.c</code></li>
<li><code>secondary.c</code></li>
<li><code>writer.h</code></li>
<li><code>calculator.h</code></li>
</ul>
<p>The project has many more files than this, of course, but these are the important ones for demonstrating this particular piece of insanity (which shows up <em>many</em> places in the codebase).</p>
<p>I’m reproducing here some dummy code representing an <em>actual set of relationships in the codebase</em>. The functions and module nameshave been changed; the relationships between the pieces of code have not.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> When I started trying to build the program that included what I am representing as <code>main.c</code> below, this is the basic structure I found:</p>
<section id="main.cpp" class="level3">
<h3><code>main.cpp</code></h3>
<p>This is the main module of the program. In the actual code in which I found this particular morass, it was actually code generated by the UI builder in Visual Studio 6<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> and then turned into an unholy mess by a developer whose idea of good programming involved coupling the various parts of the code as tightly as possible.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<pre class="c"><code>#include &quot;calculator.h&quot;
#include &quot;secondary.h&quot;
int a=0, int b=0;
int addNumbers(a, b) {
return a+b;
}
void doBadThingsWithGlobals(int * someNumber) {
a = 6;
*someOtherNumber = 5;
}
#include &quot;writer.h&quot;
void main() {
a = 3;
doBadThingsWithGlobals(&amp;b);
addNumbers(a, b);
doStuffWithNumbers(a,b);
subtractNumbers(b, a);
}
// More insanity follows...</code></pre>
<p>Yes, the main function and the <code>doBadThingsWithGlobals</code> function are both modifying global state, and yes, there is an include statement midway down through the module. (Just wait till you see what it does.)</p>
</section>
<section id="secondary" class="level3">
<h3>“secondary”</h3>
<p>Here is a secondary module which has been somewhat cleaned up. It has normal relationships between header and source files, and includes all its dependency headers at the top of the file. It has a header which defines the public API for the module, and that even has inclusion guards on it.</p>
<section id="secondary.h" class="level4">
<h4><code>secondary.h</code></h4>
<pre class="c"><code>#ifndef SECONDARY_H
#define SECONDARY_H
int doStuffWithNumbers();
#endif SECONDARY_H</code></pre>
</section>
<section id="secondary.c" class="level4">
<h4><code>secondary.c</code></h4>
<p>The <code>doStuffWithNumbers</code> function here calls <code>addNumbers</code>:</p>
<pre class="c"><code>#include &quot;secondary.h&quot;
#include &quot;calculator.h&quot;
int doStuffWithNumbers(int x, int y) {
addNumbers(x, y);
}</code></pre>
<p><em>But wait!</em> you say, <em>That function isn’t defined here!</em> Ah, and you would be right, except that it doesn’t refer to the <code>addNumbers</code> function in <code>main.c</code>. It refers to a function implementation in <code>calculator.h</code>.</p>
</section>
</section>
<section id="calculator.h" class="level3">
<h3><code>calculator.h</code></h3>
<pre class="c"><code>int addNumbers(int p, int q) {
return p + q;
}
int subtractNumbers(int r, int s) {
return r - s;
}</code></pre>
<p>Strangely, this <code>addNumbers</code> function is identical to the one in <code>main.c</code>. Even <em>more</em> strangely, it is defined—not merely declared, actually defined—in the header file! Nor is this the only such function. Look at the details of <code>writer.h</code>, which was mysteriously included above in the middle of the main module.</p>
</section>
<section id="writer.h" class="level3">
<h3><code>writer.h</code></h3>
<pre class="c"><code>void writeStuff() {
fprintf(stdout, &quot;a: %d, b: %d&quot;, a, b);
}</code></pre>
<p>Once again, we have a full-fledged implementation in the header file. Why, you ask? Presumably because the developer responsible for writing this code never quite got his head around how C’s build system works. The entirety of one of the central components of this software—an element that in any normal build would be a common library—was a single, approximately 2,000-line <em>header file</em>. (Say hello to <code>calculator.h</code> up there; that’s what I’m abstracting away for this example.)<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<p>Worse: it is printing the values of <code>a</code> and <code>b</code>, and no, I am not skipping some part of <code>writer.h</code>. It is getting those from <code>main.c</code>, because it was included after they were defined, and the build process essentially drops this header inline into <code>main.c</code> before it compilation.<a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a> So here we have a header file with the implementation of a given piece of code, included in a specific location and defined in such a way that if you change where it is included, it will no longer function properly (since the variables will not have been defined!)</p>
<p>Worse, there are conflicting definitions for one of the functions used in <code>main.c</code>, and because of its dependency on <em>other</em> functions in <code>calculator.h</code> (e.g. <code>subtractNumbers</code> in this mock-up), it cannot be removed! Moreover, given the many places <code>calculator.h</code> is referenced throughout the code base, it is non-trivial to refactor it.<a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a></p>
<p>If this sounds insane… that’s because it is.</p>
<p>If you’re curious how I dealt with it, well… I renamed the <code>addNumbers()</code> function in <code>main.c</code> to <code>_addNumbers()</code> and put a loud, angry <code>TODO</code> on it for the current release, because the only way to fix it is to refactor this whole giant mess.</p>
<p>The takeaway of the story, if there is one, is that people will do crazier, weirder, worse things than you can possibly imagine when they don’t understand the tools they are using and just hack at them till they can make them work. The moral of the story? I’m not sure. Run away from crazy code like this? Be prepared to spend your life refactoring?</p>
<p>How about: try desperately <em>not</em> to leave this kind of thing for the person following you.</p>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>That’s actually not <em>wholly</em> true, because these pieces of code are also duplicated in numerous places throughout the codebase. We’ve eliminated as many as possible at present… but not all of them, courtesy of the crazy dependency chains that exist. Toss in a dependency on Visual Studio 6 for some of those components, and, well… suffice it to say that we’re just happy there are only two versions floating around instead of the seven that were present when I started working with this codebase two and a half years ago.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Yes, <a href="http://en.wikipedia.org/wiki/Microsoft_Visual_Studio#Visual_Studio_6.0_.281998.29"><em>that</em></a> Visual Studio 6. The one from 1998. Yes, that’s insane. No, we haven’t managed to get rid of it yet, though we’re close. So close.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>I am not joking. Multi-thousand line functions constituting the entirety of a program are not just <em>normal</em>, they are pretty much the only way that programmer ever wrote. When you see the code samples below, you will see why: someone was lacking an understanding of C’s build system.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn4" role="doc-endnote"><p>Also, that’s the piece of code of which I found seven different versions in various places when I started. Seven!<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn5" role="doc-endnote"><p>I once ran into some code working on a different project for an entirely different client where there had been a strict 1,000-line limit to C source files, as part of an attempt to enforce some discipline in modularizing the code. Instead of embracing modularity, the developers just got in the habit of splitting the source file and adding <code>#include</code> statements at the end of each file so that they could just keep writing their non-modular code.<a href="#fnref5" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn6" role="doc-endnote"><p>I have tried. Twice. I’m hoping that the third time <em>will</em> be the charm.<a href="#fnref6" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 07 Nov 2014 21:00:00 -0500tag:v4.chriskrycho.com,2014-11-07:/2014/a-ridiculous-situation.htmlsoftware developmentThe Next Generation of Version Controlhttp://v4.chriskrycho.com/2014/next-gen-vcs.html<p>The current state of affairs in version control systems is a mess. To be sure, software development is <em>far</em> better with <em>any</em> of the distributed version control systems in play—the three big ones being <a href="http://git-scm.com">Git</a>, <a href="http://mercurial.selenic.com">Mercurial</a> (<code>hg</code>), and <a href="http://bazaar.canonical.com/en/">Bazaar</a> (<code>bzr</code>), with a few other names like <a href="http://www.fossil-scm.org">Fossil</a> floating around the periphery—than it ever was in a centralized version control system. There are definitely a few downsides for people converting over from some standard centralized version control systems, notably the increased number of steps in play to accomplish the same tasks.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> But on the whole, the advantages of being able to commit locally, have multiple complete copies of the repository, and share work without touching a centralized server far outweigh any downsides compared to the old centralized system.</p>
<p>That being so, my opening statement remains true, I think: <em>The current state of affairs in version control is a mess.</em> Here is what I mean: of those three major players (Git, Hg, and Bazaar), each has significant downsides relative to the others. Git is famously complex (even arcane), with a user interface design philosphy closely matching the UI sensibilities of Linus Torvalds—which is to say, all the wires are exposed, and it is about as user-hostile as it could be.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> It often outperforms Hg or Bazaar, but it has quirks, to say the very least. Hg and Bazaar both have <em>much</em> better designed user interfaces. They also have saner defaults (especially before the arrival of Git 2.0), and they have better branching models and approaches to history.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> They have substantially better documentation—perhaps especially so with Bazaar, but with either one a user can understand how to use the tool <em>without having to understand the mechanics of the tool</em>. This is simply not the case with Git, and while I <em>enjoy</em> knowing the mechanics of Git because I find them interesting, <em>having</em> to understand the mechanics of a tool to be able to use it is a problem.</p>
<p>But the other systems have their downsides relative, to Git, too. (I will focus on Hg because I have never used Bazaar beyond playing with it, though I have read a good bit of the documentation.) Mutable history in Git is valuable and useful at times; I have rewritten whole sequences of commits when I realized I committed the wrong things but hadn’t yet pushed.<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a> Being able to commit chunks instead of having to commit whole files at a go is good; I feel the lack of this every time I use Hg.<a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a> (Needing to understand the <em>file system</em> that Git invented to make sure you do not inadvertently destroy your repository is… not so good.) A staging area is nice,<a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a> (even if <em>having</em> to stage everything manually can be in the pain in the neck<a href="#fn7" class="footnote-ref" id="fnref7" role="doc-noteref"><sup>7</sup></a>).</p>
<p>In short, then, there was no clear winner for this generation. Each of the tools has significant upsides and downsides relative to the others. Git has become the <em>de facto</em> standard, but <em>not</em> because of its own superiority over the alternatives. Rather, it won because of other forces in the community. Mostly I mean <a href="https://github.com">GitHub</a>, which is a <em>fantastic</em> piece of software and easily the most significant driving factor in the wider adoption of Git as a tool. The competition (<a href="https://bitbucket.org">Bitbucket</a> and <a href="https://launchpad.net">Launchpad</a>) are nowhere near the same level of sophistication or elegance, and they certainly have not managed to foster the sorts of community that GitHub has. The result has been wide adoption of Git, and a degree of Stockholm Syndrome among developers who have adopted it and concluded that the way Git works is the way a distributed version control system <em>should</em> work.</p>
<p>It is not. Git is complicated to use and in need of tools for managing its complexity; the same is true of Hg and Bazaar, though perhaps to a slightly lesser extent because of their saner branching models. This is what has given rise to the <a href="http://nvie.com/posts/a-successful-git-branching-model/">plethora</a> of <a href="http://scottchacon.com/2011/08/31/github-flow.html">different</a> formal <a href="https://about.gitlab.com/2014/09/29/gitlab-flow/">workflows</a> representing various attempts to manage that complexity (which have been <a href="https://bitbucket.org/yujiewu/hgflow/wiki/Home">applied</a> to other systems <a href="https://andy.mehalick.com/2011/12/24/an-introduction-to-hgflow">as well</a>). Managing branching, linking that workflow to issues, and supplying associated documentation for projects have also cropped up as closely associated tasks— thus the popularity of GitHub issues and Bitbucket wikis, not to mention <a href="http://www.fossil-scm.org">Fossil’s</a> integration of both into the DVCS tool itself. None of the tools handle differences between file systems very elegantly (and indeed, it took <em>years</em> for Git even to be useable on Windows). All of them especially struggle to manage symlinks and executable flags.</p>
<p>So there is an enormous opportunity for the <em>next</em> generation of tools. Git, Hg, and so on are huge steps forward for developers from CVS, Visual SourceSafe, or SVN. But they still have major weaknesses, and there are many things that not only can but should be better. In brief, I would love for the next-generation version control system to be:</p>
<ul>
<li>distributed (this is now a non-negotiable);</li>
<li>fast;</li>
<li>well-documented—<em>at least</em> as well as Hg is, and preferably as well as Bazaar is;</li>
<li>well-designed, which is to say having a user interface that is actually a user-interface (like Hg’s) and not an extremely leaky abstraction around the mechanics;<a href="#fn8" class="footnote-ref" id="fnref8" role="doc-noteref"><sup>8</sup></a></li>
<li>fast;</li>
<li>file-system oriented, <em>not</em> diff-oriented: this is one of Git’s great strengths and the reason for a lot of its performance advantages;</li>
<li>extensible, with a good public API so that it is straightforward to add functionality like wikis, documentation, social interaction, and issue tracking in a way that actually integrates the tool;<a href="#fn9" class="footnote-ref" id="fnref9" role="doc-noteref"><sup>9</sup></a></li>
<li>and last but not least, truly cross-platform.</li>
</ul>
<p>That is a non-trivial task, but the first DVCS that manages to hit even a sizeable majority of these desires will gain a lot of traction in a hurry. The second generation of distributed version control has been good for us. The third could be magical.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>A point that was highlighted for me in a conversation a few months ago with my father, a programmer who has been using SVN for a <em>long</em> time and found the transition to Git distinctly less than wonderful.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Anyone who feels like arguing with me on this point should go spend five minutes laughing at the <a href="http://git-man-page-generator.lokaltog.net">fake man pages</a> instead.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>Few things are as hotly debated as the relative merits of the different systems’ branching models and approaches to history. At the least, I can say that Hg and Bazaar’s branching models are <em>more to my taste</em>.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn4" role="doc-endnote"><p>Yes, there are extensions that let you do this with Hg, but they are fragile at best in my experience, and substantially less capable than Git’s.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn5" role="doc-endnote"><p>Yes, I know about Hg’s record extension. No, it is <em>not</em> quite the same, especially because given the way it is implemented major GUI tools cannot support it without major chicanery.<a href="#fnref5" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn6" role="doc-endnote"><p>Yes, I know about Hg’s queue extension, too. There is a reason it is not turned on by default, and using it is substantially more arcane than Git’s staging are. Think about that for a minute.<a href="#fnref6" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn7" role="doc-endnote"><p>Yes, there is the <code>-a</code> flag. No, I do not want to have to remember it for every commit.<a href="#fnref7" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn8" role="doc-endnote"><p>Let’s be honest: if Git’s abstraction were a boat, it would sink. It’s just that leaky.<a href="#fnref8" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn9" role="doc-endnote"><p>GitHub does all of this quite well… but they have had to write heaps and gobs of software <em>around</em> Git to make it work.<a href="#fnref9" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoThu, 16 Oct 2014 21:45:00 -0400tag:v4.chriskrycho.com,2014-10-16:/2014/next-gen-vcs.htmlsoftware developmentPushing Into C's Corner Caseshttp://v4.chriskrycho.com/2014/pushing-into-cs-corner-cases.html<p>I’m working on a project that is all in C because of its long history and legacy. We’re slowly modernizing the codebase and writing all our new code in Python (using NumPy, C extensions, and so on for performance where necessary). Occasionally, I just want to bang my head against the wall because there are things we can do so simply in any modern language that you just can’t do in any straightforward way in C. For example, I have file writers that all work <em>exactly</em> the same way, with the single exception that the format string and the data that you put into it vary for each file.</p>
<p>In Python, this would be straightforward to handle with the class machinery: you could simply specify the format string in each inheriting class and define the data points to be supplied at the top of an overriding function, call the parent function with <code>super()</code> and be done.</p>
<p>To do something similar in pure C is nearly impossible. You can supply a format string with each function (or module, or however you separate out the code), and if you feel especially clever you could convert all your data types to strings and pass them as a list to be printed by the standard function. The net result would be <em>longer</em> and <em>less maintainable</em> than simply having a set of essentially-duplicate functions, though.</p>
Chris KrychoTue, 12 Aug 2014 09:00:00 -0400tag:v4.chriskrycho.com,2014-08-12:/2014/pushing-into-cs-corner-cases.htmlsoftware developmentThe Long Racehttp://v4.chriskrycho.com/2014/the-long-race.html<p>It has been too long since I have written anything—too long not for my audience (small as it is), but for my soul. The last few weeks of class were of course even busier than the rest of the semester, courtesy of a couple major assignments I wrapped up and studying for and taking finals, all while doing my normal work as a software developer on the side. Writing simply fell by the wayside, alas. Even my devotions posts simply didn’t happen. And that is all right; there are seasons for all of these things, and it is not as if I didn’t write many thousands of words in late April and early May. They simply were not <em>blogging</em> words.</p>
<p>So here I am tonight, writing simply to unwind. I spent much of the day working on various software projects—a pattern I expect to carry throughout the summer. In addition to my regular work for Quest Consultants Inc. back in Norman, I am picking up various web design and development jobs over the summer. God has been gracious in answering prayers for opportunities to pick up extra contracting work, and I have several really excellent opportunities to supplement my 20 hours a week for Quest with other work. That is nice not only financially, but also intellectually. The change of pace between different kinds of work helps me stay fresh on all of them. My own personal <a href="http://v4.chriskrycho.com/2014/a-little-crazy.html">side projects</a> are coming along slowly, but that is all right. Slow but steady is the best way to go about those kinds of projects anyway.</p>
<p>That lesson is one I have learned more and more from my ongoing and ever-increasing delight in running. So far in May I have run about 125 miles; I expect to run over 150 miles this month in total (though of course all such plans are always subject to revision, and never more so than when one’s wife is 37 weeks pregnant). I am now running easy, aerobic miles ten to fifteen seconds faster per mile than I could manage in my personal best half marathon time a few years ago. I run so (relatively) quickly now not because of any particular innate athleticism—quite the contrary, as anyone who has known me since high school can attest. I can run as far and fast as I do only because I have stuck with it and used a <a href="http://markallenonline.com/maoArticles.aspx?AID=2" title="Working Your Heart">smart training plan</a>. And really, as in most parts of life, it is that sticking-with-it that leads to getting somewhere. Of course, sticking with it is no guarantee that things will work out. It is usually a requisite step along the way, though—a necessary-though-insufficient condition. That is simply the way God built the world.</p>
<p>Little Ellie is quickly wrapping up her second year of life in this big world. She is saying lots of words (at last!), whining until she has driven Jaimie a bit crazy (in too-typical toddler fashion), and growing up in big ways and small. We are having a great deal of fun watching her start to be more socially aware and active, even if it is a little strange to have a daughter old enough that she has friends whom she loves and who love her in turn. She has also discovered a deep love of <em>Star Wars</em>—no surprise for a daughter of ours, though the intensity of her delight in the movies, for a girl who is not yet two years old, did surprise both Jaimie and me a bit. You should hear her try to say “Darth Vader” or “Dark Side” or “Star Wars.” It is impossibly adorable.</p>
<p>Jaimie is, as noted above, some 37 weeks pregnant and quite ready to be done carrying our second little gal on the inside. She is still plugging away slowly at the <a href="http://jaimiekrycho.com/shaking-epheria-pt-1/" title="Bloodlines: The Shaking of Epheria, Part I">second novella</a> in her <a href="http://www.amazon.com/Bloodlines-Epheria-The-Trilogy-ebook/dp/B00HY478QO/" title="Get Bloodlines of Epheria on Kindle!">Bloodlines</a> fantasy trilogy. She manages to keep Ellie entertained—no small feat—and does a remarkable job taking care of things around the house so that I can focus on work and school. Her struggle with <a href="http://2012-2013.chriskrycho.com/theology/marriage-depression/" title="Marriage and Depression">depression</a> has not diminished, but God has given us grace to carry on and she and I have both learned to respond in better, healthier, more helpful ways when the slumps come.</p>
<p>As for the future, we really have no idea what the next several yeras will hold. I plan to finish my Master of Divinity—Lord willing, around December 2016. In the meantime, we will keep raising our little girls, I will keep writing software, and we will keep exploring and seeing what we want to do and how best to pursue those desires in a way that honors God. Who knows what those years will hold? God only, and certainly not us.</p>
Chris KrychoSat, 24 May 2014 00:07:00 -0400tag:v4.chriskrycho.com,2014-05-24:/2014/the-long-race.htmlsoftware developmentfamilyfitnessA Little Crazyhttp://v4.chriskrycho.com/2014/a-little-crazy.html<p>I’m going to do something a little crazy, I’ve decided. I’m going to go ahead and do like I wrote <a href="http://v4.chriskrycho.com/2014/doing-it-myself.html">a bit back</a>, and make <a href="http://step-stool.io">Step Stool</a> actually a thing over the course of the rest of the year. Not so crazy. What is a bit nuts is the way I’ve decided to go about that process. In short: as close to the hardest way possible as I can conceive.</p>
<hr />
<p>Over the last couple weeks, I’ve been spending a fair bit of time toying with <a href="http://iolanguage.org">Io</a>. It’s a neat little language, very different in its approach to a <em>lot</em> of things than the languages I’ve used previously. My programming language history is very focused on the “normal” languages. The vast majority of real- world code I’ve written has been in one of C, PHP, or Python. I’ve done a good bit of Javascript along the way, more Fortran than anyone my age has any business having done, and a little each of Java and Ruby. Like I said: the normal ones. With the exception of Javascript, all of those are either standard imperative, object-oriented, or mixed imperative and object-oriented languages. Python and Ruby both let you mix in a fair bit of functional-style programming, and Javascript does a <em>lot</em> of that and tosses in prototypal inheritance to boot.</p>
<p>But still: they’re all pretty mainstream, “normal” languages. Io isn’t like that at all. For one thing, it’s hardly popular in any sense at all. Well-known among the hackers<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> I know, perhaps, but not popular by any measure. It’s small. And it’s very <em>alien</em> in some ways. It’s <a href="http://en.wikipedia.org/wiki/Prototype-based_programming">prototypal inheritance</a>, not normal inheritance. Courtesy of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">Javascript</a>, I have a <em>little</em> familiarity with that, but it’s definitely still not my default way of thinking about inheritance. Python’s inheritance model (the one I use most frequently) is <em>essentially</em> the same as that in C++, Java, PHP, and so on—it’s normal class-driven inheritance. Io goes off and does full-blown prototypal inheritance; even just the little I’ve played with it has been fun.</p>
<p>Io also does a bunch of other things a <em>lot</em> different from the other languages I’ve used. First, there are no keywords or—formally speaking—even operators in the language. Every action (including ones like <code>+</code> or <code>for</code>) is simply a message. Every value is an object (so <code>1.0</code> is just as fully an object as an arbitrarily-defined <code>Person</code>). The combination means that writing <code>1 + 2</code> is actually just interpreted as the object <code>1</code> receiving the <code>+</code> message carrying as its “argument” the <code>2</code> object (really just the message contents). This is <em>completely</em> different at a deep paradigm level from the normal object-oriented approach with object methods, even in a language like Python where all elements are objects (including functions). The net result isn’t necessarily particularly different from calling methods on objects, but it is a <em>little</em> different, with have some interesting consequences. Notably (though trivially—or at least, so it seems to me at this point), you can pass a message to the null object without it being an error. More importantly, the paradigm shift is illuminating.</p>
<p>Io also has far more capabilities in terms of concurrency than any of the other languagues with which I’m familiar, because it actively implements the <a href="http://en.wikipedia.org/wiki/Actor_model">Actor Model</a>, which means its implementation of messaging instead of object method calls can behave in concurrent ways. (I’d say more if I understood it better. I don’t yet, which is one of the reasons I want to study the language. Concurrency is very powerful, but it’s also fairly foreign to me.) It’s also like Lisp in that its code can be inspected and modified at runtime. I’ve wanted to learn a Lisp for several years for this kind of mental challenge, but the syntax has always just annoyed me too much ever to get there. Io will give me a lot of its benefits with a much more pleasant syntax. It has coroutines, which are new to me, and also helpful for concurrency.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<p>The long and short of it is that the language has a ton of features not present in the languages I have used, and—more importantly—is <em>paradigmatically</em> different from them. Just getting familiar with it by writing a goodly amount of code in it would be a good way to learn in practice a bunch of computer science concepts I never had a chance to learn formally.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<hr />
<p>By now, as long as I’ve rambled about Io, you’ve probably figured out where I was going in that first paragraph. I’ve decided to stretch my brain a bit and write Step Stool in Io. There are bunches of static site generators out there in Python already, many of them quite mature. (This site is running on <a href="https://github.com/getpelican">one of them</a> as of the time I write this post—it’s quite solid, even its quirks and limitations occasionally annoy me.) The point of Step Stool has always been twofold, though. First, I’ve wanted to get to a spot where I was really running my own software to manage my site, letting me do whatever I want with it and guaranteeing I always understand it well enough to make those kinds of changes. Second, I’ve just wanted to <em>learn</em> a whole bunch along the way. Third, it’s right there in the website link: <a href="http://step-stool.io">step-stool.io</a>! How could I pass up such an opportunity?</p>
<p>It is that second goal that has pushed me to do this crazy project this crazy way. It’s crazier than just teaching myself a language in order to do the static site generator itself, too, because there are a few other pieces missing that I’ll need to write to make this work… like a Markdown implementation and an HTML templating language. I’ve never written anything remotely like either before, so I’m going to take the chance to learn a <em>lot</em> of new things. For the Markdown implementation, rather than relying on regular expression parsing (like most Markdowns do), I’m going to use a Parsing Expression Grammar. That will certainly be more efficient and reliable, but—more importantly—it is also outside my experience. I have yet to start thinking through how to tackle the HTML templating language implementation (though I know I am going to make it an Io implementation of <a href="http://slim-lang.com">Slim</a>, which I quite like).</p>
<p>In any case, I’m going to be taking a good bit longer to get Step Stool finished. That is all right: I am going to learn a ton along the way, and I am quite sure I will have a blast doing it. And that is <em>exactly</em> what these kinds of projects are for.</p>
<p>I’ll post updates as I go, with the things I’m learning along the way. Hopefully they’ll be interesting (or at least entertaining).</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Hackers in the original sense of the world. Not “crackers”, but people who like hacking on code, figuring things out the hard way.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Python 3.5 is actually adding coroutines, and I’m excited about that. I’ll feel much more comfortable with them there having used them in Io, I’m sure!<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>I got here backwards, as it were—by way of an undergraduate degree in physics. I don’t regret that for a second: I got a much broader education than I could have managed while getting an engineering degree, and most importantly learned <em>how to learn</em>: easily the most important skill anyone gains from any engineering degree.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoTue, 29 Apr 2014 19:30:00 -0400tag:v4.chriskrycho.com,2014-04-29:/2014/a-little-crazy.htmlsoftware developmentLearning QML, Part 1http://v4.chriskrycho.com/2014/learning-qml-part-1.html<p>For part of my work with Quest Consultants, I’ve been picking up Qt’s QML toolkit to use in building out the UI. The declarative syntax and ability to define one’s own model in non-C++- or Python-specific ways is quite nice. That said, the learning process has had more than a few bumps along the way. I decided to go ahead and write those up as I go, both for my own reference and in the hope that it may prove useful to others as I go.</p>
<p>QML is a <em>Javascript-like</em> language for <em>declarative programming</em> of a user interface. So it’s a Javascript-based language that sort of behaves like HTML. In fact, it behaves like Javascript in terms of how you define, access, and update properties, and you can embed full-featured (mostly) Javascript functions and objects in it.</p>
<p>But when you have nested QML Types, you end up with them behaving more like HTML.</p>
<p>The weirdest bit, and the thing that I’m having the hardest time adjusting to, is that you can only edit properties of root Types when you’re working with an instance of that Type. And those Types are defined by <em>documents</em>.</p>
<p>So, to give the simplest possible example, let’s say I defined a new type called <code>Monkey</code>, in the <code>Monkey.qml</code> file, like this:</p>
<pre><code>// Monkey.qml
import QtQuick 1.1
Item {
id: monkey_root
property int monkey_id: -1
property string monkey_name: &quot;I don&#39;t have a name!&quot;
Item {
id: monkey_foot
property string monkey_foot_desc: &quot;The monkey has a foot!&quot;
}
}</code></pre>
<p>I can use that in another file. If they’re in the same directory, it’s automatically imported, so I can just do something like this:</p>
<pre><code>//main.qml
import QtQuick 1.1
// Rectangle is exactly what it sounds like. Here we can display things.
Rectangle {
id: the_basic_shape
height: 400
width: 400
color: green
Monkey {
id: monkey_instance
monkey_id = 42
monkey_name = &quot;George&quot; // he&#39;s kind of a curious little guy
}
Text {
text: monkey_instance.monkey_name
color: &quot;red&quot;
}
}</code></pre>
<p>That creates a (really ugly) rectangle that prints the <code>Monkey</code>’s name in red text on a green background. It’s impossible to access directly the <code>monkey_foot</code> element, though, which means that composing more complex objects in reusable ways is difficult. In fact, I haven’t come up with a particularly good way to do it yet. At least, I should say that I haven’t come up with a good way to create high-level reusable components yet. I can see pretty easily how to create low-level reusable components, but once you start putting them together in any <em>specific</em> way, you can’t recompose them in other ways.</p>
<p>From what I’ve gotten my head around so far, this ends up being less flexible than either HTML templating languages (which are, or at least can be, completely declarative) or normal Javascript (which is obviously <em>not</em> declarative). Mind you, it’s all sorts of <em>interesting</em>, and I have a pretty decent idea what I’m going to do to implement our UI with it, but it’s taken me most of the day to get a good handle on that, and my head still feels a bit funny whenever I’m trying to see how best to create composable components.</p>
<p>Note, too, that this is the <em>only</em> way to create a new basic type of object in QML: it has to be the root level object in a QML document. I would <em>really</em> like to be able to access internal declarations—to have named internal types/objects. Unfortunately, QML doesn’t let you do this. I suspect this has to do with how the QML type system works: it actually binds these types to C++ objects behind the scenes. This is a non-trivially helpful decision in terms of the performance of the application, but it certainly makes my brain a little bit twitchy.</p>
<p>There are two basic consequences of this structure. First, any types you need to be able to use in other QML objects have to be defined in their own QML documents. Second, it is (as near as I can see so far, at least) difficult to create good generic QML types of more complex structures that you can then use to implement specific variations. For example: if you want to create accordions, you can create a fair number of the low-level elements in generic ways that you can reuse, but once you get to the relationships between the actual model, delegate, and view elements, you will need to create them in custom forms for each distinct approach.</p>
<p>This is more like creating HTML documents than Javascript, which makes sense, <em>if</em> you remember that QML is Javascript-based but <em>declarative</em>. You just have to remember that while you can define some reusable components, the full-fledged elements are like full HTML pages with a templating system: you can include elements, but not override their internal contents. In QML, you can override <em>some</em> of their contents, which is nice—but that is not the primary way to go about it.</p>
Chris KrychoFri, 11 Apr 2014 15:30:00 -0400tag:v4.chriskrycho.com,2014-04-11:/2014/learning-qml-part-1.htmlsoftware developmentFeels Righthttp://v4.chriskrycho.com/2014/feels-right.html<p>I had spent most of the last week and a half working on getting <a href="http://www.firebirdsql.org">FirebirdSQL</a> configured and ready to use for a project I’m working on with <a href="http://www.questconsult.com">Quest Consultants</a>. It was slow going. The tool is decent, but the documentation is spotty and it felt like everything was just a bit of a slog—to get it working correctly, to get it playing nicely with other pieces of the development puzzle, to get it working across platforms.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> Then, because I had done something a <em>little</em> bit silly in my eagerness to get up and going last week and written code without a testable configuration, I hit a wall today. The queries weren’t working. I had made a <a href="http://stackoverflow.com/questions/22865573/sqlalchemy-successful-insertion-but-then-raises-an-exception">bug</a>.</p>
<p>I spent a substantial part of the day chasing down that bug, and then a conversation with user <em>agronholm</em> on the <a href="http://docs.sqlalchemy.org/en/rel_0_9/">SQLAlchemy</a> IRC channel (<a href="irc://irc.freenode.net/sqlalchemy">freenode/#sqlalchemy</a>) got me thinking. The Firebird team describes one of their options as an “embedded” server, but <em>agronholm</em> pointed out that what they really mean is <em>portable</em>. It’s running a standalone server and client, but it’s not part of the same thread/process (like SQLite is). Then <em>agronholm</em> very helpfully asked—my having mentioned my preference for <a href="http://www.postgresql.org">PostgreSQL</a> earlier—“Does Postgres not have a portable version?” Two minutes later, we had both found <a href="http://sourceforge.net/projects/postgresqlportable/">PostgreSQL Portable</a>, and I rejoiced.</p>
<p>It took me less than half an hour to get it downloaded and set up and to confirm that it would work the way we need for this particular piece of software. (Firebird had taken me a good three hours, what with digging through badly organized and not terribly clear documentation.) It took me less than half an hour more to get PostgreSQL to the same point that I’d finally gotten Firebird to after multiple hours working with it. And I was so <em>very</em> happy. What had been an especially frustrating work day now had me quietly smiling to myself constantly for the last two and a half hours as I <a href="http://stackoverflow.com/questions/22865573/sqlalchemy-successful-insertion-but-then-raises-an-exception/22872598#22872598">finished</a> tracking down the bug that had set me on this path in the first place.</p>
<p>Several years ago, when I first started doing web development, I got my feet wet in database work with MySQL—probably the single most common starting point for anyone going that route, courtesy of the ubiquity of the standard Linux-Apache- MySQL-PHP stack.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> A year after that, I picked up some work that was already using PostgreSQL and fell in love almost immediately.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> Something just felt <em>better</em> about running <code>psql</code> than running <code>mysql</code> on the command line. Postgres’ implementation of the SQL standard felt more natural. Even the tiniest little details like the way tables display when you query them in <code>psql</code> was nicer. In less than a week, I was sold and haven’t looked back. While I’ve used MySQL out of convenience on shared hosting from time to time, PostgreSQL is unquestionably my preferred database target.</p>
<p>Today’s experience brought that all home again. That grin on my face all afternoon felt a bit silly, but it highlights the difference that really good software design makes. I am not just talking about how it looks here—though, to be sure, PostgreSQL is prettier than FirebirdSQL—but how it works. PostgreSQL feels responsive, its command set makes a lot of sense and is easy to use, and it is <em>extremely</em> well documented. In fact, I would go so far as to say that it is the best documented open source software I have ever used, as well as among the very most robust. (The only other open source software I find to be as incredibly rock-solid and reliable as PostgreSQL is the Linux kernel. I am by no means an expert on either, or on open source software in general, but the Linux kernel is an unarguably amazing piece of work. So is PostgreSQL.) All those tiny little details add up.</p>
<p>It’s a good reminder for me as I write software that yes, the things I care about—the small matters that would be so easy to overlook when customers express no interest in them—really do matter. People may not know that things like typography make a difference in their experience, but those subtle, often imperceptible things matter. They may not consciously notice the differences in your interface design (even a command line interface), but it will change their experience of the software. Do it poorly, or even in a just-good-enough-to-get- by fashion, and you’ll annoy or simply bore them. Do it well, and you might just delight them—even if they can’t tell you why.</p>
<hr />
<section id="examples" class="level2">
<h2>Examples</h2>
<p>To make my point a little more visible, I thought it might be useful to post samples of SQL to accomplish the same task in the two different database dialects.</p>
<section id="firebirdsql4" class="level3">
<h3>FirebirdSQL:<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></h3>
<pre><code>CREATE TABLE projects (
id INT NOT NULL PRIMARY KEY,
title VARCHAR(32) NOT NULL,
file_name VARCHAR(32) NOT NULL,
file_location VARCHAR(256) NOT NULL,
CONSTRAINT unique_file UNIQUE (file_name, file_location)
);
CREATE SEQUENCE project_id_sequence;
SET TERM + ;
CREATE TRIGGER project_id_sequence_update
ACTIVE BEFORE INSERT OR UPDATE POSITION 0
ON projects
AS
BEGIN
IF ((new.id IS NULL) OR (new.id = 0))
THEN new.id = NEXT VALUE FOR project_id_sequence;
END+
SET TERM ; +</code></pre>
</section>
<section id="postgresql" class="level3">
<h3>PostgreSQL</h3>
<pre><code>CREATE TABLE projects (
id SERIAL NOT NULL PRIMARY KEY,
title VARCHAR(32) NOT NULL,
file_name VARCHAR(32) NOT NULL,
file_location VARCHAR(256) NOT NULL,
CONSTRAINT unique_file UNIQUE (file_name, file_location)
);</code></pre>
<p>It is not just that the PostgreSQL example is shorter and clearer—it is that it is shorter and clearer because its designers and developers have taken the time to make sure that the shorter, cleaner way works well, and have documented it so you can know how to use that shorter cleaner way without too much difficulty.</p>
</section>
</section>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I do most of my development on a Mac, but do all the testing on the target platform (Windows) in a VM.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>At this point, I would only use one of those by default if I were building a web app: Linux. I’d use <a href="http://wiki.nginx.org/Main">nginx</a> instead of Apache, <a href="http://www.postgresql.org">PostgreSQL</a> instead of MySQL, and <a href="https://www.python.org">Python</a> (though <a href="https://www.ruby-lang.org/">Ruby</a>, Javascript via <a href="http://nodejs.org">node.js</a>, <a href="http://msdn.microsoft.com/en-us/vstudio/hh341490">C# and the .NET stack</a>, or just about anything <em>but</em> PHP would do fine).<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p><em>Almost</em> immediately because at that point configuration on OS X was a bit of a pain. That is <a href="http://postgresapp.com" title="Postgres.app">no longer the case</a>.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn4" role="doc-endnote"><p>To be perfectly fair to Firebird, it is improving. The upcoming 3.0 series release will make these two a lot more similar than they are at present, and clean up a number of other issues. What it won’t do is get the <em>feel</em> of using Firebird more like that of using Postgres, or make the installation procedure smoother or easier, or make the documentation more complete.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 04 Apr 2014 21:30:00 -0400tag:v4.chriskrycho.com,2014-04-04:/2014/feels-right.htmlsoftware developmentdesignFirebirdSQL and IntelliJ IDEA (etc.)http://v4.chriskrycho.com/2014/firebirdsql-and-intellij-idea-etc.html<p>Setting up IntelliJ IDEA’s built-in database tools to work with FirebirdSQL requires a particular setup configuration, which I’m documenting here for public consumption.</p>
<p>These setup tools <em>should</em> be applicable to any of JetBrains’ other Java-based IDEs which include database support (e.g. PyCharm, RubyMine, WebStorm, etc.). <em>Note:</em> the following apply to IntelliJ IDEA 12 and the associated platforms, but <em>not</em> to the IDEA 13 platform, which made substantial changes to how databases are configured. The underlying details are consistent, but the interface has changed. I have tested on PyCharm 3.1 to confirm that.</p>
<p>This was all done on OS X 10.9, so I also make no guarantees that this works on other platforms, though the likelihood that it behaves the same on Linux is fairly good. I will update the post if and when I have confirmed that it does.</p>
<p>Steps to configuring a database correctly for use with IDEA/etc. Note that steps 1–3 are fairly obvious; the real point of interest is in steps 4 and 5, which took me the longest time to figure out.</p>
<ol type="1">
<li><p>Download the latest version of the Firebird <a href="http://www.firebirdsql.org/en/jdbc-driver/">Java drivers</a> for your operating system and your Java version. (You can check your Java version by running <code>java -version</code> at the command line.) Extract the downloaded zip file. The extracted folder should include a file named <code>jaybird-full-&lt;version&gt;.jar</code> (<code>&lt;version&gt;</code> is currently 2.2.4).</p></li>
<li><p>In IDEA, in the database view, add a new data source: in the Database view (accessible via a menu button on the right side of the screen), right click and choose <strong>New -&gt; Data Source</strong>.</p></li>
<li><p>Under <strong>JDBC driver files</strong>, browse to the location where you extracted the Jaybird driver files and select <code>jaybird-full-&lt;version&gt;.jar</code>.</p></li>
<li><p>Under <strong>JDBC driver class</strong>, choose <code>org.firebirdsql.jdbc.FBDriver</code>.</p></li>
<li><p>Under <strong>Database URL</strong>, specify <code>jdbc:firebirdsql://localhost:3050/</code> followed by <em>either</em> the full path to the database in question or a corresponding alias.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> A full path might look like this on Windows:</p>
<pre><code>jdbc:firebirdsql://localhost:3050/C:/my_project/the_database.db</code></pre>
<p>With an alias, you would instead have:</p>
<pre><code>jdbc:firebirdsql://localhost:3050/the_alias</code></pre>
<p>Then specify valid values for the <strong>User</strong> and <strong>Password</strong> fields from your existing configuration of the database.</p></li>
<li><p>Click the <strong>Test Connection</strong> button and make sure the configuration works.</p></li>
</ol>
<p>That should do it. Note that the driver choice and path configuration both matter. On OS X, I found that only the <code>FBDriver</code> with this (and one other, older-style and therefore not recommended) path setup worked successfully.</p>
<p>Observations, corrections, additional information, and miscellaneous comments welcomed on <a href="https://alpha.app.net/chriskrycho">App.net</a> or <a href="https://www.twitter.com/chriskrycho">Twitter</a>.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I strongly recommend configuring an alias in the aliases.conf file in the Firebird home directory (usually set as <code>$FIREBIRD_HOME</code> during installation on *nix systems). This lets you move the database around at will, update just the configuration file, and not have to update any references to the database file whatsoever.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 28 Mar 2014 09:00:00 -0400tag:v4.chriskrycho.com,2014-03-28:/2014/firebirdsql-and-intellij-idea-etc.htmlSoftware DevelopmentThe End of Surfinghttp://v4.chriskrycho.com/2014/the-end-of-surfing.html<p>Sometime in the last few months it occurred to me that I no longer “surf” the internet. I read, to be sure, and every once in a long while I even go on a spree where I follow links from one site to another (or just in a long trail on Wikipedia). In general, however, I no longer surf. I suspect I am not alone in this: if we took a straw poll I would venture that most of my friends offline and acquaintances online alike spend rather less time in “browsing” mode than they do reading Facebook or Twitter or Instagram. Motion from link to link has been replaced by individual hops out onto Buzzfeed or a viral cat picture website.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>The obvious explanation for all of this is already there in what I’ve written: Facebook and Twitter and all the rest of the social media web. To be sure, the advent of social media and the increasing degree to which social media have captured user attention on the web are a significant factor in the end of the old surfing/browsing behavior. This is a dream come true for those social media giants which have found ways to deliver ads to their many millions of users and thereby turn enormous profits.</p>
<p>At the same time, I think there is an oft-overlooked factor in the shifting nature of the web over the last decade: the browser. In fact, if there is any single cause behind the death of old-fashioned surfing, I would point to Firefox 1.0: the browser which popularized tabbed browsing to increasingly large sections of the internet-using public.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> The open-source browser steadily ate away at Internet Explorer’s then absurd levels of dominance, until Internet Explorer 8 included of tabs itself. By the time that Chrome came on the scene, tabbed browsing had long since become a given.</p>
<p>So why do I think that <em>tabbed browsing</em> of all things contributed to the end of “browsing” and “surfing” as our dominant mode of reading the internet? Simply put: it broke linearity. Previously,<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> one’s experience of the web was single- stranded, leaping from one point to another in a line that however contorted was always connected by the forward and backward buttons on the browser. The moment tabbed browsing came on the scene, that line was broken. Following a link might mean it opened in a new tab instead of moving the whole view forward to it.</p>
<p>Surfing as I remember it in the late ’90s and early ’00s was inherently the experience of getting lost along that timeline, finding myself dozens of links along the chain and wondering how I had ended up there, and then being able to trace my way back. With tabs, that traceability was gone. With it went the inherent tension that we faced with every link: to follow, or not? To get sucked down into <em>this</em> vortex or <em>that</em>? Because in all likelihood, we knew, we were not going to be coming back to this page. With tabs, though, I could open both of those pages without ever leaving this one. I could start new journeys without ending the old. But there was a hidden cost: that newly opened tab had no history. It was a clean slate; before that newly opened link there was only a blank page. If I closed the original from which I had opened it, there was no going back.<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a> If I closed this new tabs, there was no going forward to them. The line was broken.</p>
<p>From there it was only a short step to the idea of a single site being the center from which one ventured out to other points on the web before returning: the Facebooks and Twitters of the world. In some sense, Facebook’s entire model is predicated on the idea that it is natural to open a new tab with that juicy Buzzfeed content while keeping Facebook itself open in a background tab. Would it work in that old linear model? Sort of. Would it feel natural? Never.</p>
<p>All of this because of tabs. Invention’s most significant results are rarely those the minds behind it expect. When we are designing things—whether a piece of furniture or a piece of the web—we have to remember that design decisions all have repercussions that we may not see. Technology is never neutral. Particular innovations may or may not be <em>morally</em> significant, but they always produce changes in people’s behavior. Design has consequences.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>For the record, lots of that hopping from link to link was on Buzzfeed- like and viral-cat-picture-like sites, too. I am not concerned with the <em>kind</em> of content being read here, so much as the way it is being read.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Note that I am not crediting Firefox 1.0 with <em>creating</em> the tabbed browser—only with popularizing it. That distinction matters.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn3" role="doc-endnote"><p>Excepting having multiple browser windows open, which I am sure people did—but to a much lesser extent.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn4" role="doc-endnote"><p>Yes, yes, browser history and re-open closed tab commands. But the <em>experience</em> of those is different, and that’s what we’re talking about here.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoWed, 26 Mar 2014 20:00:00 -0400tag:v4.chriskrycho.com,2014-03-26:/2014/the-end-of-surfing.htmldesignsoftware developmentDoing It Myselfhttp://v4.chriskrycho.com/2014/doing-it-myself.html<p>Last summer, I started work on a project I named <a href="http://step-stool.io">Step Stool</a>—aiming to make a static site generator that would tick of all the little boxes marking my desires for a website generator. In due time, the project got put on hold, as I started up classes again and needed to focus more on my family than on fun side projects.</p>
<p>Come the beginning of 2014, I was ready to bit WordPress farewell once and for all, though. While <a href="https://ghost.org">Ghost</a> looks interesting, since I do all my writing in Markdown files, there is something tempting about the canonical version of the documents being the version on my computer (and thus also on my iPad and iPhone and anywhere I have Dropbox and/or Git access). I did not have time at the beginning of the year to finish writing Step Stool, and I knew as much,<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> so instead I moved to <a href="http://docs.getpelican.com/en/3.3.0/">Pelican</a> as a stop-gap. There were lots of good reasons to pick Pelican: it has an active development community, fairly thorough documentation,<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> and it’s in Python and uses Jinja2 templates—the same basic approach I had taken with Step Stool, and the same toolset.</p>
<p>Unfortunately, while I have been glad to be away from WordPress, my experience with Pelican so far has only reinforced my desire to get Step Stool done. There are <em>lots</em> of little things that it does in ways that just annoy me. Many of them have to do with configuration and documentation. On the latter, while the documentation is <em>fairly</em> complete, there are quite a few holes and gaps. (Yes, yes, open source software and anyone can add to the docs. That’s great—it really is—but if I’m going to use someone else’s solution, it had better <em>just work</em>. Otherwise, I’d rather spend my time getting my own going.)</p>
<p>For example, if you want to see how the pagination actually works, good luck figuring it out from the documentation. You’ll need to go looking at the way the sample themes (yes, both of them) are implemented to start getting a feel for it. Along the same lines, many of the objects that get handed to the templates are not fully documented, so it is difficult to know what one can or cannot do. I do not particularly want to spend my time adding debug print statements to my templates just to figure out what options I have available.</p>
<p>The same kinds of things hold true for configuration options. Moreover, the configuration is done through a Python module. While that makes the module easier to integrate on the code side of things, it makes its actual content much less transparent than one might hope. Python is not really well optimized for writing configuration files—nor is any normal programming language. Configuration is inherently declarative, rather than imperative.</p>
<p>This is not to say that Pelican is bad software. It is not. It is, however, a fairly typical example of open source software implemented by committee. It has holes (some of them serious), bumps, and quirks. Here is the reality: so will Step Stool, though they will be the quirks that come from an individual developer’s approach rather than a group’s. But the one thing I can guarantee, and the reason I am increasingly motivated to get back to working on Step Stool. And yes, I do have a couple other projects on my plate as well—contributions to the Smartypants and Typogrify modules, my own <a href="https://bitbucket.org/chriskrycho/spacewell">Spacewell typography project</a>, and quite possibly a <a href="https://bitbucket.org/chriskrycho/markdown-poetry/">Markdown Poetry extension</a>. But I would like very much to just get back to doing this myself. There is freedom in rolling my own solution to things. I will not always have time to do these kinds of things; I figure I should do them when I can.</p>
<p>So here’s to <a href="http://step-stool.io">Step Stool</a>, and—more importantly—to writing your own software just to scratch that itch.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>I spent quite a bit of time tweaking my friend Vernon King’s <a href="http://www.vernonking.org">Jekyll-powered site</a>, I got Winning Slowly off the ground, including designing the site from scratch and implementing it (also in Pelican), and I did some substantial redesign work on this site. That was more than enough for my three week break—as evidenced by the fact that I didn’t get to the sort of 1.0 version of this site until just a week or so ago.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩</a></p></li>
<li id="fn2" role="doc-endnote"><p>Emphasis on “fairly.” More on <em>that</em> in a moment as well.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩</a></p></li>
</ol>
</section>
Chris KrychoFri, 21 Mar 2014 22:14:00 -0400tag:v4.chriskrycho.com,2014-03-21:/2014/doing-it-myself.htmlsoftware development