TIL: divide by 10 with this one weird number
Running an application across two physical databases is not a straightforward thing. One of the relatively easier ways to do it involves assigning each database instance a shard number and then arranging for all your primary key IDs to end with that number. For example, shard 0 generates IDs like 1230, 40, 482340
, shard 1 generates IDs like 1231, 41, 482341
, and shard 2 generates IDs like 1232, 42, 482342
, etc. all the way up to 9. If you want more than 10 database shards, it gets more involved.
My brain is wired oddly, so I came to wonder how you would quickly get the shard ID for an ID (e.g. shard 1 for 1231
). This is really easy with decimal math; you just divide by 10. However, we run our databases on computers that can only do binary math, so its not actually simple.
But it turns out you can do it quite fast! There’s one weird number, expressed as <code>0x1999999A
hexadecimal, that is very close to multiplying by the fraction 1/10
(plus further binary math and register trickery). Thus you can do this in only a few instructions on Intel processors released in the past twenty years.
I’m really glad someone else figured this out.
If I could imagineer Tomorrowland for a moment
A little bit of fan reflection on Transportation in Tomorrowland and how to revitalize it:
When you visit Disneyland in California, how do you feel when you walk down Main Street, U.S.A. and turn right to enter Tomorrowland? I mostly feel a combination sadness and frustration when I walk through Tomorrowland–primarily due to the misplaced and pathway– clogging Astro Orbiter and the vacant, rotting PeopleMover track. And while fantasy space travel is well represented in Tomorrowland (Buzz Lightyear Astro Blasters, Star Tours, and Space Mountain), any semblance of tangible ways of pondering, dreaming about, and honoring humankind's achievements and the wonders of the future are long gone. It's as if Disneyland, like seemingly so much of the world, gave up on an optimistic view of the future, too.
Personally, I’d copy/paste the Magic Kingdom People Mover over to Disneyland, keep the monorail as-is, bring back the motor boat cruise as some kind of “see the world from a personal-sized yacht” thing, and reimagine Autopia as pure-electric autonymous cars that are integrated with pedestrian, bicycle, and commercial traffic in a way that is less car-centric as our current world. The five second pitch: the future of transportation is global and interconnected.
JavaScript's amazing reach
There’s plenty of room to criticize JavaScript as a technology, language, and community(s). But, when I’m optimistic, I think the big things JavaScript as a phenomenon brings to the world are:
- amazing reach: you can write JS for frontends, backends, games, art, music, devices, mobile, and domains I'm not even aware of
- a better on-ramp for people new to programming: the highly motivated can learn JS and not worry about the breadth of languages they may need to learn for operations, design, reporting, build tooling, etc.
- lots of those on-ramps: you could start learning JS to improve a spreadsheet, automate something in Salesforce, write a fun little Slack bot, etc.
In short, JavaScript increases the chances someone will level up their career. Maybe they’ll continue in sales or marketing but use JS as a secret weapon to get more done or avoid tedium. Maybe it gives them an opportunity to try programming without changing job functions or committing to a bootcamp program.
Bottom line: JavaScript, like Ruby and PHP before it, is the next thing that’s improving the chances non-programmers become programmers and reach the life-improving salary and career trajectories software developers have enjoyed for the past decade or two.
👍 Master of None Season 2
Just finished watching Master of None, season 2. What a great show. It’s hilarious without being campy, poignant without being a downer. Aziz Ansari is very good at this. Also, now I just want to listen to old Italian music and eat food.
If I were a producer: DJ Khaled
Actually, I probably wouldn’t change much. But I have questions about this marketing photo:
[caption id=“attachment_4434” align=“aligncenter” width=“487”] People, do not pose with apex predators. And especially, don’t keep them as domestic pets. I’m looking at you, oil billionaires.[/caption]
- Just, no. Do not pose with apex predators, even the little ones. Not okay, Mr. Khaled. I know this isn't a question?
- Why doesn't said apex predator kitty get a matching robe?
- Are you, Mr. DJ Khaled, just a catchphrase soundboard? Have you, at any time, been a soundboard? Is this like a Blue Man Group thing where there are multiple, anonymous DJ Khaleds?
Thank you for your time, DJ Khaled. Grateful is actually pretty good pop music.
If I were a producer: Muse
I have feelings about Muse, but let’s talk about this particular song I’m listening to right now: “Big Freeze” off The 2nd Law. In general, I would overgeneralize Muse’s music as “future-prog”. But this song has a) the typical fuzz bass Muse uses, b) nearly chicken grease guitar chords, and c) a distinct U2 vibe. I’m not sure these things all go together. If’d been the producer on this track, I’d have tried to convince them that chicken grease chords are cool as heck, but they don’t belong on any of Muse’s album tracks.
I welcome our future computer assistants...
…but they’re going to have to deal with the fact that my wife and I commonly have exchanges like this:
Me: can you hand me the thingy from the thing?Courtney: this one?
Me: which one?
Courtney: the one I’m pointing at
Me: I’m not looking at you
Courtney: this one
Me: the thingy!
Good luck, machine learners!
Computers are coming for more jobs than we think
A great video explainer on how computers and creative destruction are different this time. Why Automation is Different this Time. Hint: we need better ideas than individualism, “markets”, and supply-side economics for this to end well. Via Kottke.
OAuth2 🔥-takes
Is it too late to do hottakes for something that’s been around for nearly a decade?
OAuth2 pros:
- I can allow other sites to use my data with some confidence that, at least, my authentication information won't leak
- It has made really cool stuff possible at my current workplace and workplace-2
- Libraries to make it happen in server-side apps are pretty good
Cons:
- There are a bajillionty implementations and standard definitions of OAuth2 (for somewhat justifiable reasons)
- If you want to tinker with an OAuth2 API, you're in a bit of hurt because you can't just grab a token and start playing (mostly, depending on the implementer)
- Those open source libraries are the kind of thing that drive maintainers away pretty quickly 😬
Overall: would not uninvent this technology.
The emotional rollercoaster of extracting code
There’s a moment of despair when extracting functionality from a larger library, framework, or program. The idea grows, a seed at first and then a full-blown tree, that the coupling in this functionality isn’t all bad. A lot of people talk only about coupling and leave out cohesion. They aren’t mutually exclusive! When the two are balanced, it’s hard to come up with a reason to start extracting.
On the other hand, sometimes that moment of despair strikes when you start really digging into the domain and realize this chunk of functionality isn’t what you thought it was. Maybe it’s not coherent (see above!) or perhaps the model of the domain isn’t deep enough. This is a pretty good signal to hit the brakes on the refactoring, figure the domain out, and reconsider the course of action.
Feature envy rears its head in extractions too. Patterns of crosstalk between the existing thing and the new thing are a sure sign of feature envy. It’s tempting to say, hey maybe you really need a third thing in the middle. That’s probably making matters worse though.
That said, changing bidirectional communication to unidirectional is usually a positive thing. Same for replacing any kind of asynchronous communication with synchronous. Or replacing lockstep coordination with asynchronous messaging. Envy is tricky!
(I) often encourage starting a new service or application within your existing “mothership”. The trendy way to say this right now is “monorepo all the things” or build a “modular monolith”. I find this compelling because you can leverage a lot of existing effort into operationalizing, tooling, and infrastructure. Once you know the domain and technical concerns specific to the new thing, you can easily extract into its own thing if you need to. The other edge of a monorepolith is that path dependence is a hell of a thing. Today is almost certainly an easier day to split stuff out than tomorrow.
A thing to consider pursuing is a backend-for-frontend service in pursuit of a specific frontend. It doesn’t even have to serve an application. You may have services that are specific to mobile, desktop, apps, APIs, integrations, etc. Each of these may need drastically different rates of change, technical features, and team sets.
Probably don’t split out a service so that a bunch of specialized people can build a “center of excellence” for the rest of the organization to rely upon. This is a very fancy way to say “we are too cool for everyone else and we just can’t stand the work everyone else is doing”. On their best day, the Excellence team will be overwhelmed by the volume of work they have put in front of themselves to make Everything Good. On their worst day, they will straight give up.
If you split something out, realize you’re going to have to maintain it until you replace it. And you’re going to rebuild the airplane while it’s flying. If you’re not really into that, stop now. Just because you can’t stand Rails, relational databases, or whatever doesn’t mean you should jump into an extraction.
What I talk about when I talk about cars
Human design: what went into deciding how a human-facing thing is made? How did they decide to put the infotainment screen there? Why are BMW dashboard lights orange-ish? Who designs gauges and do they know what they’re doing? What the hell is going on with Mercedes dashes? When will we stop using gearshifts? When will the scourge of the PRNDL knob leave us?
Mechanical design: i.e. why is this car the way it is from an engineering point-of-view? Why is the rear-engine 911 unique, special, and kinda dumb? What makes the BMW M1 a weird BMW and yet perhaps the most special? Why do Ferrari engines catch fire so frequently? Do BMW/Audi/Mercedes design their cars as sedans, coupes, or hatchbacks first?
History: What puts some brands, e.g. Ferrari and Porsche over the others? Is Audi interesting? What is the gestalt of Honda or Toyota? How did the Viper come to have a tractor engine and a Lamborghini body? How does a BMW M car become “the next coming of BMW Jesus?”
Emotion: What makes people think a car is special? What kind of person owns a Koenigsegg or Pagani? Why own a Lamborghini? Is it practical to drive a Ferrari touring car? When does an Acura TL make sense for someone who enjoys cars? What will enthusiast cars look like once electric cars are the norm; will we finally enter a world of boring aerolumps?
…amongst other things. So many questions, so many subjective answers. That’s what makes it fun!
More ideas for framework people
A few months ago I wrote about Framework and Library people. I had great follow-up conversations with Ben Hamill, Brad Fults, and Nathan Ladd about it. Some ideas from those conversations:
use a well-worn framework when it addresses your technical complexities (e.g. expose functionality via the web or build a 3-d game) and your domain complexity (e.g. shopping, social networking, or multi-dimensional bowling) is your paramount concern
once you have some time/experience in your problem domain, start rounding off corners to leave future teammates a metaframework that reduces decision/design burdens and gives them some kind of golden path
frameworks may end up less useful as integration surface area increases
napkin math makes it hard to justify not using a framework; you have to build the thing and accept the cost of not having a community to support you and hire from
to paraphrase Sandi Metz on the wrong abstraction: “(Using) no abstraction is better than the wrong abstraction”; if you’ve had a bad time with a framework, chances it was an inappropriate abstraction or you used the abstraction incorrectly
Did you try editing the right file?
The first few years of my career, I edited the wrong file all the time. I could spend hours making changes, wondering why nothing was happening, until I realized I’d been tinkering in the wrong place because I was misreading a file path or not paying close enough attention to control flow.
Fast forward to now, and I’m pretty quick to drop a raise “BLORP”
in code I’m tinkering with if things aren’t working like I think they should. All hail puts debuggerering.
However, it turns out I found a new class of this operator error today. I was diligently re-running a test case, expecting new results when the test fixture file I thought was changed was the wrong file. Once I deleted the right file, I was back on my way.
Joyful and grumpy are we who can find new ways to screw up time ever day!
Chaining Ruby enumerators
I want to connect two Ruby enumerators. Give me all the values from the first, then the second, and so on. Ideally, without forcing any lazy evaluations and flat so I don’t have to think about nested stuff. Like so:
xs = [1, 2, 3].to_enum ys = [4, 5, 6].to_enum [xs, ys].chain.to_a # => [1, 2, 3, 4, 5, 6]
I couldn’t figure out how to do that with Ruby’s standard library alone. But, it wasn’t that hard to write my own:
def chain(*enums) return to_enum(:chain, *enums) unless block_given? enums.each { |enum| enum.each { |e| yield e } } end
But it seems like Ruby’s library, Enumerable
in particular, is so strong I must have missed something. So, mob programmers, is there a better way to do this? A fancier enumerator-combining thing I’m missing?
Stored Procedure Modern
The idea behind Facebook’s Relay is to write declarative queries, put them next to the user interaction code that uses them, and compose those queries. It’s a solid idea. But this snippet about Relay Modern made me chuckle:
The teams realized that if the GraphQL queries instead were statically known — that is, they were not altered by runtime conditions — then they could be constructed once during development time and saved on the Facebook servers, and replaced in the mobile app with a tiny identifier. With this approach, the app sends the identifier along with some GraphQL variables, and the Facebook server knows which query to run. No more overhead, massively reduced network traffic, and much faster mobile apps.Relay Modern adopts a similar approach. The Relay compiler extracts colocated GraphQL snippets from across an app, constructs the necessary queries, saves them on the server ahead of time, and outputs artifacts that the Relay runtime uses to fetch those queries and process their results at runtime.
How many meetings did they need before they renamed this from “GraphQL stored procedures” to “Relay Modern”?
(FWIW, I worked on a system that exposed stored procedures through a web service for client-side interaction code. It wasn’t too bad, setting aside the need to hand write SQL and XSLT.)
We should get back to inventing jetpacks
I don’t like using services like Uber, Twitch, or Favor. I want to like them, because the underlying ideas are pretty futuristic. But the reality of these services is that the new boss wants to squeeze their not-even-employess-anymore just as badly the old boss did. It feels manipulative, like buying a car. Except I’m abetting the manipulation too. :(
The New Yorker, THE GIG ECONOMY CELEBRATES WORKING YOURSELF TO DEATH:
The contrast between the gig economy’s rhetoric (everyone is always connecting, having fun, and killing it!) and the conditions that allow it to exist (a lack of dependable employment that pays a living wage) makes this kink in our thinking especially clear.
What happens when the gig economy tries to turn a profit? The race downwards will squeeze out all of their contractors until they can replace them all with automated drivers, commoditized personalities, and punitively-low ad revenue sharing rates. This sounds horribly dystopian but I’m pretty sure it’s already happening. See also: when Google kneecapped bloggers as a side-effect of end-of-lifing Reader and changing Pagerank.
The New York Times, Platform Companies Are Becoming More Powerful — but What Exactly Do They Want?
Platforms are, in a sense, capitalism distilled to its essence. They are proudly experimental and maximally consequential, prone to creating externalities and especially disinclined to address or even acknowledge what happens beyond their rising walls. And accordingly, platforms are the underlying trend that ties together popular narratives about technology and the economy in general. Platforms provide the substructure for the “gig economy” and the “sharing economy”; they’re the economic engine of social media; they’re the architecture of the “attention economy” and the inspiration for claims about the “end of ownership.”
After reading this, I started substituting “platform company” for “company building its own monopoly”. And then it all makes sense. Businesspeople say they love free markets, but give any rational-thinking business the chance and they will create so many “moats” and “barriers to entry” that they resemble tiny state enterprises more than a private business. See also: telecoms and airlines.
Anil Dash, Tech and the Fake Market tactic:
This has been the status quo for most of the last decade. But the next rising wave of tech innovators twist the definition of “market” even further, to a point where they aren’t actually markets at all.
Yes, my confirmation bias is burning. Yes, technologists are doomed to recreate the robber-baron past they didn’t study. Yes, we still have time to change this. Yes, our field needs an ethics refresher. Yes, we should get back to inventing jetpacks!
Jeremy Johnson, It’s time to get a real watch, and an Apple Watch doesn’t count:
...watches are one of the key pieces of jewelry I can sport, and while many have no clue what’s on my wrist, those that do… well do. And they are investments. Usually good purchases will not only last forever (with a little love and care), but go up or retain most of their value over time.
When pal Marcos started talking to me about watches, I realized they checked all the boxes cars do, but at a fraction of the price. If cars check your boxes, look into watches. Jeremy’s intro will get you started without breaking the bank.
Feedback: timing is everything
With feedback, like jokes, timing is everything. Good feedback at a bad time won’t do the trick.
I’ve mostly experienced programming feedback through pull requests. This is way better than no feedback. However, since most pull requests occur at the end of work, and not somewhere in the middle, some kinds of feedback are not conducive to pull requests.
Suppose all feedback falls somewhere on two axes: “timeliness” and “depth”. The narrow sweet spot of code review is apparent:
[caption id=“attachment_4302” align=“alignnone” width=“861”] Pairing and code review are not so similar[/caption]
The sweet spot in the top-right corner is when code review works best: unhurried and in-depth feedback. I’d hesitate to call the lower-right corner of hurried, minimal feedback a code review at all; it’s more like rubber stamping.
I’ve often referred to code review, flippantly, as the worst form of pairing yet invented. I’ve given a lot of code review feedback in the past that was better suited to the synchronous nature of pairing than the very asynchronous nature of code reviews. That said, I feel like pairing is an excellent way to give all manners of feedback in the moment the code is being conceived or written. You can immediately point out possible incorrectness or better designs and talk it out, with the code at hand, with your collaborator.
However, we can’t all pair all the time. Let me show you how I’m trying to better time my feedback when I can’t share it immediately.
A tale of four pull requests
Consider four PR subject lines. Which ones are appropriate for architectural ideas? What about optimization ideas? When is deep refactoring feedback appropriate? Can I look at one of these in an hour when I’m done with my current task?
- “Hotfix Facebook Auth scope”
- “Prevent sending email for failed payment jobs”
- “Add tagging to admin storylines listing”
- “WIP introduce Redis/Lua-based story indexing”
Lately, when I do pull request reviews, I use these guidelines:
- Figure out if this PR seems like it’s a hot patch to production, a quick fix on existing work, a PR landing new functionality, or a work-in-progress checkpoint seeking feedback.
- Bear in mind that hot patches and quick fixes are more time sensitive and need yes/no feedback on correctness more than detailed feedback.
- For hot patches (e.g. “Hotfix FB auth”), I’m only looking for “is this correct” and “will it fix the problem?”; thumbs up or thumbs down and commentary as to what I think is missing to solve the problem. No refactoring ideas. I only touch on performance if I spot a regression.
- For quick fixes (e.g. “Prevent sending email…”), I’m again looking for correctness and timeliness. I might leave ideas for how to improve the performance or cleanliness of the code later. Those kinds of notes are entirely up to the gumption of the other developer, though. I know the low-gumption feeling of wanting only to fix something and get on to the next thing.
- Landing new functionality (e.g. “Add tagging…”) receives a full review cycle. Beyond baseline correctness, I’m trying to view this code through my crystal ball. When some value of
N
is grows, will this code slow down noticeably? Is the code structured so that future changes are easy and obvious? - Work-in-progress checkpoints (“WIP introduce Redis/Lua…”) are open to the full spectrum of feedback. Ideas for how to differently structure data, which APIs to export, how to structure objects, how to name the domain model, etc. are all in play. Pretty much the only thing out of play is anything that feels too close to bike shedding.
- Bear in mind that everyone exists on a spectrum of coding specificity. More seasoned developers are likely open to ideas for restructuring code or considering novel approaches. Less seasoned developers (including seasoned developers new to the team) likely want specific guidance about which changes to make or factors they need to consider.
- Where I may try to respond to hot patches and quick fixes in less than fifteen minutes, I may wait a couple hours before I look at new functionality or WIP reviews.
- The most difficult part with these guidelines is how to handle ideas about refactoring on time-sensitive reviews. I want to hold the line against letting lots of little fixes accrete into a medium-sized mess. I don’t want to discourage ideas for refactorings either; I want them separately so I can act on them when I have the energy to really do them.
In short
Use different tactics when sharing feedback for code review; it’s not pairing. Identify patches, reviews, and full feedback pull requests. Sanity check patches, look for correctness in review, look for design in review. Use GitHub’s review process to indicate your feedback is “FYI” vs. “fix this before merging”. Time-to-response is most important for patches and fixes.
Above all: giving feedback is a skill you acquire with practice, empathy, and maintaining a constructive attitude.
Practically applying Clojure
Fourteen Months with Clojure. Dan McKinley on using Clojure to build AWS automation platform Skyliner:
The tricky part isn’t the language so much as it is the slang.
Also, the best and worst part of Clojure:
When the going gets tough, the tough use maps
This is probably better now that specs and schema are popular. Before, when they were mysterious maps full of Very Important State, reading Clojure code (and any kind of Lisp) was pretty challenging.
Make sure you stick around for the joke about covariance and contravariance. Those type theories, hilarious!