There is a sentence I have held back for a long time, because on the surface it sounds like the kind of thing a person says when they want to feel taller than the people around them, and that is not what it means and not who it should be aimed at. "You're a developer, act like it" is something we say to ourselves first, usually on the day when the convenient option and the responsible option point in different directions, and it is worth saying out loud because the responsibility it refers to is real whether or not anyone stops to name it. Nobody is born with this obligation, and nobody formally hands it to you on your first day either, which is exactly why it is possible to spend a whole career in this industry without ever consciously picking it up.


The Trust Is Already There

The unusual thing about writing software for other people is that the people who depend on it cannot read it, and so they relate to it the way they relate to an electrician or a doctor or the person who inspected the elevator, which is to say they extend trust across a gap of knowledge they cannot personally close. Most of those older professions responded to that gap by building formal structures around it, with licensing and liability and apprenticeships and codes of practice, while our profession grew so quickly that it never got around to building much of anything, and whether that was freedom or neglect is a debate for another post. What matters here is the practical consequence, which is that the obligation exists but the structure does not, so the obligation is either self-imposed or it is absent, and there is no third option.

When I started in 1986, the person who wrote the software a small company depended on was usually someone the company knew by name, and the distance between author and user was short enough that responsibility had a face attached to it. That distance has since grown to the point where a developer can ship code to people they will never meet, inside organizations they will never visit, and the strange result is that the dependence of those users has not shrunk at all while the felt weight of it has almost disappeared. Acting like a developer means behaving as if the trust is still there, because it is, and it was placed in you by people who had no realistic way to check whether you deserved it.

The user cannot read your code, so they read you instead, and they do it by trusting what you shipped.


Decide for the Software That Has to Survive

The applications we build are mostly not the kind that get rewritten every eighteen months when a new fashion arrives, because they run the daily operations of organizations that need them to keep working for years, maintained by one person, sometimes part-time, sometimes by whoever could be persuaded to look after the thing. A booking system for a community center or a member directory for an association does not get a platform team and an on-call rotation, it gets a long life and a thin maintenance budget, and that shape of life has to be present in the decisions made at the very beginning, when everything still feels temporary.

Every technical decision carries a time horizon with it, and the honest version of the question is never "does this work today", because almost everything works today, but "what does this cost the person who owns this system in three years", and in our context that person is frequently us, which makes the question impossible to outsource. Choosing the slightly harder option that keeps the system understandable, choosing the boring approach that the next maintainer will recognize on sight, writing the twenty lines yourself instead of importing a stranger's two hundred - all of these look slower in the week they are made and obviously correct in the year they pay off.

Convenience compounds as surely as quality does, only in the wrong direction, because each small shortcut is a small loan taken against the future of the system, and the interest is paid by whoever is still around when the loan comes due. The developer who decides for survival is not being pessimistic about the future. They are the reason the system still has one.

Long-term survival is decided by a hundred small choices, each of which looked harmless on the day it was made.


The Random Package From the Registry

This is the point where the stance stops being philosophical and becomes specific, because there is a daily habit in modern JavaScript development that fails every part of the argument above at once, and it is the casual installation of a package that nobody on the team has read. The need is real and usually small: format a date, validate an email, debounce a function, and the registry has a package for it, and the install takes four seconds, and the import works, and the feature ships. What actually happened in those four seconds is that you took the trust your users placed in you and silently extended it to a person you have never met, whose code you have not opened, whose maintenance habits you do not know, and whose future motivations you cannot guess, and you did it for something you could frequently have written yourself before the install even finished.

We have written about the supply chain side of this in No Deps, No Build and there is no reason to repeat that argument here, because the point of this post is narrower and less dramatic: reading code before it enters your project is not paranoia and not heroics, it is simply the job, in the same way that an electrician checking a wire before connecting it is simply the job. A surprising share of what gets installed is smaller than the ceremony of installing it, and the stereotype of this habit already exists, so let us use it.

The registry contains two packages, one called is-even and one called is-odd, and their names are their entire documentation. As this is being written, is-odd is downloaded over a million times a week and is-even close to half a million more, and here is what is-even contains in its entirety:

var isOdd = require('is-odd');

module.exports = function isEven(i) {
  return !isOdd(i);
};

The evenness of a number, expressed as a dependency on the oddness of a number, which itself depends on a third package whose job is to confirm that a value is a number at all, which means that installing the even check places a small tree of packages written by strangers into your project so that your code can avoid writing n % 2 === 0. To be fair to the author, who is a prolific and respected maintainer, the code is honest, tested, and does exactly what it promises, which is precisely what makes it the perfect example, because the problem was never that these packages are bad. The problem is that a million and a half weekly downloads represent a million and a half occasions where nobody stopped to look, and a habit that size is not a series of decisions but the absence of one.

Once you have read the source of a few of these packages, you start to notice how often the honest response is to write the function and move on:

const is_even = (n: number): boolean => n % 2 === 0;

One line, no dependencies, no transitive tree, no download count standing in for a review that never happened, and no unremarkable morning three releases from now on which that line turns out to have changed owners and intentions while you were not watching.

None of this means packages are wrong, and our own projects vendor a small number of third-party libraries that genuinely earn their place, because some problems are deep enough that a well-maintained library is the responsible answer rather than the lazy one. The distinction that matters is between choosing a dependency and acquiring one. Choosing means you read the code or at least sized it honestly, you know what it does when things go wrong, you know how it is maintained and what it would cost to replace, and you made a decision you could explain to the person who will maintain the system after you. Acquiring means the install command succeeded and the import did not throw, and that was the entire evaluation.


The Not Knowing Is the Job

Every week this profession presents you with something you do not know yet - a protocol you have never touched, a data structure you have only heard named, a corner of the language you have been quietly avoiding, a failure mode you have never seen in production - and the response you choose in that moment is, as far as I can tell, the whole difference between a career that accumulates and a career that merely continues. There are two ways across the gap. You can close it, by sitting with the unfamiliar thing until it becomes familiar, or you can route around it, by installing a package that already solved it or asking a model to produce the answer, and both will get the feature shipped this week, which is exactly why the choice is so easy to get wrong.

What you trade away with the second option never appears on any invoice. The code ships either way, but in one version of the week you end it knowing something you did not know before, and in the other version you end it with precisely the same gaps you started with, plus one more dependency on something you could not rebuild if you had to. Understanding is the only asset in this job that compounds reliably, and the developer who has spent ten years routing around their gaps has not gathered ten years of experience so much as one year of experience repeated ten times, which is an old observation and remains an accurate one.

The threat I want to name is not that packages exist or that models write code, because both are useful and we use both, but that every unread answer quietly removes your ability to evaluate the next one. A developer who has never learned what the abstraction hides cannot tell a good answer from a plausible one, cannot debug the thing when it breaks at midnight, and cannot notice when the package update or the generated code is subtly, dangerously wrong, and the model will be wrong sometimes, delivered in the same confident tone it uses when it is right, because that is how it works. Blindly trusting an LLM to write the code instead of you is not a new sin at all but the same acquisition reflex as installing an unread package, wearing a newer and friendlier interface, and the question that judges both is identical: could you defend this in a review, line by line, if the person asking had written none of it.

The difference between a good answer and a plausible one is exactly the knowledge you skipped acquiring.

The honest way to use these tools is as teachers rather than as substitutes, which means asking the model to explain the protocol and then reading the specification to check whether it told the truth, studying the package's approach and then writing your own version to see what you missed, letting the tool accelerate the learning, which it genuinely can, without ever letting it replace the learning. We have made the case elsewhere for using the model once to build the generator rather than letting it guess at every task forever, and the same logic applies to the person: the tool should make you know more next month than you know now, because the day it lets you know less, you have stopped being the developer on the project and become its courier, and the courier is the first role the next better tool will come for.


The Honest Objections

The objections to all of this are real and they deserve to be taken seriously rather than waved away, because deadlines exist, budgets exist, managers exist, and the developer who installs an unread package an hour before the release cut is usually not careless but cornered by a schedule they did not set, a pressure we have written about in Stop Optimizing for the Wrong Speed and will not pretend away here. Nothing in this post is a verdict on people working under pressure, and if the sentence from the title is ever used to look down at someone in that position, it has been misunderstood in the worst way available.

It is also worth saying plainly that this is not a seniority ranking dressed up as ethics, because some of the most careful developers I have worked with were early in their careers and read everything precisely because they knew how much they did not know, while some of the least careful had two decades behind them and a reflex of trusting whatever the tutorial installed. The dividing line was never years or titles. It is attention, and attention is a choice that is available on the first day of the job.


What We Hold Ourselves To

For us, acting like it has a concrete shape, and it is the shape this whole site keeps circling around: zero runtime dependencies in the applications we generate, third-party code vendored as files we have read and committed, generators that produce code a maintainer can actually open and understand, and decisions made against the five-year horizon of the system rather than the five-day horizon of the sprint. This is how we do it, it has served us well, you do not have to, and we fail at it ourselves often enough that the sentence stays useful as a reminder rather than a trophy.

Because that is all the sentence ever was. It is not a ranking of who counts as a real developer, and it was never meant to be said down to anyone. It is said across, to the people who already feel the weight of what they ship, and it is said inward, to ourselves, on the days when the easy option is right there and nobody would ever find out.

You're a developer, act like it, because the people who trust your software already assume that you do.