TrickAJournalist.com  

Nathan Kontny, CTO at Highrise, writing at Medium:

So I made Trick A Journalist as satire on how bad marketing has gotten. But I also made it for a much more important reason.

It’s a Bad Marketing Honeypot. The people signing up for this, and unfortunately there’s quite a few, are banned from using Highrise.

In Shoe Dog nomenclature, I imagine that Phil Knight’s dad would call building TrickAJournalist.com “jackassing around” on the web, but still, this is awesome.

Calculate Your Average Interval Pace and Total Interval Distance for a Strava Run

Lately I’ve been implementing Jack Daniels’ Running Formula step-count interval workout. The way it works is this: you run at interval pace for 20 steps, then you jog for 20 steps. Then you run at interval pace 40 steps, then you jog 40 steps. You keep doing this until you do 200 steps of each pace, then you run another 200 of each, and wind your way back down: 180 interval, 180 jog, 160 interval, 160 jog, so on and so forth until you arrive once again at 20 of each.1 This run comes out to be between 3 and 4 miles in total distance and about 2 miles of it is at interval pace. If you’re running 20-30 miles per week, this is a good amount of interval running for that week.2

Once your activity is uploaded to Strava, you’ll see a zipper pattern of a fast lap, a slow lap, a fast lap, a slow lap. Lurking amongst this data are two things that Strava doesn’t reveal out of the box: the total distance of your interval-pace laps, and this total distance’s average pace.3 Everything you need to compute these two data points exists; you just need a way to harvest it. This is where Strava’s API comes in.

First you’ll need an access token. To do this, create a Strava app4 and then head to this URL:

https://www.strava.com/oauth/authorize?client_id=[clientID]&response_type=code&redirect_uri=http://localhost&scope=view_private

Change out the [clientID] with your app’s client ID.

Once you’ve authorized your own app, you’ll get redirected to localhost, which unless you have a local server running will result in a “This site can’t be reached” Chrome page.5 That’s ok though, because your payload is the code parameter in the URL. Grab that and do a POST request to https://www.strava.com/oauth/token with these params:

  • client_id
  • client_secret

I like to handle POST requests like these using the Advanced REST client. If you’re using that for this, you’ll want to select multipart/form-data as your body content type in order to get this to work.

This POST will return a payload with your athlete information, but the piece you’re after is the access_token. Store this somewhere safe. You worked hard for it, it won’t expire, and you’ll reuse it later.

Now, get the ID of the activity you’re interested in. You’ll find the ID in the URL of the activity. E.g. https://www.strava.com/activities/1428717700 has an ID of 1428717700. Now go here to get the payload of your activity:6

https://www.strava.com/api/v3/activities/[activityID]?access_token=[yourAccessToken]

Copy all the JSON from the response of this request, pop open your Chrome console, and write this:

const activity = [paste from clipboard]

Then run this in the console:

const totals = { distance: 0, seconds: 0 };
activity.laps.forEach(lap => {
  if (lap.pace_zone === 6) {
    totals.distance += lap.distance;
    totals.seconds += lap.elapsed_time;
  }
});

totals.distance =  totals.distance * 0.000621371;

console.log(totals);

You now have, logged at the bottom of the console, the total number of miles and seconds of your interval pace. Head over to pace.martynchamberlin.com (or similar — there are a number of online calculators that achieve what that one does, so use your favorite) and plug in these numbers, and you’ll get your output. This is the process by which I can know that my run today contained a total of 2.15 miles at a 5:33/mi pace, even though the overall activity was 3.45 miles at a 7:46/mi pace.

Groovy, right?7


  1. I don’t keep track of my footfalls in my head, although you could do that if you had to. Instead, I manually lap each set of steps using my Garmin vívoactive 3, which conveniently lets you see your number of steps per lap and lets you manually create new laps. As an aside, it’s exactly this sort of functionality that Garmin offers and that Apple Watch doesn’t that explains why serious athletes still prefer Garmin. ↩︎
  2. Jack Daniels recommends that your weekly amount of interval distance be the lesser of 10K or 8% of your weekly mileage. This is right in that sweet spot. ↩︎
  3. These two data points are immensely useful, because they let you know how you’re performing compared to previous workouts. Your total distance and total average pace aren’t as helpful for this sort of workout because those are influenced heavily by how quickly or slowly you’re jogging in between interval laps. The question we’re trying to answer is this: how much quality interval time did we get? How fast were the intervals and how much distance did they cover? In my mind, the answers to those questions are some of the most valuable things we can know when analyzing a completed interval workout. ↩︎
  4. This app is for your eyes only, so name it whatever you want, and upload a picture of your dog as the app’s icon. As an aside, it’s bizarre to me that an icon is required when creating a Strava app. Why? ↩︎
  5. I assume you’re using Chrome for all this. 😛 ↩︎
  6. Strava access tokens are per-athlete which means you’ll only be able to do this on your own activities. ↩︎
  7. If you’re thinking, “This is quite a hassle and this entire process should be automated in software,” you’re on the right track. I eventually want to build this out similarly to how I built out distance.martynchamberlin.com, but it all takes time, and right now I’ve got too many other irons in the fire. So for now, computing this number takes some elbow grease. Our only consolation is that the coaches and runners who lived pre-Strava and pre-Garmin must’ve done an awful lot of number crunching by hand on yellow notepads. I don’t envy those days. ↩︎

The Stack Overflow Question That Led to Ross Ulbricht’s Arrest  

Moments after posting this question, Ross Ulbricht changed his email address on Stack Overflow from one in which his name was associated to the fictitious “[email protected]” Stack Overflow keeps track of all previous email addresses used, and when an IRS agent approached Stack Overflow with a subpoena, the company provided the original email address, thereby revealing the identity of the user.

Ross Ulbricht is in jail for life for masterminding the Silk Road website. This Stack Overflow post was a critical clue.1


  1. I highly recommend reading American Kingpin for the full story. ↩︎

Michael Lopp’s iPhone Home Screen  

Michael:

Strava. Because smaller more connected [villages] are bringing us a healthier internet. I have a lot to say about Strava in a future article. I pay a subscription fee for Strava.

It warms my heart that the Vice President of engineering at Slack has Strava on his home screen.

Five Minutes and Fifteen Seconds

Yesterday I wrote a somewhat cryptic comment on a Strava activity headlined 40.87 miles ahead of pace, as of this millisecond:

If you want a fun math problem, you can find out when I changed the title of this post, to an accuracy range of 5 minutes and 15 seconds. The only data points you need to derive this number are (1) my precise distance up to this point (2) my yearly goal. The latter is publicly available on my profile, but I suppose to get the former you’d have to hack my Strava account, since OAuth tokens are per-athlete. So never mind. 🙃

What in the world am I talking about? Well, I have a one thousand mile running goal this year. When we do the math in a 365-day year, that comes out to about 2.73973 miles that we must average every day.

1000 / 365 = 2.7397260274

In my headline, I gave away the fact that I was 40.87 miles ahead of pace at the time that I modified the headline. That’s rounded to the hundredth place. How many times per day would this number change? We can easily find out. We need to run 2.73973 miles per day, and since we’re keeping track of this in hundredths, we multiply that by 100:

2.7397260274 * 100 = 273.9726

This resulting 273.9726 is how many times per day that 40.87 number will regress by a hundredth of a mile. To answer how many times per day this would change in seconds, we find out how many seconds are in a day:

60 * 60 * 24 = 86400

And then we divide that by the number of times our pace will regress:

86400 / 273.9726 = 315.3600

In other words, that number will regress every 315.36 seconds, or every 5 minutes and fifteen seconds. This is why I said in the Strava activity that we could get within “an accuracy range of 5 minutes and 15 seconds.”

With that explanation in the backdrop, we can get to the fun math problem of which I spoke. We need my precise distance year-to-date in order to be able to solve that problem, and I have that precise distance. It’s 262824.7 meters. Let’s figure out how many miles that is:

262824.7 * 0.000621371 = 163.3116466637

Next we need to find out what my distance for the year up to this point should be in order for me to be on pace. To do this, we take 163 miles and subtract from it the 40 miles:

163.3116466637 - 40.87 = 122.44

Now all we have to do is find out how many 315.3600-second intervals occur from January 1 to the time that we’d need to have run 122.44 miles, get the total number of seconds that occurred in those intervals, and we’ll have our answer.

First, we need to establish the pattern. For the first (315.3600 / 2) seconds of the year, we need to have run .004978437341451041 miles. Since we’re rounding to the hundredths, that comes out to be zero miles. For the 315.3600 seconds following, we need to have run .01 miles. For the next 315.3600 seconds, we need to have run .02 miles.

Here’s some JavaScript to demonstrate. First some core functions, which are the backbone of my distance web app:

const amountOfYearExpired = (time = new Date().getTime()) => {
  const startOfYear = new Date(`Jan 1, ${new Date(time).getFullYear()}`).getTime();
  const startOfNextYear = new Date(`Jan 1, ${new Date(time).getFullYear() + 1}`).getTime();
  const percentagePassed = (time - startOfYear) / (startOfNextYear - startOfYear);
  return percentagePassed;
}

const metersToMiles = (meters) => {
  return (meters * 0.000621371);
};

paceDelta = (currentDistance, goal, timestamp = new Date().getTime()) => {
  if (!goal) {
    return 0;
  }
  const percentagePassed = amountOfYearExpired(timestamp);
  const currentTarget = goal * percentagePassed;
  // if this number is negative then we're behind pace
  const output = metersToMiles(currentDistance) - currentTarget;
  return output;
};

Next we use them like so to prove the established pattern above.

// Subtract 1 to get the value at the very last millisecond before
// it switches to the second half of the first interval. Multiply
// by 1000 to get the value in milliseconds.
const firstHalfOfFirstInterval = (315.3600 / 2) * 1000 - 1;
const date = new Date(new Date('January 1, 2018').getTime() + firstHalfOfFirstInterval);
const delta = Math.abs(paceDelta(0, 1000, date));

The above delta variable has a value of 0.004999968290208016. Rounded to hundredths, that’s 0. If we don’t subtract 1 from firstHalfOfFirstInterval, we get exactly .005. Rounded to hundredths, that’s .01. It stays at .01 for the next 315.3600 seconds:

Math.abs(paceDelta(0, 1000, new Date(new Date('January 1, 2018').getTime() + ((315.3600 / 2) * 1000 - 1) + 315.3600 * 1000)))
// outputs 0.014999968290208016

And then once we re-supply that one final millisecond, we arrive at .02 when rounding to the hundredths:

Math.abs(paceDelta(0, 1000, new Date(new Date('January 1, 2018').getTime() + ((315.3600 / 2) * 1000) + 315.3600 * 1000)))
// outputs 0.015000000000000001

With this established pattern, all we have to do is multiply 12,243 (122.44 miles times 100, since our interval duration is per one hundredth of a mile increments, and then subtract 1, since the full 12,244 will round up and yield our upper limit) by our interval duration, and then add a half an interval to that (because of the aforementioned rounding pattern), and we’ll have the start time of our range.

12,243.5 * 315.3600 = 3,861,110.16

To get the end time of our range, we add an interval of 315.3600 from the previous formula:

12,244.5 * 315.3600 = 3,861,425.52

Let’s multiply those by 1000 to change them to milliseconds, and make dates out of them. Notice we subtract 1 millisecond from the finish since otherwise it’s technically in the next range:

const jan1InUnix = new Date('January 1, 2018').getTime();
// Wed Feb 14 2018 16:31:50 GMT-0600 (CST)
const start = new Date(jan1InUnix + 3861110160);
// Wed Feb 14 2018 16:37:05 GMT-0600 (CST)
const finish = new Date(jan1InUnix + 3861425519);

We can check these numbers to make sure they’re in the right range and representative of that range’s extreme lower and upper limits, which indeed they are:

// outputs 122.435 which rounds to 122.44, the lower limit
Math.abs(paceDelta(0, 1000, jan1InUnix + 3861110160));
// outputs 122.4449999682902 which also rounds to 122.44, the upper limit
Math.abs(paceDelta(0, 1000, jan1InUnix + 3861425519));

When we look at the activity, the start time was around 3:25 PM CST with a moving time of 53:27 minutes. That puts the finish time in the 4:18 PM CST range. We can know with confidence that somewhere between 4:31:50 PM CST and 4:37:05 PM CST, about 14 to 19 minutes after I completed the run, I modified the headline. That’s an accuracy range of five minutes and fifteen seconds.

How “Complex” and “Confusing” Is the Modern Web Really?  

Frank Chimero:

That breaks my heart, because so much of my start on the web came from being able to see and easily make sense of any site I’d visit. I had view source, but each year that goes by, it becomes less and less helpful as a way to investigate other people’s work. Markup balloons in size and becomes illegible because computers are generating it without an eye for context. Styles become overly verbose and redundant to the point of confusion. Functionality gets obfuscated behind compressed Javascript.

I want to make a few points about this piece overall.

  1. First, HTML tables and spacer gifs are not simpler than Flexbox and CSS Grid. More importantly, tables are not mobile friendly. They should never ever be used in modern web development.
  2. If someone’s building with “overly verbose” stylesheets that override each other as they cascade, they’re doing it wrong. If it’s difficult to understand what’s going on in a DOM because there are too many nested DOM nodes, they’re doing it wrong. If you want an example of a modern web app that avoids these pitfalls, look no further than my distance tracking web app for athletes.
  3. This complaint that, “Functionality gets obfuscated behind compressed Javascript” is a real kicker. In a 2002 web era, what would be different here? Is Frank wishing that the JavaScript simply didn’t exist, and by extension, the functionality? Or is he wishing that it existed on the backend, where you couldn’t view it whatsoever? Or is he wishing that it remained as JavaScript, albeit not obfuscated (thereby murdering load performance)? If the litmus test for whether an app is great or not is by how easy it is to decipher the source code, then all iOS apps are by extension the devil incarnate.
  4. Just because somebody publishes a 90-page ebook doesn’t mean that font faces are as complicated as all that. It just means that they’re trying to sell an $8 ebook and realize it’d be a harder sell if it were only 15 pages. Granted, anything to do with web technology can get complex if you choose for it to. If you’re working for Facebook, maybe you need a 90-page ebook to decide exactly how you want to serve up your fonts. But for the little web design projects that it sounds like Frank is doing, he doesn’t need it.
  5. A web page in 2018 can be as simple as it was in the early 2000s if you choose for it to be. The only thing that’s changed is that in the intervening years we’ve built tools that let you make things more complex if you need for them to be. The early 2000s quite frankly didn’t have the sophisticated web apps that we have today, and arguably they could not because the tools did not exist. It does not take a mandatorily greater amount of work to achieve the same things on the web today than it did 15 years ago. Rather, there is a greater depth of complexity awaiting you if you need it. In other words, we didn’t go from A to B. We went from A to A and optionally B if you need it. That’s progress, not regress. Frank writes of his past days back when the web was ostensibly great, “Perhaps I was fascinated by the potential of bashing together something in my room, hitting a button, then having it be ‘out there.‘” I still do that all the time, in 2018, and it’s still great. Again.

(Via Nick Heer, who is still struggling to remember the syntax of Flexbox, which tells me he’s not writing much Flexbox.)

Track Your Yearly Running Goal With This Simple One-Screen Calculator  

In an effort to cut needless fat out of my software budget, I’m letting my Strava Premium expire this spring. $60 a year for Strava Premium doesn’t sound so bad; $600 over the next decade sounds like a lot.1 Moreover, Garmin Connect shows 100% of the in-depth data that Strava Premium does, and Garmin Connect is free.2 The only thing I knew I’d really miss about Strava Premium is the ability to track how far I’m ahead or behind pace in my yearly goal of running 1,000 miles. So this morning I threw together this mobile-friendly HTML page that computes this for you. It’s localStorage cached, and therefore persistent yet anonymous. I’m 124 miles into my yearly goal, which puts me 26.54 miles ahead of pace as of this sentence.3

Usually the subscribers to a service like Strava Premium do it because they love the service and want to support it. What I’ve learned is that those people will always be around, and that there’s no shame in the other 97% of us using the software for free.

I love Strava greatly; I love reducing rows on my credit card statements even more. 💸

Update: The HTML page is now here. I’m now frying bigger fish at the previous URL. More on that later. Maybe.


  1. And with inflation and whatnot, who thinks Strava Premium or any other premium service for that matter will not be higher in ten years than it is today? ↩︎
  2. You have to own a Garmin device to use Garmin Connect, so it’s free in the same sense that Apple Messages is free. ↩︎
  3. I think Strava recalculates your ahead-or-behind amount every 24 hours or when you upload a new activity, whichever comes sooner. My “app” computes it based on the exact timestamp of page load, accurate to the millisecond. A 1,000-miles-per-year goal means you need to average roughly 2.7 miles every day. If your calculator refreshes its output every 24 hours, when does that refresh occur? At midnight? If so, what timezone? Regardless of when it is, your ahead-or-behind amount stays constant all day long and then jumps backwards 2.7 miles all at once every 24 hours. Nobody wants that. That number should be completely smooth in its regression, and lurch forward when you complete a new run. ↩︎

Let’s Bury the Hustle  

This is one of my all-time favorite pieces by DHH. It’s brutally savage and rings true.1 His 5-step process is an essential guide for how to nurture professional creativity.


  1. My only complaint about DHH’s writing style is his disrespectful and borderline obnoxious crassness. Using four-letter words to get a point across is a lazy copout to serious prose, and it achieves no service to the reader. ↩︎

Fewer Podcasts, More Audio Books

Listening to the same podcast feeds to glean new information is like squeezing the same grapefruits over and over again. Unless they’re usually high quality, well-researched shows, once you’ve heard a half-dozen episodes of a podcast, you’ve heard most of what their hosts have to say. After that, they’re just re-voicing their opinions, offering variations on well-worn themes.1 You’ll continue to get a drip here and a drop there, but what’s the point?

Stop listening to the same people say the same things, and renew your mind with fresh books.2


  1. Podcasts are the Hipsterville version of radio talk shows. They’re more sophisticated but they contain the same inescapable problem of repeating themselves over and over and over and… ↩︎
  2. The best place to do that is Audible. Contrary to misconception, Audible can be a pay-per-month service, but it isn’t a typical one like Zwift or Netflix in which you’re exchanging dollars for zero value during a month that you don’t use the service. Rather, if you don’t use Audible for a given month, your credits that you’ve accrued will rollover to the next month. Moreover, you’re not renting audiobooks from Audible; you’re buying them. You keep them for life; you have perpetual access to them. In short, the value that you get for $14.99 per month is equivalent to adding new books to your bookshelf on a monthly basis, except you’re adding them in an accessible form that guarantees you’ll actually get good out of them. That’s more than I can say for the scores of books, for which I paid good money, that are sitting on my shelves in various stages of neglect. ↩︎

Why We Forget the Books We Read  

Julie Beck, writing for The Atlantic:1

The lesson from his binge-watching study is that if you want to remember the things you watch and read, space them out. I used to get irritated in school when an English-class syllabus would have us read only three chapters a week, but there was a good reason for that. Memories get reinforced the more you recall them, Horvath says. If you read a book all in one stretch—on an airplane, say—you’re just holding the story in your working memory that whole time. “You’re never actually reaccessing it,” he says.

If you really want to recall a book, read it over an extended period of time. A few pages per day is better than fifty pages per weekend. Counterintuitively, the longer it takes you to read a book, the better retention you’ll have of it.

(Via Bob Ryskamp.)


  1. The URL of this Atlantic piece is delightful. ↩︎

How to Change the Default Background Color of a Stickies Note on macOS  

The intuitive way would be for Stickies to have a Preferences window where you specify your defaults. Stickies prides itself on being a nimble app however, so it doesn’t have a Preferences window. Instead, you select a sticky that you’ve customized to your heart’s content, go to Window, and select “Use as Default.”

I’ve been using a Mac for more than a decade and I never knew this until today. I’m delighted to have finally changed my default Stickies background from yellow to blue.

Persistent Local Overrides Delayed Until Chrome 65  

From Kayce Basques’ release notes for Chrome 64:1

Whoops! We originally scheduled this feature to launch in Chrome 64, but pulled it close to the deadline in order to smooth out some rough edges.

The ability for local overrides to persist between pages loads is going to be nothing short of amazing, especially for projects that have Hot Module Reloading. It is often the case that I will locally override the CSS for a page, get it looking exactly like I want it, then head over to my editor to make the changes for real. I’ll make the first change and then without thinking save the file. HMR internally refreshes the page, and I lose my other changes. I then have to continue making the rest of the changes in the editor from memory. Persistent local overrides solves that problem.


  1. There’s something the Chrome team doesn’t mention in its Chrome 64 update that’s worth mentioning: the San Francisco font looks different, in a good way. It’s now much closer to how the font appears in Safari. If you prefer doing your web reading in Safari because of its superior typography, that reason is going away. ↩︎

Why Disney Owns Transwaybuslines.com  

There’s a scene in Pixar’s Inside Out where Riley is determined to leave her parents and return to Minnesota. She gets out her laptop, goes to the web address for the fictitious company Transway Bus Lines, and books a ticket. The URL of the old-Safari-esque browser on the Chromebook-esque laptop is this:

http://www.transwaybuslines.com/pg3/index/0124984328#8848392924

It’s a lousy, and thereby realistic, URL. It lacks SSL and everything past the TLD contains unhelpful information. I was curious to see if this URL actually worked or not, so I went to transwaybuslines.com. The page doesn’t have any DNS records that it can resolve to, but a WHOIS lookup shows that Disney, the distributor for the movie, purchased the domain in 2014, one year before the film’s release.1

By owning this domain, Pixar and Disney ensured that they were in full control of the user experience of this fictitious brand. Very few people are going to pause the movie and capture this address bar — the laptop screen appears for a fleeting second — but the companies wanted all the bases covered.

This kind of attention to detail is so great.


  1. It’ll be interesting to see if the company renews this domain in 2019 when its 5-year purchase expires. ↩︎

What Browsers Do With the Extra Pixel When Centering Items Within a Container  

Have you ever wondered what happens with a container with a width of 10 pixels and a div inside of it that has a width of 3 pixels and a margin of 0 auto? It sounds like a contrived example, but these sorts of dilemmas are common in a world of mobile-fluid flexbox layouts. This morning I got down to business and figured out what happens with “extra” pixels. The tl;dr is this: in a horziontal situation, the left side of the aligned item gets the extra pixel. In a vertical situation, the top side gets the extra pixel. This feels consistent with CSS’s preference for top-left in things like border-radius.

As I mention in the gist, this discussion is irrelavent on retina screens; since a CSS 1px equals two actual pixels on a retina screen, a retina screen can render any centered layout in perfect symmetry.

How the Top Rated London Restaurant on TripAdvisor Was Fabricated  

Eli Rosenberg, writing at the Washington Post:

It was a unique restaurant in London and certainly the hardest to get into. And it beat out thousands of upscale restaurants in the city to earn the top ranking on the popular review site TripAdvisor for a time, drawing a flood of interest.

There was just one small problem: It didn’t exist.

This entire piece is fascinating and I recommend reading it in its entirety.

To put this story into a broader context though, I’ll tell a story. I’m listening to an audio recording of Shoe Dog whilst running and my mind’s been blown by how easy it was to fabricate businesses and locations in the 1960s. Oregonian Phil Knight, who would later become the founder of Nike, flew to Japan in his mid twenties and told shoe company Onitsuka Tiger that he wanted to be a distributor of its Tiger shoe in the Pacific Northwest. When asked what his company name was, he replied, “Blue Ribbon.” Blue Ribbon was a nonexistent entity that Phil made up on the spot. This was pre-internet; the world was a big place, and there wasn’t a way for Onitsuka to verify whether such a legal entity existed or not. Onitsuka agreed to sell Phil’s postulated company a thousand Tiger shoes at wholesale, whilst Phil flew back to Oregon and scrambled to create the company Blue Ribbon. Later, when Onitsuka was concerned that Blue Ribbon wasn’t a big enough U.S. distributor compared to Blue Ribbon’s competitors, Phil countered this by saying that Blue Ribbon was represented on both coasts, which wasn’t true. Skeptical, Onitsuka said it would ship Phil’s newest shoe order to its east coast address, to which Phil replied that he would wire the exact address shortly. He promptly had one of his employees go and create a Blue Ribbon store in Boston, then he wired Onitsuka the address.

In the internet era, Phil Knight’s fabrication would be harder to pull off; but Oobah Butler’s fabrication was only possible because of the internet.

You can’t trust everything you encounter on the internet, but that law applies just as much offline.

How Facebook Kills Personal Development  

DHH, writing at Signal v. Noise:

What allowed me to change and prosper was the freedom to grow apart and lose touch with people. It’s hard to change yourself if you’re stuck in the same social orbit. There’s a gravitational force that pulls you into repeating the same circular pattern over and over again. Breaking out of that takes tremendous force.

Whilst was reading this, something struck me. If you view Facebook’s primary problem as one of fake news and insular group think, then you’ll be in favor of people having as many kinds of friends as possible, retaining every connection they meet in real life. You’ll view this statement as a good thing:1

Knowing that everything you share will be seen by all these people from your past quietly. moderates what you actually share.

To DHH, this kind of moderation is a bad thing. It stifles growth.

This dilemma of how many connections to retain on Facebook is simple: don’t use Facebook.


  1. There’s a lot of typos in this piece. DHH’s a busy man. ↩︎

Burger King Explains Net Neutrality  

ISPs deliberately slowing down lanes of traffic might occur in a future of no government regulation. But saying that this sort of thing used to go on and that we’re returning to this because of the repeal of so-called net neutrality is blatantly misleading. Everyone in that video is getting furious about a hypothetical that has never occurred. If you’re the kind of person who thinks the government should put laws in place to protect hypothetical scenarios that are unlikely to occur based on historic data, you’ll be for net neutrality. Otherwise you won’t be.

Update: what would Burger King have to change about their ad in order to make it an historically accurate analogy to ISP favoritism? They’d have to make it so that all the customers get their burgers in the normal timeframe, except for a few people who get their burgers faster than usual. Think of it as the dozen passengers who have priority boarding and who fly first class on an airplane. They’re special, everyone knows it, and everyone’s cool with it.1 Being in favor of net neutrality is roughly equivalent to being against priority boarding on an airplane.


  1. Well, almost everyone. I’m sure you could find some stage 4 liberals who pontificate the “inequality” of riding first class and how world poverty could be ended once and for all if they simply took the extra cost and gave it to those in greatest need, but you get my drift. ↩︎

You Needn’t Learn English to Learn to Code  

Nick Heer:

It’s not enough to know what words to put where; good programmers understand the specific use of these words, and that requires an understanding of the grammatical syntax of English.

It’s laughable to think that you’d have to have a deep understanding of English to know how to program. There are millions of software developers who have limited English skills. You don’t have to be a grammar whiz to understand what if, when, case, while, and let mean. You only have to understand what they do in the context of software. I’ve never heard a developer who was a non-native English speaker complain about this, and I’ve worked with and corresponded with a lot of them. If you’re incapable of learning the meaning of 10 or so English words, you’re not cut out to be a software developer.

Moreover, getting a language to support an indeterminate number of keywords in the name of i18n would be a nightmare to maintain. Microsoft Office tried this for a while by shipping with a partially translated VBA. It was a disaster. It’s never going to happen for Swift.

Stack Overflow Analyzes Remote Work from Its 2017 Developer Survey Results  

Julia Silge:

There is a big difference in the overall experience levels of remote and non-remote developers. In most countries, developers who work remotely have more years of professional coding experience than those who work in their companies’ offices. This is a large effect, a difference of 5 years of median experience in the United States and Canada.

The data crunching that Stack Overflow is doing with its survey results is hugely insightful.

The Twelve Ways to Sneeze

There are three tenses in English that denote time: past, present, and future. There are two tenses in English that denote aspect: perfect and progressive. The aspect tenses can be combined with the time tenses. For example, a past tense can be perfect, or progressive, or both. This gives us a total of twelve different ways to sneeze in first person:

  1. Past: I sneezed.
  2. Past perfect: I had sneezed.
  3. Past progressive: I was sneezing.
  4. Past perfect progressive: I had been sneezing.
  5. Present: I sneeze.
  6. Present perfect: I have sneezed.
  7. Present progressive: I am sneezing.
  8. Present perfect progressive: I have been sneezing.
  9. Future: I will sneeze.
  10. Future perfect: I will have sneezed.
  11. Future progressive: I will be sneezing.
  12. Future perfect progressive: I will have been sneezing.

Not all languages have all these tenses, and likewise, English lacks some tenses. One example of the latter is the imperfect tense, utilized by Latin, French, and Greek. In the case of missing tenses, most languages have close equivalents, but it’s never a perfect match. Your sneeze isn’t quite the same as a Frenchman’s.

The Hypocrisy of Blaming the Rich for the World’s Poverty  

Here we have a millionaire, John, linking in approval of an article that blames billionaires for their greed; who in turn, if they had opportunity, would gladly pass this blame on to trillionaires. I suppose many persons have visited this story today and shook their heads in righteous indignation, never once thinking to take their own gains from the past year’s stocks and bestow them to the poor. No, that’s a problem for the truly rich, where by truly rich I of course mean anyone who has one dollar more than oneself. If having wealth means having guilt, which it does not, then there will always be those out there who are guiltier, to whom we may eagerly point the accusatory finger.

Pushing to a Protected GitHub Branch Still Sends the Commit to GitHub  

GitHub’s article on protected branches states that a protected branch can’t be force pushed nor can it have changes merged into it that haven’t passed CI. Asssuming you’ve set up CI on your repo, this means that you can never push to a protected branch from your local machine (even a non-forcing push), since the only way for CI to pass is through a Pull Request. What I’ve discovered though is that if you do a git push to a protected branch, GitHub rejects the branch from updating but the commit itself exists on GitHub’s server in limbo, untied to any branch (i.e. it has zero connectivity). Since GitHub never purges commits regardless of their connected state, you can access your rejected commit in perpetuity with this URL scheme:

https://github.com/<account>/<repo>/commit/<sha>

What Could’ve GoDaddy Done Differently?  

Last month, Chris Brogan had an interesting story to tell about a domain that GoDaddy sold and then retracted due to a price glitch. It’s a long story and I won’t attempt to summarize it here. Read it in full and then come back.

Clause 10 of the GoDaddy Legal Agreements and Policies gives GoDaddy the right to do exactly what Chris is so upset about:

GoDaddy expressly reserves the right to deny, cancel, terminate, suspend, lock, or modify access to (or control of) any Account or Services (including the right to cancel or transfer any domain name registration) for any reason (as determined by GoDaddy in its sole and absolute discretion), including but not limited to the following: (i) to correct mistakes made by GoDaddy in offering or delivering any Services (including any domain name registration) […]

To correct mistakes made by GoDaddy in offering or delivering any Services (including any domain name registration). You agree to this ToS when you buy a GoDaddy domain.

Chris:

With something as important as a domain purchase, there either must be a real time option available OR there has to be a lot more/better communication flow explaining this experience.

The realtime concept just isn’t a realistic option. And while it’s true that GoDaddy could be more in-your-face about the conceivable scenarios where clause 10 of its ToS might come into play, the scenarios in which it does come into play are exceedingly rare, as evidenced by Chris’ shock despite being a longstanding customer. What GoDaddy could do is have a summary of clause 10 at font size 11 in the footer of the checkout page, although no one is going to read that. But giving this information a truly prominent position at checkout is absurd since it almost never actually happens.

Regardless, it’s unfair to expect GoDaddy to be obligated to its up-front price and eat $550 on a single transaction. That’s like short selling — the sky’s the limit on how much the company could lose on a premium domain glitch like this.

The customer may choose to abandon his cart, and the merchant may choose to abandon the sale. Both parties have this freedom. Those are the rules of engagement when it comes to domain purchases. It’s clearly stated in the ToS. If you have a problem with that, you have the freedom to not buy domains.

My biggest beef with GoDaddy in this story is the fact that it gifted this domain simply because of the prominence of the customer’s lover. GoDaddy should be consistent and stick to its policies regardless of the pedigree of who’s whining.1


  1. The amount of ruckus that Chris has raised over this makes his statement here to seem disingenuous: “To be utterly honest, if the price started at $650, Jacq would’ve bought it without flinching.” If Chris really meant this, he would’ve put his money where his mouth was, and gone forward with the deal at the new price. ↩︎