<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>README — careers</title>
<link>https://readme.news/tags/careers/</link>
<atom:link href="https://readme.news/tags/careers/feed.xml" rel="self" type="application/rss+xml"/>
<description>README pieces tagged careers.</description>
<language>en-us</language>
<lastBuildDate>Thu, 01 Oct 2026 13:20:31 +0000</lastBuildDate>
<item><title>What I look for in a codebase in the first hour</title><link>https://readme.news/what-i-look-for-in-a-codebase-in-the-first-hour/</link><guid isPermaLink="true">https://readme.news/what-i-look-for-in-a-codebase-in-the-first-hour/</guid><pubDate>Fri, 24 Jul 2026 09:00:00 +0000</pubDate><description>A checklist for assessing an unfamiliar codebase quickly — for a job, a due diligence, or a project you inherited.</description><content:encoded><![CDATA[<p>You have an hour with an unfamiliar codebase and you need to form a judgment: is this healthy, what will it cost to work in, what is the risk.</p>
<p>Here is the order I go in, and what each thing tells you.</p>
<h2 id="1-can-i-run-it-15-minutes">1. can I run it? (15 minutes)<a class="anchor" href="#1-can-i-run-it-15-minutes" aria-label="link to this section">#</a></h2>
<p>Clone it. Follow the README. Start a timer.</p>
<p>This is the single most informative test and most people skip it in favor of reading code.</p>
<ul><li><strong>Under 10 minutes to a running application:</strong> the team cares about developer experience, and probably about a lot of other things.</li><li><strong>An hour, with several undocumented steps:</strong> onboarding costs a week and every new hire pays it.</li><li><strong>You cannot get it running:</strong> the only people who can work on this are the ones who already have it working. This is a serious risk and it is invisible from the outside.</li></ul>
<p>Note every step that failed. That list <em>is</em> the health assessment.</p>
<h2 id="2-the-test-suite-10-minutes">2. the test suite (10 minutes)<a class="anchor" href="#2-the-test-suite-10-minutes" aria-label="link to this section">#</a></h2>
<p>Run it. Then look at it.</p>
<p><strong>Does it pass?</strong> On a clean checkout, first try. If not, that tells you the team has normalized a red build.</p>
<p><strong>How long?</strong> Under two minutes is excellent. Over ten and people have stopped running it locally.</p>
<p><strong>What is the ratio of assertions to setup?</strong> Read three test files. If setup dominates, the code is heavily coupled.</p>
<p><strong>Are there tests for the error paths?</strong> Almost nobody writes these and their presence is a strong positive signal.</p>
<p><strong>Is there a <code>skip</code> or <code>xfail</code> graveyard?</strong> Count them. A pile of disabled tests means the suite has been losing a slow argument with reality.</p>
<h2 id="3-the-shape-of-the-repository-5-minutes">3. the shape of the repository (5 minutes)<a class="anchor" href="#3-the-shape-of-the-repository-5-minutes" aria-label="link to this section">#</a></h2>
<div class="code"><span class="code-lang">bash</span><pre><code class="lang-bash">tokei .            # lines by language
git log --oneline | wc -l
git log --format='%an' | sort | uniq -c | sort -rn | head</code></pre></div>
<p><strong>Contributor concentration.</strong> If one person wrote 80% of it and they left, that is the largest risk in the codebase, larger than anything technical.</p>
<p><strong>Language sprawl.</strong> Four languages in a small project usually means four sets of tooling and nobody who understands all of it.</p>
<p><strong>Directory structure.</strong> Does it reflect the domain or the framework? <code>models/</code>, <code>views/</code>, <code>controllers/</code> tells you nothing about what the software does. <code>billing/</code>, <code>inventory/</code>, <code>shipping/</code> tells you everything.</p>
<h2 id="4-the-largest-files-5-minutes">4. the largest files (5 minutes)<a class="anchor" href="#4-the-largest-files-5-minutes" aria-label="link to this section">#</a></h2>
<div class="code"><span class="code-lang">bash</span><pre><code class="lang-bash">find . -name '*.py' -not -path '*/.venv/*' | xargs wc -l | sort -rn | head -20</code></pre></div>
<p>Every codebase has a few enormous files. Open the biggest one.</p>
<ul><li><strong>Is it generated?</strong> Fine, ignore it.</li><li><strong>Is it a god object?</strong> A 4,000-line service class is where all the complexity accumulated and where all the bugs live.</li><li><strong>When was it last changed?</strong> <code>git log -1</code> on it. If it is huge and changes weekly, that is the hot spot, and any work you do will touch it.</li></ul>
<h2 id="5-dependencies-5-minutes">5. dependencies (5 minutes)<a class="anchor" href="#5-dependencies-5-minutes" aria-label="link to this section">#</a></h2>
<p><strong>How many?</strong> Compare against similar projects. An unusual number in either direction is worth understanding.</p>
<p><strong>How old?</strong> Anything more than two major versions behind is an upgrade project waiting for you.</p>
<p><strong>Anything abandoned?</strong> Check the largest ones for last release date. A critical dependency with no release in three years is a fork you have not made yet.</p>
<p><strong>Anything surprising?</strong> A cryptography library nobody has heard of. A vendored copy of something. A dependency on a specific fork.</p>
<h2 id="6-the-commit-history-10-minutes">6. the commit history (10 minutes)<a class="anchor" href="#6-the-commit-history-10-minutes" aria-label="link to this section">#</a></h2>
<div class="code"><span class="code-lang">bash</span><pre><code class="lang-bash">git log --oneline -50</code></pre></div>
<p><strong>Message quality.</strong> "fix", "wip", "asdf" versus real descriptions. This is a direct readout of the engineering culture and it is remarkably predictive.</p>
<p><strong>Commit size.</strong> Are they atomic, or is every commit a 3,000-line dump?</p>
<p><strong>Is there review?</strong> Merge commits from pull requests, or direct pushes to the main branch?</p>
<p><strong>Cadence.</strong> Steady, or bursts separated by silence?</p>
<h2 id="7-the-things-that-are-missing-5-minutes">7. the things that are missing (5 minutes)<a class="anchor" href="#7-the-things-that-are-missing-5-minutes" aria-label="link to this section">#</a></h2>
<p>Frequently the most informative part.</p>
<ul><li><strong>No CI configuration.</strong> Nothing is checked automatically.</li><li><strong>No linter or formatter config.</strong> Every file is a different style and every review argues about it.</li><li><strong>No <code>CONTRIBUTING.md</code> or equivalent</strong> on a project with multiple contributors.</li><li><strong>No <a class="xref" href="/the-unreasonable-effectiveness-of-a-changelog/" title="The unreasonable effectiveness of a changelog">changelog</a>.</strong> Nobody knows what changed between versions.</li><li><strong>No architecture documentation of any kind.</strong> The system exists only in people's heads.</li><li><strong>No <code>.env.example</code>.</strong> You cannot configure it without asking someone.</li></ul>
<h2 id="8-one-real-feature-end-to-end-10-minutes">8. one real feature, end to end (10 minutes)<a class="anchor" href="#8-one-real-feature-end-to-end-10-minutes" aria-label="link to this section">#</a></h2>
<p>Pick a user-visible feature and trace it from the entry point to the database.</p>
<p>This is the highest-value ten minutes. You learn: how many layers, how much indirection, where the business logic lives, whether the abstractions are consistent, and whether you could add a similar feature without asking anyone.</p>
<p>If you cannot follow it in ten minutes, neither can anyone else, and every change will be expensive.</p>
<h2 id="the-summary-judgment">the summary judgment<a class="anchor" href="#the-summary-judgment" aria-label="link to this section">#</a></h2>
<p>After an hour I can usually say:</p>
<ul><li><strong>How long until a new engineer is productive.</strong> (From step 1 and 8.)</li><li><strong>Whether changes are safe.</strong> (From step 2.)</li><li><strong>Where the risk is concentrated.</strong> (From steps 3 and 4.)</li><li><strong>What the team values.</strong> (From steps 6 and 7.)</li></ul>
<p>None of that requires understanding what the software does. It is all structural, and structure is what determines the cost of working in something.</p>]]></content:encoded></item><item><title>The onboarding document that actually works</title><link>https://readme.news/the-onboarding-document-that-actually-works/</link><guid isPermaLink="true">https://readme.news/the-onboarding-document-that-actually-works/</guid><pubDate>Mon, 13 Jul 2026 09:00:00 +0000</pubDate><description>Most onboarding docs are written by people who already know. Here is what a new engineer needs on day one, in order.</description><content:encoded><![CDATA[<p>Onboarding documentation is written by someone who already knows the system, which means it is written from the wrong side of the knowledge gap.</p>
<p>The result is consistently: an architecture overview that is meaningless without context, a list of tools with no explanation of why, and no answer to any question a new person actually has.</p>
<h2 id="what-a-new-engineer-actually-needs-in-order">what a new engineer actually needs, in order<a class="anchor" href="#what-a-new-engineer-actually-needs-in-order" aria-label="link to this section">#</a></h2>
<p><strong>Day one: get something running.</strong></p>
<p>Not understanding. Running. A new engineer who has the application running locally on day one is in a completely different position from one who is still fighting a dependency on day three.</p>
<p>This section should be a numbered list of commands that work. Tested. On a clean machine. Recently.</p>
<div class="code"><span class="code-lang">markdown</span><pre><code class="lang-markdown">## get it running

1. Install prerequisites:  `brew bundle`   (or the equivalent — see below)
2. Copy the environment:   `cp .env.example .env`
3. Get secrets:            `./scripts/fetch-dev-secrets` (needs VPN)
4. Start dependencies:     `docker compose up -d`
5. Migrate:                `./scripts/db-reset`
6. Run:                    `pnpm dev`

You should see the app at http://localhost:5173 with seeded data.
Log in with dev@example.com / password.

If step 3 fails with "unauthorized", you need to be added to the
dev-secrets group — ask in #eng-onboarding.</code></pre></div>
<p>That last paragraph — the anticipated failure with its resolution — is the part that separates a document that works from one that does not. Every step that has ever failed for anyone should have a note.</p>
<p><strong>Day two: make a change and see it.</strong></p>
<p>A guided first change. Something trivial and real: change a label, add a field, fix a typo in a template. All the way through: edit, test, review, merge, deploy.</p>
<p>The point is not the change. It is that they have now executed the entire delivery pipeline once, so every subsequent change is a variation on something they have done.</p>
<p><strong>Day three to five: the map.</strong></p>
<p><em>Now</em> the architecture overview, and now it means something, because they have seen the system run.</p>
<p>Keep it to a page. What are the major pieces, what does each do, how do they talk. A diagram. Where the code for each piece lives.</p>
<p>Not a complete description. A map, at the resolution of "which building do I go to."</p>
<p><strong>Week two: the why.</strong></p>
<p>The decisions that are not obvious from the code. Why the database is structured that way. Why there is a queue between those two services. Why that module is frozen. Why the obvious approach to X does not work.</p>
<p>This is the highest-value and least-written documentation in any organization, because it exists only in the heads of people who were there. When they leave, it is gone, and the next person spends a year rediscovering it — usually by proposing the obvious approach and being told no.</p>
<h2 id="the-sections-everyone-forgets">the sections everyone forgets<a class="anchor" href="#the-sections-everyone-forgets" aria-label="link to this section">#</a></h2>
<p><strong>The glossary.</strong> Every organization has jargon: internal product names, acronyms, words used with a specific local meaning. A new person hears twenty of these in their first week and cannot ask about all of them without feeling stupid.</p>
<p>Write them down. This is a thirty-minute task with an outsized payoff.</p>
<p><strong>Who to ask about what.</strong> Not the org chart. "Payments: ask Priya. Deploy pipeline: #platform-help. Anything about the legacy importer: Marcus, and be warned it is complicated."</p>
<p><strong>The things that will surprise you.</strong> The test suite that fails on the first run until you seed a fixture. The service that takes four minutes to start. The one flaky test everyone knows about. The staging environment that resets on Sundays.</p>
<p>Every codebase has these. Writing them down converts "this is broken and I do not want to admit I cannot fix it" into "oh, that is expected."</p>
<p><strong>What not to touch.</strong> Frozen modules, generated files, anything requiring a specific review.</p>
<h2 id="the-maintenance-mechanism">the maintenance mechanism<a class="anchor" href="#the-maintenance-mechanism" aria-label="link to this section">#</a></h2>
<p>Onboarding docs rot faster than any other documentation, because the people who would notice the errors are the ones who no longer read it.</p>
<p><strong>The fix: the last person onboarded owns it.</strong></p>
<p>Every new engineer's first task is to follow the document, fix everything that was wrong, and add the things they had to ask about. Then they own it until the next person arrives.</p>
<p>This works because their frustration is fresh and their perspective is exactly the target reader's. It is the only mechanism I have seen that keeps these documents accurate.</p>
<h2 id="the-test">the test<a class="anchor" href="#the-test" aria-label="link to this section">#</a></h2>
<p>Hand it to a new engineer and do not help them.</p>
<p>Time how long until they have the application running. Note every question they had to ask. Each question is a gap, with a measured cost.</p>
<p>Then fix them, and repeat with the next person.</p>
<p>Most teams have never done this and would be surprised by the result.</p>]]></content:encoded></item><item><title>What a staff engineer does all day</title><link>https://readme.news/what-a-staff-engineer-does-all-day/</link><guid isPermaLink="true">https://readme.news/what-a-staff-engineer-does-all-day/</guid><pubDate>Fri, 19 Jun 2026 09:00:00 +0000</pubDate><description>The role is genuinely ambiguous and that ambiguity is load-bearing. An attempt at a concrete description.</description><content:encoded><![CDATA[<p>"Staff engineer" is the most poorly-defined common title in the industry. It means different things at different companies, and even within one company two staff engineers may do almost nothing in common.</p>
<p>Here is an attempt at what the role actually is, based on watching people do it well.</p>
<h2 id="what-it-is-not">what it is not<a class="anchor" href="#what-it-is-not" aria-label="link to this section">#</a></h2>
<p><strong>Not "a senior engineer who has been there longer."</strong> Time in seat produces a senior engineer with more context, which is valuable and is not this.</p>
<p><strong>Not "the best coder."</strong> The highest-output individual contributor is a valuable role and it is a different one. Staff engineers frequently write less code than seniors.</p>
<p><strong>Not "a manager who did not want to manage."</strong> The scope is comparable to a manager's; the mechanism is entirely different.</p>
<h2 id="what-it-is">what it is<a class="anchor" href="#what-it-is" aria-label="link to this section">#</a></h2>
<p>The concise version: <strong>a staff engineer is responsible for the technical success of work that spans more than one team, without having authority over those teams.</strong></p>
<p>Everything distinctive about the role follows from "without authority." You cannot assign work. You cannot approve headcount. You cannot make a decision stick by deciding it. Every outcome has to be achieved through information, credibility, and persuasion.</p>
<h2 id="the-actual-activities">the actual activities<a class="anchor" href="#the-actual-activities" aria-label="link to this section">#</a></h2>
<p><strong>Finding the problem nobody owns.</strong> The most common form of staff-level impact. Every organization has problems that fall between teams: the shared library nobody maintains, the integration that fails and each side thinks is the other's, the performance issue that is caused by the interaction of three services.</p>
<p>Nobody owns these, so nobody fixes them, so they persist for years. Identifying one, proving it matters, and getting it fixed is a substantial contribution and it usually requires a person who is not on any of the teams involved.</p>
<p><strong>Making a decision that spans teams.</strong> Which of three approaches, when each team has a preference and none of them can see the whole picture. This is where the "no authority" constraint bites hardest: the decision has to be made in a way that the people affected accept, which means the reasoning has to be visible and the objections have to be genuinely addressed.</p>
<p><strong>Writing the document that ends the argument.</strong> A recurring disagreement that resurfaces every quarter because nobody wrote down the resolution. One good document — with the options, the trade-offs, the decision, and the reasoning — can end a multi-year debate.</p>
<p><strong>Being the person who read the whole system.</strong> Most engineers know their team's code. Somebody needs to know how it all fits together, including the parts nobody has touched in three years. That knowledge is what makes the cross-cutting problems visible.</p>
<p><strong>Raising the floor.</strong> Not by writing better code. By making the good pattern easy: a library that removes a class of bug, a template that encodes the right defaults, a lint rule that prevents the mistake, documentation that means nobody has to ask. Impact through leverage rather than output.</p>
<p><strong>Mentoring, specifically on judgment.</strong> Not "how do I use this API." "Should we build this at all," "how do I disagree with my manager about a technical decision," "how do I tell if this design will be a problem in a year."</p>
<p><strong>Saying no with a reason, at a level where it lands.</strong> Frequently the most valuable thing a staff engineer does, and the reason it requires seniority is that the no has to come with an alternative and with credibility behind it.</p>
<h2 id="the-day-concretely">the day, concretely<a class="anchor" href="#the-day-concretely" aria-label="link to this section">#</a></h2>
<p>A real week looks roughly like:</p>
<ul><li>20% writing code, usually the hard or risky part of something, or a prototype that settles an argument.</li><li>25% writing documents — designs, decisions, analyses, postmortems.</li><li>25% in conversations — reviews, one-on-ones, arguing about designs, being asked "does this seem right to you."</li><li>15% reading — code, incident reports, other people's designs, the thing everyone is complaining about.</li><li>15% on whatever is currently on fire.</li></ul>
<p>The proportion of coding is the part that surprises people moving into the role, and the discomfort of not shipping visible code is the most common reason people bounce out of it.</p>
<h2 id="how-to-tell-if-someone-is-good-at-it">how to tell if someone is good at it<a class="anchor" href="#how-to-tell-if-someone-is-good-at-it" aria-label="link to this section">#</a></h2>
<p><strong>Do things get decided?</strong> Not "do they have opinions." Do arguments they are involved in reach a resolution that holds.</p>
<p><strong>Do other engineers get better?</strong> Look at the people around them over a year.</p>
<p><strong>Do they work on things nobody asked them to?</strong> The highest-value staff work is usually self-directed, because if it were obvious and assigned it would already have an owner.</p>
<p><strong>Are they trusted by people who disagree with them?</strong> This is the real test. Someone who is only trusted by people who already agree has influence, not credibility.</p>
<h2 id="the-failure-modes">the failure modes<a class="anchor" href="#the-failure-modes" aria-label="link to this section">#</a></h2>
<p><strong>Becoming an architecture astronaut.</strong> Designs, diagrams, opinions, no contact with running code. The credibility runs out within about a year, and it is very hard to get back.</p>
<p><strong>Becoming a very expensive senior engineer.</strong> Doing excellent work with single-team scope. Comfortable, valuable, and not the job.</p>
<p><strong>Spreading too thin.</strong> Involved in twelve things, effective in none. The scope is tempting and the constraint is real: two or three significant efforts at a time is the realistic maximum.</p>
<p><strong>Losing the ability to build.</strong> The role requires enough hands-on work to stay credible and calibrated. An engineer who has not shipped in a year is guessing.</p>]]></content:encoded></item><item><title>Hiring juniors in 2026</title><link>https://readme.news/hiring-juniors-in-2026/</link><guid isPermaLink="true">https://readme.news/hiring-juniors-in-2026/</guid><pubDate>Thu, 30 Apr 2026 09:00:00 +0000</pubDate><description>The entry-level pipeline is breaking in a way that will be expensive in five years. Some of the fixes are cheap.</description><content:encoded><![CDATA[<p>Entry-level software hiring has contracted sharply. The reasons are partly cyclical and partly a genuine belief among hiring managers that AI tooling has reduced the need for junior engineers.</p>
<p>The first part will recover. The second part is a mistake, and it is the kind of mistake that is invisible for four years and then extremely expensive.</p>
<h2 id="the-argument-for-not-hiring-juniors">the argument for not hiring juniors<a class="anchor" href="#the-argument-for-not-hiring-juniors" aria-label="link to this section">#</a></h2>
<p>Stated honestly, because it is not stupid:</p>
<p>A junior engineer's first-year output is mostly small, well-specified tasks — the CRUD endpoint, the test coverage, the bug in a file someone pointed them at. That work is now substantially automatable. Meanwhile the junior requires mentoring time from senior engineers, which is the scarcest resource.</p>
<p>So the ROI on a junior looks worse than it did. That reasoning is coherent.</p>
<h2 id="why-it-is-wrong">why it is wrong<a class="anchor" href="#why-it-is-wrong" aria-label="link to this section">#</a></h2>
<p><strong>Seniors come from juniors.</strong> There is no other supply. An organization that hires only seniors is free-riding on other organizations' training, and if everyone does it, the pipeline empties. This is a classic collective action failure and the industry is walking into it with open eyes.</p>
<p><strong>The judgment that makes seniors valuable comes from doing the work.</strong> The ability to look at plausible code and know it is wrong comes from having written the wrong version and debugged it at 3 a.m. You cannot read your way to it and you cannot prompt your way to it.</p>
<p>If the apprenticeship stops, the next generation of senior engineers does not exist, and the current one retires.</p>
<p><strong>Juniors are better at the new tools.</strong> Consistently, in my experience. They have no prior workflow to defend and they explore. A team of only senior engineers adopts new tooling slowly and grudgingly.</p>
<p><strong>Mentoring makes seniors better.</strong> The engineer who has to explain why a design is wrong understands it better afterward. Teams with no juniors lose that forcing function and get sloppier about articulating their own reasoning.</p>
<h2 id="what-actually-has-to-change">what actually has to change<a class="anchor" href="#what-actually-has-to-change" aria-label="link to this section">#</a></h2>
<p>The old model — hire a junior, give them small tickets for a year, gradually increase scope — does not work as well when the small tickets are automated. The model has to change, not the hiring.</p>
<p><strong>Start them on reading, not writing.</strong> Give a new engineer a real system and a week to understand and explain it. Have them write the architecture document that does not exist. This builds the skill that actually matters now and it produces something useful.</p>
<p><strong>Give them debugging, not features.</strong> Debugging is the skill that generalizes, that AI is least reliable at, and that cannot be learned from a course. Pair them on incidents. Give them the flaky test nobody wants.</p>
<p><strong>Make them review agent output.</strong> Reviewing machine-generated code with a senior engineer walking through what is wrong with it is an extraordinarily efficient teaching mechanism. You get a stream of plausible-but-flawed code, which is exactly the training material you want and which used to be expensive to produce.</p>
<p><strong>Require them to write the tests first.</strong> Specifying behavior before implementing teaches design, and it is the part of the workflow that has become more important rather than less.</p>
<p><strong>Do not let them delegate the hard part.</strong> For the first year, some things get done by hand, deliberately, because the point is the learning rather than the output. Say this out loud so it does not feel like an arbitrary restriction.</p>
<h2 id="the-hiring-signal-that-works-now">the hiring signal that works now<a class="anchor" href="#the-hiring-signal-that-works-now" aria-label="link to this section">#</a></h2>
<p>Traditional junior screens — implement this algorithm, complete this take-home — are substantially defeated and were never good predictors anyway.</p>
<p>What works better:</p>
<p><strong>A code review exercise.</strong> Give them a pull request with three problems. Watch what they find and how they talk about it. This is the job.</p>
<p><strong>A debugging exercise on a real repository.</strong> Failing test, thirty minutes, any tools they want including AI. Watch the process, not the outcome. Do they read the error? Form a hypothesis? Check it? Notice when the model's suggestion is wrong?</p>
<p><strong>A conversation about something they built.</strong> Follow-up questions until you hit the edge of their understanding. Where that edge sits, and how they handle reaching it, tells you almost everything.</p>
<h2 id="the-case-to-make-internally">the case to make internally<a class="anchor" href="#the-case-to-make-internally" aria-label="link to this section">#</a></h2>
<p>If you are arguing for junior headcount:</p>
<p>The cost of a junior is roughly a senior's partial attention for a year plus a below-market salary. The cost of a senior hire in three years, in a market where nobody trained anyone, is going to be considerably higher than it is now.</p>
<p>Every organization that stopped training in 2009 spent 2013 through 2016 paying enormous premiums for the engineers who had been trained elsewhere. It is the same trade and it is being made again.</p>
<p>The organizations that keep training through this period will have a meaningful advantage in five years, and it will be very hard to catch up to them quickly.</p>]]></content:encoded></item><item><title>Reading code is a skill and nobody teaches it</title><link>https://readme.news/reading-code-is-a-skill-and-nobody-teaches-it/</link><guid isPermaLink="true">https://readme.news/reading-code-is-a-skill-and-nobody-teaches-it/</guid><pubDate>Tue, 13 Jan 2026 09:00:00 +0000</pubDate><description>We spend years learning to write and approximately zero hours learning to read. Then we spend our careers reading.</description><content:encoded><![CDATA[<p>Every programming course teaches you to write code. Not one of them teaches you to read it.</p>
<p>Then you get a job and spend, conservatively, eighty percent of your time reading: reading the existing system before you change it, reading a pull request, reading a library's source because the docs are wrong, reading a stack trace, reading a diff a machine produced.</p>
<p>The skill you were never taught is the one you use most. And it is a skill — it is learnable, it has technique, and people are dramatically better or worse at it in ways that have little to do with how well they write.</p>
<h2 id="what-good-readers-actually-do">what good readers actually do<a class="anchor" href="#what-good-readers-actually-do" aria-label="link to this section">#</a></h2>
<p>I have watched a lot of people read unfamiliar code. The good ones have a method.</p>
<p><strong>They find the entry points first.</strong> Not the top of the file. The place where control enters the system: <code>main</code>, the route handlers, the message consumers, the event listeners. Everything else is reachable from there and unreachable code is noise.</p>
<p><strong>They read for shape before detail.</strong> A first pass that answers: how many layers? Where is the state? What talks to what? They will read a hundred files shallowly before reading one deeply, and they resist the urge to understand any single function completely on the first pass.</p>
<p><strong>They follow the data, not the calls.</strong> Where does this value come from, where does it go, who mutates it. Call graphs tell you the structure; data flow tells you the behavior, and bugs live in behavior.</p>
<p><strong>They run it.</strong> Reading static text is a bad way to understand a dynamic system. Set a breakpoint, add a print, run the test with a debugger attached. Five minutes of watching it execute beats an hour of reading.</p>
<p><strong>They read the tests first</strong>, when the tests are good. Tests are the spec written in a language the machine checks. A well-tested module's test file is the best available documentation of what it is supposed to do.</p>
<p><strong>They read the history.</strong> <code>git log -S</code> for the function name. When was this added, what was the commit message, what else changed with it. The rationale for a weird piece of code is frequently in a commit from 2019, and nobody looks.</p>
<p><strong>They accept partial understanding.</strong> The bad habit is trying to understand everything before touching anything. You cannot. Understand enough to make the change safely, make it, and let the tests and the review catch what you missed.</p>
<h2 id="the-techniques-worth-practicing-deliberately">the techniques worth practicing deliberately<a class="anchor" href="#the-techniques-worth-practicing-deliberately" aria-label="link to this section">#</a></h2>
<p><strong>Read a library you depend on.</strong> Pick something in your stack, one you use daily and have never opened. Read its source for an hour. You will learn more about your language's idioms than from any tutorial, and you will find at least one thing that changes how you use it.</p>
<p><strong>Explain it to someone.</strong> The fastest way to discover you did not understand something is to try to say it out loud. This is why rubber-duck debugging works and it works just as well for comprehension as for debugging.</p>
<p><strong>Reconstruct the design decision.</strong> For any piece of code that looks strange, ask: what problem would make this the right answer? Usually there was one. Code that looks stupid is either a workaround for something you cannot see, or a fossil of a requirement that no longer exists. Both are worth knowing.</p>
<p><strong>Diff two versions of something.</strong> Reading the evolution of a file teaches you what the author learned. It is a much richer signal than the current state.</p>
<h2 id="why-this-matters-more-now">why this matters more now<a class="anchor" href="#why-this-matters-more-now" aria-label="link to this section">#</a></h2>
<p>Because reading is now a much larger fraction of the job.</p>
<p>If a machine writes a substantial share of the code that lands in your repository, then your value-add is on the reading side of the transaction. The person who can read a 400-line diff and spot the one place that breaks under concurrency is worth enormously more than the person who can produce 400 lines.</p>
<p>And it compounds badly in the other direction: someone who never developed reading skill, in an environment where they write less code than any previous generation, will develop neither.</p>
<h2 id="the-thing-i-would-change-about-how-we-teach">the thing I would change about how we teach<a class="anchor" href="#the-thing-i-would-change-about-how-we-teach" aria-label="link to this section">#</a></h2>
<p>Give students a real codebase and a bug report before you give them a blank file.</p>
<p>Have them find it. Have them explain what the system does. Have them make a one-line fix and defend why it is correct.</p>
<p>That is the actual job. We spend four years preparing people for the part of it that machines now do well, and zero hours on the part that they do not.</p>]]></content:encoded></item><item><title>The technical interview is measuring the wrong thing, again</title><link>https://readme.news/the-technical-interview-is-measuring-the-wrong-thing-again/</link><guid isPermaLink="true">https://readme.news/the-technical-interview-is-measuring-the-wrong-thing-again/</guid><pubDate>Fri, 28 Nov 2025 09:00:00 +0000</pubDate><description>Every hiring process eventually optimizes for the wrong signal. The current one has a new failure mode.</description><content:encoded><![CDATA[<p>The technical interview has been broken in a rotating set of ways for twenty years. Each fix creates the next problem.</p>
<ul><li><strong>Brainteasers</strong> measured whether you had heard the brainteaser. Replaced by algorithms.</li><li><strong>Algorithm puzzles</strong> measured whether you had ground a puzzle site. Replaced, partially, by take-homes.</li><li><strong>Take-homes</strong> measured how much unpaid time you had, which selects against people with children and second jobs. Replaced, partially, by pairing.</li><li><strong>Pairing</strong> is the best of them and it measures your comfort being watched, which is correlated with experience and confidence, which is correlated with demographics.</li></ul>
<p>Now there is a new one, and it is genuinely novel.</p>
<h2 id="the-current-problem">the current problem<a class="anchor" href="#the-current-problem" aria-label="link to this section">#</a></h2>
<p>A candidate with a model available can pass most remote technical screens. Not "can cheat" — <em>can pass</em>, because the tasks we set are exactly the tasks these tools are good at.</p>
<p>The industry response has been mostly bad. Return-to-office for interviews. Proctoring software. Increasingly hostile monitoring. All of it makes the experience worse for honest candidates and is defeated by anyone determined.</p>
<p>The response has been bad because the question was framed wrong. The question is not "how do we stop candidates using AI." It is "what are we actually trying to measure, given that the job now includes using these tools."</p>
<h2 id="what-the-job-actually-is">what the job actually is<a class="anchor" href="#what-the-job-actually-is" aria-label="link to this section">#</a></h2>
<p>If you hired someone today, their work would involve:</p>
<ul><li>Understanding an existing system well enough to change it safely.</li><li>Deciding what to build, which is mostly deciding what not to build.</li><li>Using AI tools effectively, including knowing when the output is wrong.</li><li>Communicating a technical decision to people who will be affected by it.</li><li>Debugging something under time pressure with incomplete information.</li><li>Reviewing someone else's code — increasingly, a machine's — and catching the problem.</li></ul>
<p>Not one of those is measured by "implement an LRU cache in forty-five minutes."</p>
<h2 id="interviews-that-measure-the-real-thing">interviews that measure the real thing<a class="anchor" href="#interviews-that-measure-the-real-thing" aria-label="link to this section">#</a></h2>
<p><strong>Code review.</strong> Give them a 300-line pull request with three deliberate problems: one obvious bug, one subtle design issue, one thing that is fine but looks wrong. Ask them to review it.</p>
<p>This is excellent. It is exactly the job, AI does not obviously help, and the conversation about the third item — where they explain why the suspicious thing is actually correct — tells you more about their judgment than any implementation task.</p>
<p><strong>Debugging a real system.</strong> Give them a repository, a failing test, and thirty minutes. Let them use whatever tools they want, including models. Watch how they narrow it down. Do they read the error? Do they form a hypothesis? Do they check it? Do they notice when the model's suggestion is wrong?</p>
<p>Watching someone debug with AI assistance is a much better signal than watching them code without it, because it is the actual work.</p>
<p><strong>Design discussion on their own past work.</strong> "Tell me about a system you built. What would you change?" The follow-up questions are where the signal is. People who genuinely understood their system can answer six levels deep. People who did not, cannot, and it becomes clear quickly.</p>
<p><strong>A short, paid, scoped project.</strong> Four hours, paid at a real rate, on something close to the actual work. This is the highest-signal option and the least scalable, and it is worth it for senior roles.</p>
<h2 id="what-to-stop-doing">what to stop doing<a class="anchor" href="#what-to-stop-doing" aria-label="link to this section">#</a></h2>
<p><strong>Stop asking people to implement data structures from memory.</strong> They will not do this in the job, and if they need one they will look it up, correctly.</p>
<p><strong>Stop the six-round loop.</strong> Every round is a coin flip with a false-negative rate. Six rounds does not make the signal six times better; it makes the process long enough that good candidates take another offer.</p>
<p><strong>Stop pretending the whiteboard measures anything but whiteboard performance.</strong></p>
<h2 id="the-thing-nobody-wants-to-hear">the thing nobody wants to hear<a class="anchor" href="#the-thing-nobody-wants-to-hear" aria-label="link to this section">#</a></h2>
<p>Interviews have a low ceiling on signal. The correlation between interview performance and job performance is weak in every study anyone has run.</p>
<p>The highest-signal thing is working with someone. Everything else is a proxy. Which argues for: shorter processes, more willingness to take a chance, and robust ways to correct the mistake — a real probation practice, honest early feedback, and the organizational nerve to act on it.</p>
<p>That is a harder cultural change than redesigning the interview loop, which is why everyone redesigns the interview loop instead.</p>]]></content:encoded></item><item><title>Shopify's memo and the new hiring question</title><link>https://readme.news/shopifys-memo-and-the-new-hiring-question/</link><guid isPermaLink="true">https://readme.news/shopifys-memo-and-the-new-hiring-question/</guid><pubDate>Fri, 25 Apr 2025 09:00:00 +0000</pubDate><description>&quot;Prove AI can&#x27;t do this job&quot; as a requirement before headcount. A reasonable policy with an unreasonable failure mode.</description><content:encoded><![CDATA[<p>Tobi Lütke published an internal memo this month stating that Shopify teams must demonstrate why AI cannot do a job before requesting headcount, and that "reflexive AI usage" is now a baseline expectation in performance reviews.</p>
<p>The memo is better written and more reasonable than the headlines about it. It is also going to be misapplied everywhere it gets copied, and it is going to get copied everywhere.</p>
<h2 id="the-defensible-core">the defensible core<a class="anchor" href="#the-defensible-core" aria-label="link to this section">#</a></h2>
<p>Two claims in the memo are correct.</p>
<p><strong>"Try the AI first" is good engineering hygiene.</strong> Before you build the internal tool, before you write the script, before you file the ticket — spend ten minutes seeing whether an existing model handles it. Often it does. The cost of checking is near zero and the expected value is high.</p>
<p><strong>Stagnation is a choice.</strong> A team that has not changed how it works in two years during a period of rapid tooling change is not being careful, it is being incurious. That is a fair thing to name.</p>
<h2 id="the-failure-mode">the failure mode<a class="anchor" href="#the-failure-mode" aria-label="link to this section">#</a></h2>
<p>"Prove AI cannot do it" is an unfalsifiable standard, and unfalsifiable standards in an organization become political tools.</p>
<p>You cannot prove a negative about a capability that changes monthly. Any manager who wants to deny headcount now has an infinitely flexible reason, and any manager who wants to grant it will produce a document explaining why AI cannot do it. The document is not evidence. It is theater. Every organization that has ever required a justification memo for headcount has produced a genre of justification-memo prose, and this is just the newest style.</p>
<p>The real question — "what is the highest-leverage use of an additional engineer" — was always the question. Adding an AI framing does not make it easier to answer, it makes it easier to obscure.</p>
<h2 id="the-second-order-effect-nobody-plans-for">the second-order effect nobody plans for<a class="anchor" href="#the-second-order-effect-nobody-plans-for" aria-label="link to this section">#</a></h2>
<p>If teams are evaluated on AI usage, teams will use AI, including in places where it is worse. This is Goodhart's law with a new coat of paint. You will get:</p>
<ul><li><a class="xref" href="/code-review-comments-that-change-things/" title="Code review comments that change things">Code review comments</a> generated by a model that read fine and check nothing.</li><li>Documentation nobody reads, generated because generating it is cheap.</li><li>Test suites with impressive coverage numbers and no assertions that would fail.</li><li>Postmortems written by a model that faithfully summarize the incident and identify no real cause.</li></ul>
<p>All of that is measurable AI adoption. None of it is value.</p>
<h2 id="what-a-better-version-looks-like">what a better version looks like<a class="anchor" href="#what-a-better-version-looks-like" aria-label="link to this section">#</a></h2>
<p>If you want the outcome the memo is aiming at, ask for the outcome directly:</p>
<ul><li><strong>Cycle time</strong>, not tool adoption. If the team ships faster with the same quality, they are using their tools well, and it does not matter which ones.</li><li><strong>Toil reduction as a named goal</strong>, with a quarterly review of what got automated. That surfaces the same opportunities without the unfalsifiable test.</li><li><strong>A budget and permission, not a mandate.</strong> The blocker in most organizations is not enthusiasm, it is that the good tools are not approved and the data policy is unclear. Fix that and adoption happens without a memo.</li></ul>
<h2 id="the-part-i-actually-agree-with">the part I actually agree with<a class="anchor" href="#the-part-i-actually-agree-with" aria-label="link to this section">#</a></h2>
<p>The memo says learning to use these tools well is now part of the job. That is true and it is not controversial in the way people are treating it.</p>
<p>Getting good output from a model is a skill — knowing what context to provide, how to decompose a task, when the answer is wrong in a way that looks right. It is closer to being a good technical lead than to typing a search query. People who have developed it are meaningfully more effective, and people who dismissed the whole category in 2023 and never revisited it are falling behind in a way that is going to be uncomfortable to talk about at review time.</p>
<p>That is worth saying out loud. It just does not require a headcount policy.</p>]]></content:encoded></item>
</channel>
</rss>
