Thursday, January 11, 2018

Quick Terminal/iTerm2 Hack

My shell prompt uses unix status codes to either return a go-get-em Unicode smiley, when everything's going well, or a shrug, when a command failed.

To get this into my shell prompt, I use a shell prompt function, which sets than the usual $PS1 environment variable. You need the function because it sets the value of $PS1 every time something changes. This also makes it easy to, for example, display whatever git user, or set of users, I happen to "be," since I use git pair.

A nice side effect is that you can call arbitrary functions in there. tab-title $(this) sets the title of the Terminal or iTerm2 tab to whatever my current git branch name is. Since the shell prompt function is executed every time my shell needs to display a new prompt, the tab title updates every time I change git branches.

A couple notes: first, as you might guess from the comment, I found the code for tab-title on the big wide Web somewhere. Second, this is a function I wrote years ago, when it was difficult to get git branch names on the command line. I think there are easier ways to do it now.

Saturday, December 30, 2017

Pricing Cryptocurrencies Is Basically Impossible

This is NOT investment advice. This is a web developer, with no background in economics or finance, thinking out loud.

With the price of bitcoin skyrocketing, and other cryptocurrencies following it up, there's a pretty obvious question: what are cryptocurrencies actually worth?

Back in the day, Rick Falkvinge argued that bitcoin's killer app was international money transfers, and, therefore, that the total value of all bitcoin in circulation should be equal to the total value of the international money transfer market, which he estimated at 1% of total money in circulation. I liked this argument and found it compelling enough to buy a few bitcoins at $14 (which I then sold at around $60, because at the time I didn't take it seriously). But there are multiple problems with this argument.

The first is that there are many other cryptocurrencies in circulation, and bitcoin's value would have to be determined not only relative to its use case, but also relative to competing cryptocurrencies which were similarly well-suited for that use case. The second problem is that Falkvinge compared money currently in circulation with the total number of bitcoin expected to ever exist. The third problem is that this is basically a streetlight effect. There's no compelling argument that I'm aware of which makes the case that international money transfers are the only use case for Bitcoin specifically or cryptocurrencies in general. Logically, even if Falkvinge's argument is correct — which I don't know for sure — since there are probably other use cases, the total value of all cryptocurrency in circulation should be greater than the total value of the international money transfer market.

And again, that's the value of cryptocurrency in general, not bitcoin in particular.

Another, equally inconclusive way to estimate bitcoin's value is to look at how the market behaves when there are no compelling reasons to suspect that influential pump-and-dump scams are underway. In a YouTube video, economist Neil Gandal charts the impact of two such pricing scams. This was in a presentation given at an academic conference on blockchains at Berkeley in September; bitcoin's subsequent surge in price also arouses serious pump-and-dump questions. If you look at the time period free of pump-and-dump scams, however, you see a range from around $300 to $500 per bitcoin. A person could argue that this is the "true" price of bitcoin, but removing fradulent influences from an analysis does not magically grant omniscience to the remaining market participants, especially not in the context of an emerging technology with untested potential, so this argument is still very flawed.

A further compounding factor in any attempt to come up with a plausible price for cryptocurrencies is that the prices of cryptocurrencies in general go up whenever the price of bitcoin goes up. You might believe, for example, that blockchain applications hold sufficient potential to justify at least some optimism re: cryptocurrencies, and that Ethereum is a much more sophisticated platform for building these applications than Bitcoin. But you don't see the price of Ether go up when the price of bitcoin goes down. The market reflects surges in optimism and skepticism re: the general topic far more than relative evaluations of the different instances of the concept. And it's an apples to oranges comparison anyway; not only do the tokens exist in different quantities, but also, bitcoin has an absolute limit on the number of coins produced (unless the network changes its mind about that), while Ethereum plans to always release new Ether.

With all this, it's essentially impossible to invest responsibly in cryptocurrency, since the uncertainty is so high that there's no way to determine any plausible "correct" price for the stuff. Falkvinge's argument for a million-dollar bitcoin value was basically this: take 1% to 10% of the (loosely estimated) total money currently in supply, worldwide — which he says is $60 trillion — and match it against the finite limit of about 6 million bitcoins that will eventually ever be in circulation. But this is apples to oranges again: a projected number in the future (bitcoin in circulation) vs. a number (very loosely) based on today's economy. And even if this math were flawless, coinmarketcap.com estimates that the current dollar value of cryptocurrency in circulation is $568,661,188,172.

So, using a modified version of Falkvinge's argument, if the total value of cryptocurrency should ultimately be 1% of $60 trillion, well, hooray, the future is already here. One percent of $60 trillion is $600,000,000,000, which is essentially how much money is in cryptocurrency right now — although that's including bitcoin prices which arguably appear to be artificially inflated via a scam involving Tether. Falkvinge's argument included an enormous fudge factor: basically, if bitcoin is ever used for anything above and beyond international money transfer, then its total share of the money supply could go up from 1% to as high as 10%. Although Falkvinge was by far the most disciplined thinker in bitcoin at the time, this is still not a super rigorous approach. He basically pulled that order of magnitude fudge factor straight out of his ass.

So it could be that we've reached the useful limit of cryptocurrency in circulation, and it could be that we're only one-tenth of the way there. It could be that we have the "correct" amount of money in the sector, but it's not allocated to the "correct" coins. Plenty of other interpretations exist, and might be true instead. This is just the degree of certainty we get from the only analysis I've seen that ever even tried to do any math; more mainstream commentators seem to go with "we don't know yet" and call it a day, and that does seem to me to be a more realistic approach. If the only math you can do involves made-up numbers, it's better to admit you don't have enough information to make a precise estimate.

The best lens I've seen for guessing at the values of cryptocurrencies comes from Twitter snark. A popular trend in snarking about bitcoin in particular is to say that it's like a 1990s dot-com stock, except without a company attached. This is supposed to be a dis but it's easily the most flattering thing you can say about cryptocurrencies. If I could have bought Rails stock back in 2005, I would have. To me, the uncertainty in Internet stocks has always been the companies attached; the underlying open source technologies are much easier to evaluate. From that point of view, bitcoin looks like Java; it sucks, but people are going to build a lot of stuff with it. And Ethereum reminds me of SmallTalk; it's trying to build too much of a world around itself to ever really become what it wants to be, but it's still an impressive leap forward.

This is all very much not investment advice. But I am totally qualified to give you advice on how to talk about tech without sounding like a jackass, even if I haven't always followed that advice myself. So here's some advice in that vein: if you're a dev and you're curious about cryptocurrencies, read the whitepapers and look at the code. Although the dot-com crash was overall a very overdue market correction, which cleared out a bunch of trash companies and let the real leaders emerge, at the same time, plenty of complete idiots made a mint during the dot-com boom, and plenty of great technologies tanked in the crash. The only certainty in any of this is that randomness will play a part. But if you know which cryptocurrencies are better designed than others, it'll at least be a useful piece of the picture. It might make all the difference in the world.

Saturday, August 5, 2017

Drive Refactors with a Git Pre-Push Hook

When I'm writing code, if I see something I want to fix, I write a quick FIXME comment. When I'm working on my own projects, this is no big deal. But I don't like adding FIXMEs to code at work, or in open source repos. And really, I prefer not to keep them hanging around in my own repos, either. So I set up a git pre-push hook. It looks like this:

 ᕕ(ᐛ)ᕗ cat .git/hooks/pre-push
#!/bin/bash

if ag fixme . -i --ignore tmp/ --ignore log/ --ignore node_modules/ --ignore vendor/; then
  echo
  echo 'not pushing! clean up your fixmes'
  echo
  exit 1
else
  exit 0
fi

This code uses ag to make sure that there are no FIXMEs in my code, skipping dependency directories since they're not my problem, and either returns a Unix failure code, interrupting the push, if FIXMEs are present, or a success code, allowing the push to proceed, if they aren't.

In other words, if I tell git to push code which contains a FIXME, git effectively says no.

This worked well for a while. But soon, at work, somebody else added a FIXME to a repo. So I commented out my hook for a few days or weeks, and then, when I had a spare second, I fixed their FIXME. But soon enough, somebody else added a FIXME, and it was harder to fix. So I commented out the hook, and forgot all about it.

Eventually, though, I had to do some pretty complicated work, and I generated a lot of FIXMEs in the process. As an emergency hack, I uncommented the hook, did my main work, tried to push my branch, and got automatically chastised for trying to push a FIXME. So I went in, fixed them, and pushed the branch.

This is my routine now. If I'm dealing with a big enough chunk of work that I can't take a break to fix a FIXME, I just uncomment the hook for the period of time that I'm working on that topic branch. It's a really good way to stay on task while also putting together a to-do list for refactoring. You basically can't finish the branch until you go through the FIXME to-do list, but you're 100% free to ignore that to-do list, and focus on the primary task, until it's time to push the branch. So you can easily build refactoring into every topic branch without getting distracted (which is the primary risk of refactoring as you go).

It's probably pretty easy to modify this hook so that it only looks at unstaged changes, so I might do that later on, but it works pretty well as a habit already.

Sunday, June 4, 2017

Reddit Users Are A Subset Of Reddit Users

An interesting blog post on view counting at Reddit reminded me of an old post I wrote almost ten years ago. Reddit engineer Krishnan Chandra wrote:

Reddit has many visitors that consume content without voting or commenting. We wanted to build a system that could capture this activity by counting the number of views a post received.

He goes on to describe the scaling and accuracy problems in this apparently simple goal. But he never addresses a few really weird assumptions the Reddit team appears to have made: that every Reddit user is logged in, or even has an account in the first place; that every Reddit user has only one account; and that every account is only ever used by one person.

As I wrote back in the ancient days of 2008:

Assuming a one-to-one mapping between users and people utterly disregards practical experience and common sense. One human could represent themselves to your system with several logins. Several humans could represent themselves as one login. Both these things could happen. Both these things probably will happen.

In other words, "users" aren't real. Accounts and logins are real. The people who use those accounts and logins are also real. But the concept of "users" is a social fiction, and that includes the one-to-one mapping "users" implies between accounts and people. In some corners of the vast Reddit universe, creating more than one "user" per account is as common as it is in World of Warcraft.

As I say, this is all from a blog post back in 2008. More recently, in 2016, I decided that the best way to use Reddit (and Hacker News as well) is without logging in. In other words, the best use case is not to be a "user":

reading Reddit without logging in is much, much more pleasant than being a "user" of the site in the official sense. The same is true of Hacker News; I don't get a lot out of logging in and "participating" in the way that is officially expected and encouraged. Like most people who use Hacker News, I prefer to glance at the list of stories without logging in, briefly view one or two links, and then snark about it on Twitter...

neither of these sites seems to acknowledge that using the sites without being a "user" is a use case which exists. In the terms of both sites, a "user" seems to be somebody who has a username and has logged in. But in my opinion, both of these sites are more useful if you're not a "user." So the use case where you're not a "user" is the optimal use case.


On the Reddit blog, discussing all the technical aspects of view counting, Chandra said the team's goal was to make it easy for people to understand how much activity their posts were driving, and to include more passive activity like viewing without commenting. But there's this obvious logical disconnect here, where Reddit excludes from this analysis any user who isn't logged in. You could even make the case that they'd be better served just pulling the info from Google Analytics, although that'd be naive.

First, given the scale involved, there's likely to be enough accuracy issues that a custom solution would be a good idea in either case. Second, Reddit's view-counting effort made no attempt to identify when two or more accounts belonged to the same human being, or when two or more human beings shared the same login. An off-the-shelf analytics solution could probably provide insight into that, but not definitive answers.

My favorite explanation for all this is that it's just a simple institutional blind spot: people who work at Reddit are probably so used to thinking that people who don't log in "don't count" that it seemed perfectly reasonable to literally not count them. The concept of "users" is such a useful social fiction that the company's employees probably just genuinely forgot it was a social fiction at all (or never realized it in the first place). However, if your goal is to provide view counting with accuracy, skimming over these questions makes your goal impossible to achieve.

Monday, January 16, 2017

JS Testing In Rails Apps: The Problem Space

I've got to do several things before my new book, Modern Front-End Development with Ruby on Rails and Puppies, is finished. It's currently only in version 0.2! One of the biggest things is to delve into JS testing in serious depth. The "with Puppies" part of my book's title doesn't add any extra challenges to that task, but the "with Ruby on Rails" part totally does.

The Rails culture has very high standards and expectations when it comes to the sophistication and specificity of its testing options. Say you've got a big Rails app which has presenters, decorators, and serializers. That's three different categories of view model objects — and standard methods of testing these objects exist both for RSpec and for classic TDD syntax (i.e., the assert style of Test::Unit and minitest). So you can go out and find, for example, specific, opinionated guidance on how to write tests for presenters using minitest. And I've obviously defined a 3x2 grid here, with 3 categories of view model object, and 2 categories of testing strategy. All six slots in the grid represent a strain of thinking within the Rails culture that lots of people are working on in detail. If you want to research any one of those six slots, there's a ton of prior art.

And that's just for view model objects. What about objects which move business logic out of the framework? Those can go in lib, or app/services, or app/interactors, or several other places. Want to test those quickly and well? There are projects which give you several different ways to do it. If you see open source development as a form of research, then you have this huge body of ongoing research. All these different strategies for separating business logic from the framework, and all the different ways of testing the objects which implement these different strategies — they all represent ongoing research projects into the best way to structure an application, and the best way to design an application, and/or secure that application, and/or prove its correctness (depending on how you see the purpose of testing in the first place, which itself is an area of ongoing "research," in this sense).

The common structure of Rails apps creates a shared vocabulary, not just for application logic, but for testing as well. You can have subtle, specific discussions about how to compartmentalize, organize, and structure responsibilities and processes across Rails apps, even when those apps do very different things.

Compare that to JavaScript. How many JavaScript applications share a common structure? Most don't.

The size of the Ruby community also helps here, in comparison to JavaScript. "The JavaScript community" basically means the same thing as "every programmer on the planet who ever works on or near the web." In fact, it's larger than that; if you want to script Adobe applications, for example, you use JavaScript. So for Ruby, you have a small community, where the overwhelming majority of programmers work within the same application structure, and where virtually everybody agrees that testing is important. For JavaScript, you have a group of people which is far too large to ever function as an actual community. Most applications have relatively idiosyncratic structures, and many of them change radically from month to month. What kind of consensus can emerge there?

The good news is that there are plenty of JS programmers who value testing, and plenty of JS test frameworks, to enable that. But the bad news is that many of these testing systems never get much further than unit testing. There's no Capybara of JavaScript, for example — not really — which is pretty crazy, because front-end coding is the type of work where you would expect to find a Capybara being developed.

Say you've got a Rails app with a React front-end. Maybe you're using Rails controllers for the regular web stuff and Grape for the API stuff that your React code consumes. So you can put your Grape specs in spec/requests and write simpler specs, and keep your controller specs in the more usual spec/controllers, and deal with the unfortunate downsides, i.e., the slowness, the intricate connection(s) to the framework, et cetera. But when you want to test your JS, you don't get these kinds of fine-grained distinctions for free. You can use moxios to mock your axios requests, but that's kind of as sophisticated as it gets. You have unit testing, and you have mocks, and there you go. It's like that scene in The Blues Brothers, when they ask "what kind of music do you usually have here?" and the bartender says, "we got both kinds of music, country and western!"

With JS, there are many ways to do mocks and stubs, and there are many ways to do unit testing, but there's nothing as purpose-specific as spec/requests vs spec/controllers. You're also flying blind somewhat when it comes to distinctions as fine and precise as when to use a presenter, when to use a decorator, and when to use a serializer (which is basically just a presenter for APIs).

One of the benefits of something like React is that it's an improvement just to get a sub-community (or subculture) of JS devs who all use roughly the same application structure, because that common vocabulary permits the subculture to develop more sophisticated and specific testing libraries. As far as that goes, Angular and Vue and other frameworks have a similar positive influence. However, this is especially a strength of React in my opinion, and in fact, I need to update my book to reflect that. For some reason, when people talk about React, they talk a lot about FRP and virtual DOMs, but when you get past the hand-waving, the actual day-to-day work of React is very object-oriented. There are a lot of tradeoffs to consider with OOP, but one great positive is that OOP systems present very testable surfaces. It's really easy to see where you start testing, when you're dealing with objects.

Elm has this "common application structure" advantage as well, but with Elm, you have types, and types relieve a lot of the pressure on tests. That's not to say that you don't need tests when you have types. But since the compiler is guaranteeing you certain behavior, you don't need tests to secure that behavior. People use tests to design systems, to secure systems (and prevent regressions), to document systems, and for a few other purposes. Elm's types make it easy to get most of your security cheaply. Elm also pushes you towards better designs in ways that are more subtle and which I couldn't perfectly articulate just yet.

However, in both these cases, this isn't a solution, but rather a reason to be optimistic that the cacophony which has prevented solutions from arising will soon diminish, at least somewhat.

I'll have more to say about this in the future; for now, this is just an overview of how the problem space for JS testing in Rails apps differs quite a bit from Ruby testing in Rails apps.

Monday, November 28, 2016

ERROR: Permission denied for relation

Stack Overflow will have you mess around with GRANT all day long.

But if you're seeing this error, you're probably doing dev on your laptop and you probably don't need to care any further than this:

ALTER USER myuser WITH SUPERUSER;

Enjoy.

Saturday, November 5, 2016

Rails Isn't A Full-Stack Framework Any More

Rails is a terrific framework. Its emphasis on programmer happiness and convention over configuration makes building apps easy and fun. But it has some areas of cognitive dissonance. For instance, Rails bills itself as a full-stack framework, and I think that just isn't true any more.

The Rails solution for the front end is jQuery, unobtrusive JS, and CoffeeScript. These are great technologies, but each and every one of them is showing their age.

jQuery's the most egregious example. JavaScript systematically adopts its most successful open source projects and turns them into language features. Because of this, a lot of jQuery's functionality is now provided by browsers, including the fundamental thing of querying the DOM and modifying pieces of it. For sophisticated, modern use cases, jQuery can give you slow performance, especially on mobile devices, and it carries significant risks of brittle, unmaintainable code.

Unobtrusive JS is the idea that your JavaScript should provide decoration, not functionality. It came to Rails in 2010, the same year jQuery did, and each of these things was great for 2010. Rich single-page apps had existed since Gmail debuted in 2004, but in 2004, you kind of had to be a Google to pull it off. Even in 2010, unobtrusive JS was a reasonable, pragmatic default.

Today, however, it's just one of many examples in the history of Rails and its many ways to avoid writing JavaScript.



CoffeeScript is still pretty cool in my opinion, but here's the downside with CoffeeScript. A few years ago, Jen Fong-Adwent created a cool JavaScript project called Meatspace. It's a text chat client which creates an animated GIF of your face, using your webcam, every time you say anything in the chat. It's kind of dead now, but when she created it, it was full every night, with tons of people having fun. So I went in there and I decided I should read the code, to figure out how it worked. And I had a much harder time of that than I wanted, because Meatspace used new features of JavaScript that I hadn't seen before. Despite years of experience, I felt totally out to sea.

And that was a few years ago. Since then, ES6 has made JavaScript into an entirely new (and better) language. So while I still really like CoffeeScript, I also consider it kind of a dangerous choice, where you might be sacrificing your skill level for the sake of a little comfort.

This is the motivation behind my new book. If you're a Rails developer, and you want to do modern front-end work, you know Rails just basically skips the whole question. Which front-end tech should you use? How should you use it? You might be used to Rails setting you up with really useful defaults, but that's not what it does when it comes to front-end development. So my book gives you the necessary context to make these kinds of decisions, and walks you through several alternatives for modern front-end development.

Rather than sell you on it, though, I'd prefer to just tell you what I heard from somebody who bought it. Andrew Stewart, a Rails developer from the UK, wrote the PeepCode videos on Vim back in the day — they're now on PluralSight — and he said I could quote this awesome email he sent me. So here it is:
Hey Giles,

I just finished your book (v0.2) and I thoroughly enjoyed it.

I run a little SAAS Rails app and I'm always working on features, simplifications, i18n, support, etc.  I rarely find or make the time to upgrade the underlying stack.  As a result it's way behind; the front end is asset pipeline circa Rails 3.2 with jQuery v1.11.0, Coffeescript, SASS, some CSS I haven't converted to SASS yet, and a large amount of crappy 2007-style JavaScript I haven't touched for years.

Your book is exactly what I need!

I like how it's full of stuff I can do immediately to modernise everything.  I now intend to replace the asset pipeline with webpack, drop jQuery, and rewrite the old JavaScript in ES6.  Eventually I'll replace the Coffeescript with ES6 too.  Having said that, I'm looking forward to your Elm chapter...  (The React and Om chapters helped me decide to steer clear of them for now.)

Just one suggestion for v0.3 - a table of contents would be nice.

Anyway, I can safely say this is the most helpful programming book I've bought for years.  Thank you!

Cheers,

Andy
There is a table of contents coming, by the way, and the Elm chapter's about half-written. I have the code but it's not in a repo you can see yet. Sorry -- I write the code for these books in separate repos first, to figure out what I'm doing, and then re-write them for the book repo. This way I can make sure my commits are structured in a way that is more logical and easier to follow. I want reading the git repo to be as clear for my readers as reading the book itself.

Also, the React chapter might convince you to give React a shot. It's about thirty pages, and the last ten pages are all about the tradeoffs you have to consider when it comes to giving React a thumbs up or a pass. Those tradeoffs are different for different projects.

Regardless, I was obviously thrilled to get Andy's email, and I hope you found my own email useful.

Click here to learn more about my book.

Or, to buy it directly:

Wednesday, October 12, 2016

Modern Front-End Development with Ruby on Rails and Puppies

Update: I'm taking this book off the market for the moment. I never finished the Elm chapter because of some health problems I encountered, and the guilt about that is quite frustrating.



If you've found it baffling, stressful, or confusing to get started with modern JavaScript development, I have an easy solution for you. I wrote a book which not only walks you through the process, but does so with an adorable, reassuring puppy on every page.

The first, beta edition of my new book is now available. It costs $41. Here are a few sample pages.





This book has a lot more color and design than the average tech book. I did a lot of production work for ad agencies and design shops before I became a developer, and I did a little design work, too. I'm not going to lie, I'm a little bit rusty, but I think tech books should be fun to look at, especially when they're about the front end. This also happened because I was inspired by Lea Verou's terrific book CSS Secrets.

For related reasons, the code in this book uses syntax highlighting. I think syntax highlighting is important in tech books. For a lot of programmers, it's very rare on a day-to-day basis to ever even see code which doesn't have syntax highlighting. So if you're used to seeing code with syntax highlighting, and then a book shows you the code without syntax highlighting, you're actually getting less information from the code than normal. Books on code should give you more context, not less. And, if you're a newbie, and you're buying my book, I want you to get a realistic experience of what being a programmer is like. I can understand why books printed on physical paper in black and white don't use syntax highlighting, because ink costs money, but if you're publishing a PDF — and I am — then I really think syntax highlighting ought to be a given.

The book also comes with two git repos, because the repos allow you to follow along with my code as you go through the book. If you've ever done this with another book and found out that you had to figure out what the author forgot to tell you in order to make their code work, guess what? Non-issue when the author gives you a git repo. If they forgot to mention something, you just run a git show or a git diff to get the exact changes.

Plus, a lot of code books will give you code you can download, but they just give you the finished product, or a bare-bones sandbox to play in. A code base isn't a finished product, it's a continuum over time, and with a git repo, it's a carefully indexed continuum over time. I think that's an important aspect of making code clear, so I first did all my code-related research in other repos, and then built these repos so that the repos would themselves be easy to read.

Also, to continue the theme that I think a tech book should make use of modern technology, the book has about 200 links, in its current state. An upcoming chapter adds 27 more, and future chapters will add more still. So, if at any point you want more detail, there are plenty of opportunities to dive deeper.

What I'm putting on sale today is v0.1, and I'm expecting to do a few updates before I call it 1.0. Despite that, this early-release version has a lot to it. There are the two repos I mentioned: a small repo to help you understand a new CSS standard called Flexbox, and the main example app for the book. The book covers the example app's step-by-step journey from a front-end based on jQuery and CoffeeScript to one built using React, ES6, and JSX. The book also features a puppy on every page.

The example app is a simple flash cards app for learning and studying written Japanese. These pages feature screenshots:



This app is simple enough that I can cover every change in detail, but complex enough that it can drive some investigation of different strategies for the front end. In some ways, it's like reading ToDoMVC implementations, except there's an explanation for every decision, and these decisions get compared to each other. I use a 12-point checklist to compare different front-end strategies. (I trim that checklist down for some chapters, however; for instance, the Webpack chapter is about infrastructure, so it skips some unrelated considerations.)

The existing chapters cover setting up this app as a vanilla Rails app with jQuery and CoffeeScript, translating it to ES5 — because jQuery's features are basically built into every browser at this point, and using the language instead of a library has much better performance characteristics — then translating it again to ES6 via Babel, adding CSS styles (including Flexbox), replacing the asset pipeline with Webpack, and rebuilding the app in React. There's also an experimental ES8 feature. Every step in the process is clearly explained, and there's a GitHub repo where you can file issues if you encounter errors, typos, or ambiguities.

Although I haven't set up a formal roadmap, I have a pretty strong idea what version 0.2 will look like. I've already got the next chapter written. In it, I translate the React app into an Om app, using ClojureScript. I've also translated that app again into an Elm app. I've got the code for that, and I'll be writing an Elm chapter around it soon. That's probably what you get in version 0.3.

(The Om/ClojureScript code is included in the repo, if you want to skim ahead, but I'm expecting to release version 0.2 pretty soon anyway.) (Update: The version 0.2 release just went out!)

To be clear, if you buy now, you get the new versions when it's updated, unless I ever release a 2.0 or higher version. Buying the 0.1 version means you get all the 0.x and 1.x versions free. You might get grandfathered in for a 2.0 version also, but you might not; I want to leave that open, because it's too far off for me to make any realistic plans around it.

Of course, if you're not satisfied for any reason, just let me know and I'll happily give you a full refund. You literally don't even have to give me a reason. I just want my customers to be glad they bought from me.

Friday, October 7, 2016

More About Ruby And Japanese

My "Ruby is 和" blog post is about 8,500 words long. One of the things I cut, to get it down to that compact size, was a section about similarities between Japanese and Ruby, as languages. I also cut it because I spotted a problem with the argument.

First, the part I cut:

One way to understand 和 is as a harmonious blend of disparate elements. This is an accurate description of the Japanese writing system. Written Japanese employs kanji (for example, 和), which are Chinese letters that carry the same meaning they originally held in classical Chinese when Japan adopted them, plus new meanings that Japan has added in the subsequent centuries. Written Japanese further contains our entire alphabet, which, as it was originally the Roman alphabet, is called romaji in Japan. Written Japanese also has two syllabaries, which are like alphabets except each letter represents a complete syllable. The syllabaries are called kana. While kanji and romaji are both character sets in use outside of Japan, neither of the kana syllabaries are used by any other language. However, even with the kana, there's a magpie element in effect: both syllabaries evolved from streamlined, abbreviated ways of drawing kanji.

Each of these four different character sets has different uses in written Japanese, and despite the enormous complexity, it all kind of balances out. Different character sets have different purposes. For instance, one of the syllabaries, the katakana, is primarily used for loanwords — like English, Japanese has a lot of loanwords — but it also functions as an equivalent to italics. Romaji, meanwhile, allow you to type Japanese characters using Western keyboards. Kanji have to be individually memorized, which is a lot of work for Japanese schoolchildren, but kanji have some advantages over written English, which may spell two different pronounciations the same way — e.g., "read" in the present tense vs. "read" in the past tense — or introduce subtle and totally arbitrary distinctions in spelling, like "write" vs. "right." This is also just something that kids have to memorize in school.

Now, for comparison, here's a Python fan on Reddit, complaining about Ruby:

I started working on ruby with a friend and was amazed by the multiplying way they have of making methods. For instance, ruby has for...in but it also has a .each. There are two different notations for ranges (inclusive and exclusive), and myriad unexpected methods for other things: unless (instead if not), upto (instead of the aforementioned range), etc.

It all seemed philosophically messy to me, like they just let whomever patch in whatever tool seemed most useful at the time, and did not imply the same rigid philosophical framework that the python community has adopted.

This could be a fan of English complaining about written Japanese, although English is perhaps a bad example, given that English has more corner cases than most languages. But it still has only one alphabet! And written Japanese definitely lacks unity by comparison.

I won't pick another example, as that could be a huge discussion. You get the idea. Ruby's cheerful willingness to accomodate multiple ways of doing the same thing has an obvious parallel in written Japanese. Fans of Sapir-Whorf will be thrilled to recognize this continuity, where a characteristic of the Japanese language reappears in a programming language created by a native Japanese speaker.

However, Matz himself has said that Ruby was not deliberately modelled on Japanese.

Japanese and Ruby? I try not to think too much about Japanese culture. The method chain looks like Japanese, but it’s just a coincident. Having said that, the support of M17N is heavily influenced by the use case of Japanese people. Otherwise, I wouldn’t spend too much time on such a hard problem.

This is from a tweet in Japanese. The translation comes from Makoto Inoue, a Japanese programmer based in London. He did a very interesting presentation about this, and wrote a blog post which summarizes it. He points out that Japanese sentence structure — subject first, verb last — works well with the Subject.verb syntax favored by object-oriented languages, and raises the same point I've made here about Ruby's versatility:

Doesn’t this “There are many ways to achieve one thing” concept [seem] familiar with Ruby’s philosophy?

Now for the problem with the argument, i.e., the second reason I didn't include this in my "Ruby is 和" post.

Here's a sentence in Japanese:

しつもんがあります。

It's pronounced "shitsumon ga arimasu." You could translate it as "I have a question," and that's what it usually means in my extremely limited experience. I personally say this in emails to my Japanese teacher all the time. But that's not a literal translation.

This sentence has only three words. しつもん ("shitsumon") means a question, or some number of questions, since, like Cantonese, Japanese does not differentiate between the singular or the plural. が ("ga") is a modifying particle like the modifying particles in Attic Greek. It basically means "the word I just said is the subject of this sentence." Since it comes after しつもん, it means the sentence is about a question or some number of questions. The verb, あります ("arimasu"), literally means "exists," or "will exist." Japanese does not differentiate between the present and the future, at least not in the way that English does.
If the languages I'm using for comparison seem random, that's because they are. I'm not a linguist, I've just picked up a bunch of random knowledge here and there.

So the literal translation for しつもんがあります would be "a question, or some number of questions, exists, or will exist." It's up to the reader or listener to understand that, in context, this means roughly the same thing as "I have a question."

Because of all this ambiguity, idiomatic Japanese relies heavily on inference and implication. And this is the problem with the argument that Ruby mirrors Japanese in any meaningful way, in my opinion. Makoto Inoue has an interesting argument which relates this aspect of Japanese to Ruby's functional characteristics. But my concern is that you could imagine a possible programming language which emulated this aspect of Japanese, and Ruby differs from that imaginary language.

For example:

@user = User.find
@user.register!


Here, we have a bit of Ruby which finds a user and has that user register for something. We have to say @user twice. If Ruby were more like Japanese, it might implicitly capture the return value of each expression, and apply the next line to that return value — or resolve scope in the next line while favoring the return value — so that you would never have to say @user explicitly at all.

For example:

User.find
register!


To my knowledge, no programming language does this. You can do stuff like that with method chaining:

User.find.register!

And there was a with statement in Pascal and early versions of JavaScript that allowed something kind of remotely similar, but more explicit:

with(foo = 5) { console.log(foo); }

But it's not the same. I don't expect any programming language to ever really copy this aspect of Japanese, for the same reason that Google Translate basically sucks at Japanese, and I kind of expect that it always will: Japanese relies on context, i.e., information from outside the sentence, and writing code which can infer things from context, the way humans can, is not an easy thing to do. It's probably impossible to develop a programming language which properly emulates this aspect of Japanese without solving very hard problems in artificial intelligence and/or machine learning.

Update: I got a lot of responses to this about possible hacks to implement this, equivalents to with in other languages, and similar stuff. I plan to update with a new blog post semi-soonish but it's going to be after a slight delay, because some of the responses involve languages I'm not at all familiar with, so I want to investigate a little before I post the update.

Thursday, October 6, 2016

This Infographic Explains Why JS Dev Seems So Complicated

There's a web site called Hacker Noon which seems to specialize in complaining about JavaScript. One Hacker Noon piece resonated with a lot of people recently. It's all about how huge and overcomplicated the JS ecosystem is, and how hard it is to just sit down and get stuff done.

First of all, if what you want is a beautiful, omakase system for building modern front-end applications, just learn Elm. It's omakase as fuck. It's lovely to work with. And it's the type of project where you can do everything in one language, without ever needing to deal with other stuff.

But there's another option, too: just take a moment to understand why the JavaScript ecosystem is complicated.

It's not just because JavaScript is used by everybody who does anything on the web. It's not just because code on demand becomes a more powerful strategy each day, as the computers which run web browsers become smaller and more powerful.

It's also because JavaScript employs one of the oldest strategies of the Web: paving the cowpaths. Whenever people are already doing something, and it's working well, JavaScript seeks to lift up their practices into the language itself, rather than dictating something new.

Consequently, modern JavaScript is full of things which it got from open source projects.


Puppy picture from Daniel Stockman on Flickr.

bind was pioneered by Prototype, and showed up in Underscore and jQuery (as proxy) before landing in ES5. The Array methods each, map, and filter have a very similar backstory. CoffeeScript and Node are major contributors to ES6. When Angular and Ember first blew up, Object.observe briefly became a thing. People thought it would be a big deal, but this turned out to be premature paving of an unused cowpath, and Object.observe was deprecated, because people didn't use it. This is the output of a process where the people who shape JavaScript look at how open source projects use JavaScript, and the ways in which they seek to fix JavaScript, and use that as guidance to inform decisions about what JavaScript should be.

Modern front-end development is a lot of fun. In the 1990s and the 2000s, it was a nightmare. It was horrible. And paving the cowpaths is one of the reasons it got better. Because in the 1990s and 2000s, JavaScript implementers tried to just make up features and tell people what they wanted. It didn't work.

The chaos and churn of the JavaScript landscape is how we got a better JavaScript. It would never be practical to get such a big user base to agree on a hypothetical feature set. There's just too many people. It would be beyond impractical to expect any giganto-committee to be able to foresee the needs of such a colossal group. So JavaScript is a place where lots of projects get invented, and the language learns from its users.

That's fucking great. A huge landscape full of competing projects means that JavaScript will keep getting better.

If you'll forgive a little blatant self-promotion, this infographic is from my upcoming book, Modern Front-End Development with Ruby on Rails and Puppies. In this book, I build a simple UI in vanilla Rails, using CoffeeScript and jQuery. Then I throw out jQuery and turn the front-end code into ES5, because — as you can tell from the infographic — pretty much everything that made jQuery worthwhile has been integrated into JavaScript itself now. Anyway, then I turn it into ES6. Then I run it through Webpack and integrate Webpack with Rails. I implement the UI again in React with JSX, and then again with ClojureScript and Om. (I've also built it yet again in Elm, but I haven't written that chapter yet.) I even show how to pull in an experimental feature from ES8.

And yes, there's puppies. There's a puppy on every page. So if all this unfamiliar JavaScript scares you, all you have to do is look at the puppies and you'll feel better.

It's a very hand-hold-y book. It makes it easy for you to dive into all the complexity of modern front-end development. So there's no excuse for complaining! But the reason all this works is because this book teaches you things. In order to do front-end development, you have to learn stuff. There's no way around that. You can't expect one of the most lucrative fields on the planet to be a field which does not require you to obtain new information. That's just ridiculous.


Update: Version 0.1 0.2 of the book is now live! Also, when I made this infographic, I left out the most obvious and well-known example of JS adopting user ideas, namely, JSON. My bad!