Everyone wins: document whatever resists simplification
The traditional prescription for keeping software easy to work with and amenable to change is “refactoring”. As we’re fixing bugs, adding features, and making new possibilities, we investigate how to change the structure of code so that correcting, changing, or adding behavior is easier. In reverse order — we should make the change easy, then make the easy change to achieve the desired results1.
I may not surprise you in suggesting that’s often not how things actually work out.
Some code, processes, or data are inherently complex or crystalized in path dependence. After our first urge to simplify is stymied, move on to the second possibility: live with and document the complexity, then keep moving2. Everyone wins.
Documenting code is a great forcing function for simplifying it. When I look at code with the intent of writing down how to use or understand it, my perspective shifts, and I’m more aware of the missing affordances. A clarifying parameter name or perhaps a simpler calling sequence. So I make that change (aka refactoring) as part of the process of documenting the code. Everyone wins.
The same goes for processes and data. Writing down how to fix an unprocessed payment or restore data after an accidental deletion flips my perspective enough that I’m not seeing it in the weeds. I can see opportunities for automation, so I take them. Or I can see how to improve a data structure such that errors are obvious to humans or detectable by computers. I make that change, everyone wins.
It’s not always possible to find these little wins. Occasionally, we don’t win!
Some systems, especially the older and critical ones, resist change. The volume of data may be the resistance to change, the process may touch too many people to casually change, the risk of updating code may be too great. If you’ve worked on a billing system, I bet you’re hallucinating memories of it at the mere mention of data, process, people, and code resisting even the smallest change in course.
In that case, the next best way to improve the situation is to improve everyone’s knowledge of the system by writing it down. Document how it works. Even better, elaborate on how it’s supposed to work and how it actually works in some important but problematic circumstances.
Go from tricky code to refactoring. If you’re stymied by refactoring, switch to documenting it instead. Everyone wins.
Pastoral and modern approaches to attention
Alan Jacobs, the attention cottage (Via Austin Kleon). I was not expecting to quote an attention metaphor involving the cardiovascular system and cottages, and yet:
To care only for things temporal is to lose the things eternal; but to attend rightly to things eternal is the royal road to constructive thought and action in the temporal realm. The great artists and thinkers cultivate a systolic/diastolic rhythm, tension and release, an increase and then decrease of pressure. In the latter phase they withdraw, by whatever means available to them, to their attentional cottage for refreshment and clarification — and then they can return to the pressures of the moment more effectively, and in ways non-destructive to them and to others.
But most of us, I think, get the rhythm wrong: we spend the great majority of our time in systolic mode — contracted, tensed — and only rarely enter the relaxed diastolic phase. Or, to change the metaphor: We think we should be living in the chaotic, cacophanous megalopolis and retreat to our cottage only in desperate circumstances. But the reverse is true: our attention cottage should be our home, our secure base, the place from which we set out on our adventures in contemporaneity and to which we always make our nostos.
I often think how much easier, how much more naturally healthy, life was even just a couple of decades ago, when the internet was in one room of the house, when the whole family had one computer connected to a modem that was connected to a landline, and movies arrived in the mailbox in red envelopes.
I love a cottage/workshop/garage metaphor. Doubly so when they recall a time when distraction had yet to pervade our homes and lives.
The past is gone, we’re not going back to Netflix DVD mailers. So how do we carry the idea of inhale/exhale and space forward? I’m trying a few things currently 1:
Minimize apps with an adversarial agenda. Currently: YouTube is only on my iPad, but the intent is I mostly watch via AppleTV. Twitter, Ivory, and Instagram are only on my phone. Reading apps (Books, Kindle, Reader, Reeder) are on all my devices. In other words, the apps aligned with my goals (read more of what I choose, think bigger thoughts) are everywhere and the ones that want to direct my attention to advertisements (mostly) are only present where my attention is (probably) already scattered.
Hold devices to a purpose. The intent here is that I’m holding my iPad largely for reading, focus, and writing. My laptop is largely for writing, publishing, and collaboration. The Kindle is, obviously focused on reading alone, despite the predations of Amazon into all possible revenue streams elsewhere.
Treat the transition to focus with reverence, if not physical space. When I’m reading or writing, I try to keep my phone out-of-reach. If not in another room. My laptop sits in a (part of the) room where I’m only focused on writing, ideas, publishing, or keeping those things operating smoothly. Whether I’m in my home office or making do on a roadtrip, this is the attention cottage Jacobs mentions above.
It’s not quite as quaint as an actual cottage. But, it does an okay job balancing the pastoral with the modern.
-
Caveat, “currently” is on a long road-trip. Read about it! ↩︎
Delegate, don’t dictate
It’s the only way to survive as an engineering leader.
- Hand off tasks/work to the team
- Give guidelines, execution tactics, or constraints to keep things on track
- Set an expectation of what to deliver and when
- Get out of the way
Delegate not only the main/critical path work, but also “the toys” and interesting/exciting work. Give away your toys.
Even more difficult: don’t tell someone how to do it. Give context (“why”) and constraints. A few style guides perhaps (i.e., codified influence!). But, work with the team to develop the style guide, raise the standard, and enforce the standard. Provide constraints that keep them on track and/or reduce the problem space.
Leadership is about executing through other people. To some extent, that means influencing your team to do the right work efficiently and effectively. That’s delegation in a nutshell.
Beginners helping experts
“In the beginner’s mind, there are many possibilities. In the expert’s mind, there are few.”
— Shunryo Suzuki
The trick being, how can an expert help a beginner, given they know all the false paths. And how can the expert encourage the beginner to help them find new ideas, knowing all the paths they’ve followed in the past?
The distinguishing quality of beginner-ness is that every rock turned over has something surprising or interesting under it. It’s all rabbit holes to fall down or rakes to step on.
When there are no time constraints present, it’s fine to explore these ideas, some of which may not be fruitful. Or, to figure out exactly why the result was surprising and not intended.
When time is of the essence, being a beginner is sometimes pretty dang stressful. Doubly so when the path to productivity is littered with novelty.
Ergo, Make Failure A (Safe) Option.
I feel lucky that I was able to learn a lot about software development in high school and college. Mostly, self-directed; I used Linux during college, spent a lot of time compiling Enlightenment and tinkering with up-and-coming languages you may have heard of, namely Python and Ruby (and to some extent, Lisp and ML).
Beginners today are thrown straight into narrowly guided tutorials and online courses. Then they’re dropped into the wilds of innumerable Unix minutiae, source control, relational databases, multi-paradigm programming languages, styling in browsers, and agile methods. I realized I was firmly in the “expert developer” camp when I could spot all the rabbit holes and rakes-in-leaves three moves ahead. I deftly maneuvered in the dark, knowing by feel where the potential problems were and how to avoid them.
It’s difficult to impart that knowledge to beginners. It’s not principles, it’s compounded experience. Worse, beginners find themselves amidst a hustle culture of “ship a side project alongside your day job and somehow do that whilst traveling the world”. Or, become a “content creator”. Most importantly, I knew a side-hustle and creator1 lifestyle were not for me.
I’m certain beginners can help me find new and interesting angles. But it’s difficult to thread the needle between listening for insight and skipping ahead to what I know will work. It’s tempting to say, “I see where you’re going, but there are hazards ahead and here’s all the ways your approach could stymy us.” For one, failing is a pretty dang effective way to learn! For another, “don’t do that, I’ll tell you why later” is a pretty lousy way to acquire knowledge.
One lesson I’ve learned from beginners is that probably we should design systems without reliance on understanding the full depth and breadth of the computing world. Folks don’t have the time or energy to get Very Good at ./configure; make; make install
2 like I did in college.
Beginners are pretty good at working incrementally. They have to, lest they get lost in all the stepping on rakes and learning of minute! Many experienced developers have forgotten how to build incrementally. They glimpse the glass castles in the sky and plow ahead to realizing them, only to find themselves stepping on different kinds of rakes hidden in the leaves.
Expert mistake number one: try to skip past all the beginner’s insights. That is, the beginner’s mind.
Teammates new to software development and new teammates on the team, accidentally or intentionally, can both reveal useful information about your team, process, and software. Information that is otherwise difficult to come by. There are things everyone is accustomed, and thus blind, to that a beginner can tell you straight away.
I have to remind myself that this is a critical moment. Don’t skip straight to “onboarding them onto the team’s culture” by explaining the history and the why-or-why-not. I should listen to the insight, evaluate the idea, and bias to act on it if I can.
A group of experts can make great things. But a group of experts with a beginner alongside can assimilate new ideas and make great and interesting things.
See also:
- Austin Kleon, Show Your Work
- James Clear, This Zen Concept Will Help You Stop Being a Slave to Old Beliefs
Humble writing
I’m trying to change up my blogging style: write without telling people what to do. Show, don’t tell. It’s a stronger writing position to take. It’s the difference between writing social media “content” and writing from a place of earnestness/honesty.
- Advocate by telling a compelling story.
- Motivate by strength of logic alone.
- Change minds by revealing an obvious truth that was once obscured.
- No shortcuts.
The way I read him, Kurt Vonnegut (might) want it that way. Who knows, he can’t tell us now!
Try smarter, not harder
“Try harder” is the worst kind of plan. It’s basically not a plan, a small resistance to planning. An anti-plan that signals virtue but instead reflects shallow thinking.
Don’t say “try harder”.
“Try harder” implies that folks haven’t been working hard enough. It leaves the door open to come up short again, for all the same reasons, with little to show for it.
It assumes folks can throw themselves at a project/problem/task even harder without consequences, like exhaustion, burnout, diminished performance, letting important part of their lives suffer, etc. Not only that, but it’s a terminating thought, the kind of thing you can say, and few people will say “well no, we can do better than that” and end up not solving any underlying issues.
“Try harder” is trying to avoid a tough question: why did I/we come up short last time? “Try harder” is resignation to learning nothing and plowing head-down anyway.
Try harder is literally working harder, not smarter. I highly recommend the latter.
The leisure/disconnection/creation circuit
Two prolific, internet-known travelers:
- Craig Mod: writer, walker, photographer, software-adjacent
- Brock Keen: photographer, car camper, road-tripper, Porsche-enthusiast
These gentlemen are particularly good at two things that I am not: getting outside and unplugged, and photography. (Also: walking and camping.) From the outside, their projected life/identity seems like a vacation1. In particular, they take quite different sort of vacations than I do: not Disneyland nor dog agility-adjacent.
They go out into the world, force a little disconnection. Setting aside this is part of their thing, they are separate from whatever knowledge work they might do.
I often want to better disconnect from my knowledge work, even for a couple of hours each night. And, it occurs to me that I can achieve that on any particular kind of vacation. A trip to a Disney resort is a fine opportunity to shift my mind to the present and to my intellectual/reading/writing interests2.
Disengagement en route to thinking
Mod and Keen generate a desire to think by converting walking/driving mileage into boredom and then, alchemy!, better thoughts.
Maybe our generally less-stimulated existences, before pervasive computing and social media, correlate with thinking better thoughts. i.e., does it require some kind of disengagement to be a Great Thinker in the age of pervasive networking and computing?
Keen is not specifically about thinking, whereas Mod is thinking adjacent. Possibly, more about disengagement. Yet, something about it makes me think I could do better thoughts in something like that existence.
Disengagement as precondition to creativity
What if some degree of disengagement is already table stakes? Not disengagement like Waldenponding. More like returning to a clear mind and thinking one’s own thoughts. Like, you have to say no to all the distractions that you said yes to in the first place (whether accidentally over optimistically) to do a great thing/thought. Jenny O’Dell has written the book on this, recommended.
Vacation is a tool for disconnection and disengagement adjacency
I wrote A Vacation is a Tool For Disconnecting amidst a few weeks wherein we vacationed in Disneyland and stayed in a friend’s RV at a public park while Courtney did dog agility. Despite this not being the most disconnected (I was, in fact, very connected) or disengaged (Disneyland is quite stimulating), my mind reached a good place.
I wasn’t dwelling on things. I could stop thinking about work once as soon as it snuck into my thoughts. I enjoyed quiet moments and didn’t rush to fill them with distractions. I photographed and journaled and jotted down ideas on the spot and posted photos to blogs. It was pretty dang good.
But I still found myself sitting there, half-writing and half-journaling, sort of feeling like I’m not prolific enough, even on vacation/disconnection. So maybe disconnection/disengagement isn’t the central thing. Or, ambition and aspiration are orthogonal to personal/work life splits and balances and how they manifest as some degree of “going offline”.
Possibly, if I were on a road trip or walking or in nature or disengaged or whatever, I would find this feeling/vibe anyway. Is that the disengagement or disconnection talking?
Show up every-dang day
Anne-Laure Le Cunff, 4 science-backed ways to build your own mental gym:
Building mental strength is not too different from building physical strength. It’s all about consistency. The same way you would take a few minutes to do a few push ups, you can incorporate mental pushups in your daily routine.
Be curious:
The last one is extremely powerful. Multiple research studies show the positive impact teaching someone else has on the comprehension and recall of any material.
Get creative:
There is evidence that practicing activities such as music, drawing, arts and crafts stimulate our brain in a way that enhances our health and well-being. These activities also have a positive impact on our emotional resilience.
Be mindful:
Choose a topic. It should be personal, emotional, and important to you. Write for yourself. Do not imagine your writing being read by other people. Let go. Don’t worry about style, spelling, punctuation, or grammar.
Get some rest:
A great way to combine short breaks and sleep are, of course… Naps! If you’re fortunate enough to work in an environment where taking a nap during the day is possible, do take that opportunity.
I can’t overstate how good naps are. Second only to easy access to comfort from a dog, naps are the best of work-from-home benefits.
Personal websites are corner stores and neighborhood garages
Is a personal blog or general-purpose more like a small shop or your local garage?
They’re a bit of a calm business.
A corner store with a friendly owner/operator. Never grows beyond its means. Operates at relatively-human scale. Greet every customer, have a nice conversation, send them away with something interesting. Aims for an infinite game, not limitless growth. It may not ever turn a profit, but that’s okay; neither do most restaurants or start-ups.
A good neighborhood store might make me think, “I wonder if Sam has anything interest in stock this week?” A good blog should make me hope Sam has new posts, with confidence that they’re probably pretty good.
But, a personal web space is a bit of a sports car in a workshop too.
It’s meant to enjoy, for driving. But also for nostalgia, for looking and remembering. Showing it off is important! It’s not quite as good as what you could go out and buy new, but that’s most of the charm. Working on it is part of the fun, but often a source of frustration and expense.
An interesting garage might make me think, “Hey I wonder what car Hank is working on this week?” A good blog makes me think, Hank’s site is so fascinating, I should go talk to him about it or make my own.
A lovely thing, personal websites are!
A big bucket of text
Matt Stein, How I Use Obsidian:
It’s also just a heap of Markdown I’ve carried around and put Obsidian in charge of sometime late in 2021. Those plain text files are mine and they don’t need Obsidian to be useful; I can open the same folder with iA Writer or Sublime Text and get right to work.
This is The Way to think about notes apps. Not a principle or lifestyle, but a layer of leverage over a big bucket of text.
Don’t fret if it starts off as an unimpressive pile of ideas or an overwhelming and unorganized collection of disconnected ideas. Use tools to organize and resurface the ideas, but don’t let that be the end goal. The end goal is to think better thoughts!
Recently in pair programming with AI
My recent experience with GitHub Copilot Chat (non-autocomplete assistance) and Raycast’s ChatGPT-3.5 integrations lead me to think that prompting will be a crucial skill for most knowledge workers. (I’m hardly the first person to this observation!) Not quite so obtusely as using a Unix shell and command-line programs is for programmers. But, still a thing one will want to know how to get the most out of.
A few examples:
- Talking/prompting a model into doing permutations and set math. This one is still blowing my mind a little. How does a word predictor do symbolic math? Not so much a stochastic parrot in this case!
- Coaching a model to write like me, provide useful feedback, and not use the boring/hype-y voice of Twitter or whatever a model was trained on. Hitting “regenerate” a few times to get options on different prose to include. Using the model as an always-available writing partner. In particular for “help me keep going/writing here…”.
- Building up programs from scratch with the assistance of a Copilot. Incrementally improving. Asking it for references on how to understand the library in question. Asking it for ideas on how to troubleshoot the program. I’ve used this to generate the boilerplate to get started with CodeMirror, with some success.
Elsewhere
Simon Willison, Building and testing C extensions for SQLite with ChatGPT Code Interpreter:
One of the infuriating things about working with ChatGPT Code Interpreter is that it often denies abilities that you know it has.
A non-trivial share of the prompting here is to remind ChatGPT “this is C and gcc
, you know this”. I am not sure whether to eye-roll or laugh. Maybe part of the system prompt is “occasionally, you’ll require a little extra encouragement, just like a less-experienced human.” Simon did manage to give ChatGPT enough courage to build the extension, though!
Despite needing to encourage the thing, this bit is promising:
Here’s the thing I enjoy most about using Code Interpreter for these kinds of prototypes: since the prompts are short, and there’s usually a delay of 30s+ between each prompt while it does its thing, I can do the whole thing on my phone while doing other things.
In this particular case I started out in bed, then got up, fed the dog, made coffee and pottered around the house for a bit—occasionally glancing back at my screen and poking it in a new direction with another prompt.
This almost doesn’t count as a project at all. It began as mild curiosity, and I only started taking it seriously when it became apparent that it was likely to produce a working result.
I only switched to my laptop right at the end, to try out the macOS compilation steps.
Ilia Choly, Semgrep: AutoFixes using LLMs:
Although the built-in autofix feature is powerful, it’s limited to simple AST transforms. I’m currently exploring the idea of fixing semgrep matches using a Large Language Model (LLM). More specifically, each match is individually fed into the LLM and replaced with the response. To make this possible, I’ve created a tool called semgrepx, which can be thought of as xargs for semgrep. I then use semgrepx to rewrite the matches using the fantastic llm tool.
I’ve yet to land a big automated refactoring generated solely by abstract syntax tree-powered refactoring tools. By extension, I definitely haven’t tried marrying AST-based mass refactoring with an LLM. But it sounds neat!
Juniors/seniors and incremental/vision development
The ability to focus on one concern at a time is the mark of a senior developer. It takes experience to ignore other factors as noise. It takes time to learn how to avoid tripping on distractions and side-quests.
Ben Nadel, Only Solve One Problem at a Time:
This lesson hits me hard in the feels because when I reflect on my own work history, some of the biggest mistakes that I’ve made in my career revolve around trying to solve multiple problems at the same time. Perhaps one of the most embarrassing examples of this is when I was attempting to learn OOP (Object Oriented Programming) on a new project. This was two problems: I had to build a new application; and, I tried to do it in a new programming paradigm.
Needless to say, the project ended up coming in months late and was a horrible mess of hard-to-maintain code. Trying to solve two problems at the same time ended in disaster.
Nearly universal advice for developers of all experience levels!
The trick for juniors is, they’re always learning more than one thing at a time, often on accident. They want to build a feature, but it requires a new library, and it requires learning the library. They went to start up a development server, but then something weird happens with Unix. It’s the essential challenge of being a junior – they’re just getting started, so they’re always learning a couple of things at a time.
Perversely, a senior who can see the whole feature/change in their head is sometimes tempted to push the whole thing through in one (large) change. They’re tempted to make the entire thing happen in one outburst of crisp thinking.
Developers who have learned to avoid pitfalls and gotchas sometimes have to relearn how to work incrementally. Juniors (frequently) don’t have this problem. If they don’t work incrementally, they won’t make progress at all! (Caution: juniors that try to work like the seniors they see around them will fall into this trap.)
That said, juniors and seniors both tend to struggle with:
- deciding when to focus vs. when to jump out of a rabbit hole
- building their own feedback loops with tests/compilers, jigs/scaffolding
- imagining and applying constraints
- using first-principle thinking to reduce the overwhelming possibility space of programming
These skills don’t come with simple experience. One has to decide to apply them and then build up experience using them to keep development on-track, focused, and effective.
Trim the attention sails
In America, the 2024 election cycle is unlikely to amuse anyone. Maybe this is a rallying point for “unifying” the country: a near-universal loathing of our politicians, how they get themselves elected, and the outcomes they deliver to us. Let alone the new media that reports on them.
Ahead of the inevitable hell-cycle, I’ve trimmed my attention sails a bit. The general idea is to remove feeds and notifications from my daily routine which are monetized primarily by writing doom-y, grab-y headlines. I’m looking at you in particular, New York Times. But it applies to just about everything with headlines. I’ve disabled all notifications from The Economist and Apple News. I read them once a week. That’s plenty.
Unrelated to the election, I deleted the Twitter and Instagram apps. The web app is mostly equivalent in Twitter’s case, no loss there. Instagram’s mobile web app is surprisingly mediocre. The point, in both cases, is to put a few more steps, a bit more friction, between me and randomly scrolling an algorithmic, attention-hungry feed. I’ve since found that the friction of loading these two as web apps is great. I do indeed look at them far, far less. On the other hand, their web apps are intentionally just-okay. It seems to me that any organization that can put together an excellent iOS app should be able to do the same on mobile web. Reader, let me tell you, they don’t.
I found the settings in Lyft and DoorDash that prevent them from sending advertisements-as-push-notifications. They do exist! Highly recommended.
Mute lists, they’re also fantastic. All the names and teams and keywords that tend to mean “here’s a post about the political horse-race” are scrubbed from my timeline. Even better, I can see when they’re scrubbed and dip in to see if things are as unproductive as I remember. (Thanks for that little detail, Ivory.)
Previously: Think Your Thoughts.
Detroit’s airport (DTW) is…kinda decent? It’s got a monorail and a light show set to songs of Motown. At the very least, it’s not a bad coffee shop? 🙃

Blogs were/are a fun moment
Manuel Moreale, Why I write:
But the reason why I started is long gone at this point. I started the blog as some sort of public accountability tool and it’s now everything but that. I don’t write to be accountable. I probably should.
Manuel asks a lot of folks about why they started writing their blogs. It’s a great question! Some folks want to get weird, others can’t not write and putting it online as good as anything, still others want to connect with a community.
That last one, connecting with a community, is closest to my answer. I started because there was so much excitement, energy, and connection in the early 2000s blogs. It was a real scene. And, plenty of invention! Before there was centralized social media and web 2.0 there was decentralized blogging. An earnest attempt to take the technology of peer-to-peer file sharing and build something besides music sharing on it. It was a fun moment.
Avoid the ternary operator, I’m begging you
Allow me a bit of a soapbox-rant. A spicy take, as we might say these days.
You’re using the ternary operator wrong in Ruby, JavaScript, and almost everything else. It’s for expressions, not control flow.
My personal ternary journey of discovery, delight, and distaste:
- In the old C days: what is this noise? What does a colon even mean in this language? Is this even syntactically valid?
- Later, in verbose languages like Java: oh I get it, let me show off by using it. I like that I can compress five simple lines of conditional down to one.
- Currently, seeing how it’s used in shell and React code: actually this is awful let’s never use this. Delineating the arms of a conditional with one character is awful for scanning and discovery code.
- Even when it’s appropriate, I feel a little bad.
The nuanced take: a one-condition ternary with no more than 4 tokens is maybe okay. If I can’t fit my ternary expression in 80 characters, switch to an if/else conditional. (It’s not that bad!)
// fine, I guess
foo = bar ? baz : quux
// stop this, I'm begging you
msg = bar ? ...dozens of lines of code
: ...dozens more lines of code
Why I try to avoid it:
- in the year 2024, your editor can write conditionals for you
- some folks can’t even keep your ternaries at 10 tokens, let alone 5
- and it’s literally showing
- hence, I’m here writing about it
- the ternary operator is not for control flow, stop that
- the ternary operator is really only suitable for assigning values based on other values
- for example, in the expression
val = foo ? bar : baz
val
depends onfoo
- the ternary operator is a good way to represent dependency/correlation!
- for example, in the expression
- I don’t care what React’s conventions are anymore
- they’re not good in this regard
- use conditionals for control flow
- use variables to assign meaningful names to big chunks of markup
- please, stop with the boolean and ternary logic
- I’m literally writing this before the sun rises, asking you to stop
- the ternary operator is really only suitable for assigning values based on other values
- ternaries don’t airlift/refactor well
- you can’t pluck one bit of code out of a ternary and drop it somewhere else
- I feel this one in my bones but can’t think of a short example
- (citation needed)
Bonus track: stop adding conditional clauses!
// fine
if safe-to-release
launch-the-missiles
else
reset-to-ready
end
// bad, you got some refactoring to do
if safe-to-release && target-acquired && something-that-seemed-right-once && tuesday || national-holiday
...
end
I’m guilty of this temptation to add “just one more conditional!” I regret it.
It makes code difficult to reason about. It’s basically impossible to tell people when the thing will happen in the “bad” example.
If you manage to get something right in multiple conditions today, you’re probably only making it harder for yourself (or someone else) tomorrow.
I will support you 90% of the time if you want to take 30 extra minutes to turn a multi-clause condition into a simpler structure. Your teammates will hail you as a hero later when they need to read or modify said simpler structure!
A disproportionate percentage of bugs hide in conditionals. If they’re easier to read and change, hopefully we’ll write fewer bugs!
Psuedoprose
Taylor Troesh’s pseudoprose is a notation for writing/note-taking/thinking:
How to
- Write in English, Spanish, whatever.
- Grammar is optional.
- Markdown is encouraged.
- Embed in any document with [[…]] brackets.
- Use {…} for comments.
- Use <<…>> for LLM instructions.
- “tk” means “todo”.
Why
- Jot down notes/ideas quickly.
- Focus on semantics over syntax.
- Less text to edit.
- Offload grunt work to LLMS.
Notably, also a notation for annotating LLM/AI/Copilot interactions directly into your text. For the wonks, a GPT-4 prompt is included to convert psuedoprose to well-formed Markdown without any code. What a world.
Other folks’ ways of writing and taking notes are endlessly fascinating.
Rails generators are underrated
Every experienced Rails developer should pick up Garrett Dimon’s Frictionless Generators. Generators are an often overlooked piece of the Rails puzzle. The book shines a light on getting the most out of generators in your Rails projects. It’s an amazing-looking digital object too, the illustrations are great.
(Before I go further, it’s worth noting that Garrett Dimon sent me a review copy, acted on my feedback, and is generally a pal.)
You should customize generators and write your own
Conventions, in the form of assumptions that are woven into the framework’s code but also exist as a contract of sorts, are essential to Rails. Following those conventions would not work well if creating a new model, resource, etc. wasn’t made easy and consistent without our friends rails generate resource/model/etc
. These generators have been present in Rails since the beginning. I’ve used them hundreds of times and thought nothing of it.
A few years ago, I realized that generators had become a public API in Rails and that re-use was encouraged. The guide is a good start. I was able to knock out a simple generator for a novel, but conventional, part of our application. In the process, I realized a couple of things.
No one likes boilerplate and tedium. Generators automate the tedium of boilerplate. This is particularly helpful to less experienced developers, who are likely a bit overwhelmed with trying to comprehend decades of Rails evolution and legacy code (from their perspective) quickly.
Rails developers are under-utilizing this leverage. Every system that makes it past a few thousand lines of code (or several months in use) develops bespoke conventions. These are easier to follow if you can reduce the mental burden to “when you add a new thingy, run rails g thingy
”. Added bonus: starting new conceptual pieces in your app from generators encourages consistency, itself an under-appreciated sustaining element in long-lived Rails applications.
Luckily, someone was thinking the same thing I was…
Garrett knows more about generators than anyone I know
The Rails guides for generators are okay. They whet the curiosity and appetite. But, they aren’t particularly deep. When I first tinkered with generators, I mostly learned by reading the code for rails generate model/resource/etc
.
Frictionless Generators does not require one to jump right into reading code. It opens with ideas on the possibilities of developing with custom generators. Then, it moves onto the practicalities of writing one’s own generator and crafting a good developer experience. From there, it’s down the rabbit hole: learning about the APIs for defining generators, implementing the file-creation logic therein, writing help and documentation for them, generating files from templates, and customizing the built-in Rails generators.
Garrett goes into as much depth on generators as any other technical author I know, on any topic. Did you know you can make HTTP requests and use their responses in generators? I did not, but Garrett does! Did you know that generators apply the same kind of “oh, yeah, that’s common sense” convention for copying files from generators into applications? I did not, but Garrett does! I don’t think I’d use all these ideas on every generator, but I like the idea that I can return to Frictionless Generators should I have an idea and wonder how the existing, low-friction APIs can help me.
Further, Garrett offers frequent insights into the developer experience and leverage of building generators. On building generators for “fingertip feeling” so developers can easily (and frequently!) use them:
I like to aim for no more than one value argument and one collection argument to keep generators easier to use. Everything else becomes an option.
On approaching generators as high-leverage side-quests:
Remember that the ease of use is generally inversely proportional to the length of your documentation. Assistance first. Brevity second. Content third. Or, be helpful first, concise second, and thorough third. That said, there are a few other categories of information that can be helpful.
For me, a good technical book balances presentation of technical information, the right amount of detail, and wisdom on how to apply the two in practical ways. Garrett succeeds at striking that balance while keeping things moving and easy to follow.
In short, recommended! Rails generators are underrated, whether you’re aware of their existence or not. Smart teams are customizing generators and writing their own bespoke generators. There’s a book on this now, which you should check out if any of this resonated.
Collective flow
Dave Rupert, Play at work:
I’ve talked about this before in the context of prototyping and play and how we worked at Paravel. It’s a lot like playing baseball; each member of the team showing up to practice, volleying work (in screenshots, short videos, or demos), pushing changes, communicating thoughts and challenges in the moment outside the confines of slotted meeting times. Me and my coworkers, having a catch.
Several years ago, when I was doing improv, I was rehearsing for a musical, of all things. At the same time we were getting started with table reads and gel’ing as a cast, two other shows were rehearsing in the same theater. One show was about to open, very much having their thing dialed in. Another cast was somewhere in the middle, having figured out what they were about but still trying to get the execution just right. Everywhere in the theatre, there was creation and exploration energy and it was one of the most awesome things I’ve done. This despite not liking musical theater much!
I don’t like the idea of “return to office” and I don’t think you could make it work anyway. The social momentum that kept a critical mass of people in one office has been broken, you can’t put that toothpaste back in the tube.
That said, I have yet to feel that same energy in remote work that I did in a local theatre on rehearsal night while various groups were making something together, in the moment, and iterating on it as quickly as they could share a glance or read through a scene.
I bet some teams have figured out how to feel this way in remote/async setups. But, it feels like most are still running the old in-person playbook that we learned, and sometimes thrived with, over the past years and decades of our careers.
“Yes, and” despite pessimistic engineering intuitions
As engineers, we often face the consequences of shallow ideas embraced exuberantly. Despite those experiences, we should try to solve future problems instead of re-litigating problems-past.
Engineers put too much value on their ability to spot flaws in ideas. It’s only worth something in certain situations.
— Thorsten Ball, 63 Unpopular Opinions
Don’t be edge-case Eddie, wont-scale Walter, legacy code Lonnie, or reasons Reggie. At least try to think around those issues and solve the problem.
This is very much a note to my previous self(s).
Pay attention to intuitive negative emotion…If you’ve been asked for quick estimates a bunch, you might have noticed that sometimes the request triggers negative emotions: fear, anxiety, confusion, etc. You get that sinking feeling in the pit of your stomach. “Oh crap”, you think, “this is not going to be easy.” For me (and most experienced software engineers), there are certain kinds of projects that trigger this feeling. We’re still pattern matching, but now we’re noticing a certain kind of project that resists estimation, or a kind of project that is likely to go poorly.
– Jacob Kaplan-Moss, The art of the SWAG
Jacob recommends noting how intuition and emotion are natural and not entirely negative influences on the process of evaluating ideas. The trick, he says, is to pause and switch to deeply thinking through the idea (or estimate) you’re presented with.
This, again, is very much a note to my previous self(s).
Now, if you’ll excuse me, I need to get back to brainstorming and estimating this time machine, so I can deliver this advice to my former self.