exa in 30 seconds
What is it? exa is ls
reimagined for modern times, in Rust. And more colorfully. It is nifty, but not life-changing. I mostly still use ls
, because muscle memory is strong and its basically the only mildly friendly thing about Unix.
How do I do boring old ls things?
Spoiler alert: basically the same.
ls -a
:exa -a
ls -l
:exa -l
ls -lR
:exa -lR
How do I do things I rarely had the gumption to do with ls?
exa -rs created
: simple listing, sort files reverse by created time. Other options:name, extension, size, type, modified, accessed, created, inode
exa -hl
: show a long listing with headers for each columnexa -T
: recurse into directories alatree
exa -l --git
: showgit
metadata alongside file info
Generalization and specialization: more of column A, a little less of column B
- Now, I attempt to write in the style of a tweetstorm. But about code. For my website. Not for tweets.
- For a long time, we have been embracing specialization. It's taken for granted even more than capitalism. But maybe not as much as the sun rising in the morning
- From specialization comes modularization, inheritance, microservices, pizza teams, Conway's Law, and lots of other things we sometimes consider as righteous as apple pie.
- Specialization comes at a cost though. Because a specialized entity is specific, it is useless out of context. It cannot exist except for the support of other specialized things.
- Interconnectedness is the unintended consequence of specialization. Little things depend on other things.
- Those dependencies may prove surprising, fragile, unstable, chaotic, or create a bottleneck.
- Specialization also requires some level of infrastructure to even get started. You can't share code in a library until you have the infrastructure to import it at runtime (dynamic linking) or resolve the library's dependencies (package managers).
- The expensive open secret of microservices and disposable infrastructure is that you need a high level of operational acumen to even consider starting down the road.
- You're either going to buy this as a service, buy it as software you host, or build it yourself. Either way, you're going to pay for this decision right in the budget.
- On the flip side is generalization. The grand vision of interchangeable cogs that can work any project.
- A year ago I would have thought this was as foolish as microservices. But the ecosystems and tooling are getting really good. And, JavaScript is getting good enough and continues to have the most amazing reach across platforms and devices.
- A year ago I would have told you generalization is the foolish dream of the capitalist who wants to drive down his costs by treating every person as a commodity. I suspect this exists in parts of our trade, but developers are generally rare enough that finding a good one is difficult enough, let alone a good one that knows your ecosystem and domain already.
- Generalization gives you a cushion when you need help a short handed team get something out the door. You can shift a generalist over to take care of the dozen detail things so the existing team can stay focused on the core, important things. Shifting a generalist over for a day doesn't get you 8 developer hours, but it might get you 4 when you really need it.
- Generalization means more people can help each other. Anyone can grab anyone else and ask to pair, for a code review, for a sanity check, etc.
- When we speak of increasing our team's bus number, we are talking about generalizing along some axis. Ecosystem generalists, domain knowledge generalists, operational generalists, etc.
- On balance, I still want to make myself a T-shaped person. But, I think the top of the T is fatter than people think. Or, it's wider than it is tall, by a factor of one or two.
- Organizationally, I think we should choose what the tools and processes we use carefully so that we don't end up where only one or two people do something. That's creating fragility and overhead where it doesn't yield any benefit.
Not-a-Science Science
Any field with the word "science" in its name is guaranteed not to be a science.
– Gerald Weinberg, An Introduction to General Systems Thinking
The loungification of luxury cars
High-end luxury cars are starting to resemble first-class airport lounges and it’s bothering me.
The Porsche Panamera has a dang tray table. Just about every German luxury car has the option to put an LCD screen on the back of the front seats, for entertainment. Who puts $100k+ down on a car so that someone else can drive you around? The seats recline, have tablets to control their massage and scent-control functions. Of course they’re heated and ventilated.
I’m fine with cars as things that merely get you from point A to point B, and I’m fine with rich people buying extravagant cars, but I’m not okay with this airport lounge stuff. No one likes airports! They’re miserable! Stop designing things to resemble airports!
Categorizing and understanding magical code
Sometimes, programmers like to disparage “magical code”. They say magical code is causing their bugs, magical code is offensive to use, magical code is harder to understand, we should try to write “less magical” code.
“Wait, what’s magic?”, I hear you say. That’s what I’m here to talk about! (Warning: this post contains an above-average density of “air quotes”, ask your doctor if your heart is strong enough for “humorous quoting”.)
Magic is code I have yet to understand
It’s not inscrutable code. It’s not bad code. It doesn’t intentionally defy understanding, like an obfuscated code contest or code golfing.
I can start to understand why a big of code is frustratingly magical to me by categorizing it. (Hi, I’m Adam, I love categorizing things, it’s awful.)
“Mathemagical” code escapes my understanding due to its foundation in math and my lack of understanding therein. I recently read Purely Functional Data Structures, which is a great book, but the parts on proving e.g. worst-case cost for amortized operations on data structures are completely beyond my patience or confidence in math. Once Greek symbols enter the text, my brain kinda “nope!”s out.
“Metamagic” is hard to understand due to use of metaprogramming. Code that generates code inside code is a) really cool and b) a bit of a mind exploder at first. When it works, its glorious and not “magical”. When it falls short, it’s a mess of violated expectations and complaints about magic. PSA: don’t metaprogram when you can program.
“Sleight of hand” makes it harder for me to understand code because I don’t know where the control flow or logic goes. Combining inheritance and mixins when using Ruby is a good example of control flow sleight-of-hand. If a class extends Foo
, includes Bar
, and all three define a method do_the_thing
, which one gets called (trick question: all of them, trick follow-up question: in what order!)? The Rails router is a good example of logical sleight-of-hand. If I’m wondering how root to: “some_controller/index”
works and I have only the Rails sources on me, where would I start looking to find that logic? For the first few years of Rails, I’d dig around in various files before I found the trail to that answer.
“Multi-level magic schemes” is my new tongue-in-cheek way to explain a tool like tmux
. It’s a wonderful tool for those of us who prefer to work in (several) shells all day. I’m terrified of when things go wrong with it, though. To multiplex several shells into one process while persisting that state across user sessions requires tmux
to operate at the intersection of Unix shells, process trees, and redrawing interfaces to a terminal emulator. I understand the first two in isolation, but when you put it all together, my brain again “nope!”s out of trying to solve any problems that arise. Other multi-level magic schemes include object-relational mappers, game engines, operating system containers, and datacenter networking.
I can understand magic and so can you!
I’m writing this because I often see ineffective reactions to “magical” code. Namely, 1) identify code that is frustrating, 2) complain on Twitter or Slack, 3) there is no step 3. Getting frustrated is okay and normal! Contributing only negative energy to the situation is not.
Instead, once I find a thing frustrating, I try to step back and figure out what’s going on. How does this bit of code or tool work? Am I doing something that it recommends against or doesn’t expect? Can I get back on the “golden path” the code is built for? Can I find the code and understand what’s going on by reading it? Often some combination of these side quests puts me back on my way an out of frustration’s way.
Other times, I don’t have time for a side quest of understanding. If that’s the case, I make a mental note that “here be dragons” and try to work around it until I’m done with my main quest. Next time I come across that mental map and remember “oh, there were dragons here!”, I try to understand the situation a little better.
For example, I have a “barely tolerating” relationship with webpack
. I’m glad it exists, it mostly works well, but I feel its human factors leave a lot to be desired. It took a few dives into how it works and how to configure it before I started to develop a mental model for what’s going on such that I didn’t feel like it was constantly burning me. I probably even complained about this in the confidence of friends, but for my own personal assurances, attached the caveat of “this is magical because it’s unfamiliar to me.”
Which brings me to my last caveat: all this advice works for me because I’ve been programming for quite a while. I have tons of knowledge, the kind anyone can read and the kind you have to win by experience, to draw upon. If you’re still in your first decade of programming, nearly everything will seem like magic. Worse, it’s hard to tell what’s useful magic, what’s virtuous magic, and what’s plain-old mediocre code. In that case: when you’re confronted with magic, consult me or your nearest Adam-like collaborator.
Bias to small, digestible review requests. When possible, try to break down your large refactor into smaller, easier to reason about changes, which can be reviewed in sequence (or better still, orthogonally). When your review request gets bigger than about 400 lines of code, ask yourself if it can be compartmentalized. If everyone is efficient at reviewing code as it is published, there’s no advantage to batching small changes together, and there are distinct disadvantages. The most dangerous outcome of a large review request is that reviewers are unable to sustain focus over many lines, and the code isn’t reviewed well or at all.
This has made code review of big features way more plausible on my current team. Large work is organized into epic branches which have review branches which are individually reviewed. This makes the final merge and review way more tractable.
Your description should tell the story of your change. It should not be an automated list of commits. Instead, you should talk about why you’re making the change, what problem you’re solving, what code you changed, what classes you introduced, how you tested it. The description should tell the reviewers what specific pieces of the change they should take extra care in reviewing.
This is a good start for a style guide ala git commits!
Fewer changes are faster to deploy than fewer changes
Itamar Turner-Trauring, Incremental results: how to succeed at large software projects:
- Faster feedback...
- Less unnecessary features...
- Less cancellation risk...
- Less deployment risk...
👏 👏 👏 👏 👏 read the whole thing, Itamar’s tale is well told.
Consider: incremental approaches consist of taking a large scope and finding smaller, still-valuable scopes inside of it. Risk is 100% proportional to scope. Time-to-deliver grows as scope grows. Cancellation and deployment risk grow as time-to-deliver grows. It’s not quite math, but it is easy to demonstrate on a whiteboard. In case you happen to need to work with someone who wants large scope and low risk and low time-to-delivery.
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.