4 min read · 2026-08-28
A rule you have only been told is a rule you will break under pressure.
Every programmer has been handed the same list. Do not repeat yourself. Keep functions small. Do not use global variables. Do not nest loops if you can avoid it. Name things properly.
The list is correct. It is also close to useless in the form it is usually given, because it arrives as a set of commandments with no accompanying reason. You memorise it, you follow it while someone is watching, and the first time you are tired and behind schedule you break every rule on it, because a rule you have only been told is not something you believe.
Coding War Crimes is a collection of deliberately terrible code, written on purpose, with the cost of each crime written next to it.
Show someone clean, well-structured code and they will nod. It looks like every other piece of good code they have seen, and it teaches almost nothing, because nothing about it is surprising.
Show someone a function that does the right thing in the worst possible way, and the reaction is different. There is a moment of recognition, usually uncomfortable, because most of us have written something close to it.
That recognition is what makes the lesson stick. You are not learning a rule, you are diagnosing a specific patient. And crucially, you can see what it cost, because each entry carries the complexity analysis alongside it: what happens to this code when the input gets ten times bigger.
That is the difference between "avoid nested loops" as advice and watching a comparison go from a thousand operations to a million because someone added an inner loop that looked harmless. One is a preference. The other is arithmetic.
This is the part that decides whether a collection like this is educational or just entertainment, and there is plenty of the second kind on the internet.
Each entry carries the correct version beside the terrible one. That turns the anti-pattern into an argument for the rule rather than a list to memorise. You see the bad code, you see what it costs, and you see the alternative and what it costs instead. The rule stops being an instruction from an authority and becomes the obvious conclusion from evidence you just looked at.
It is also a much better format for remembering. "Do not do X" is a floating prohibition. "Do not do X because it turns a linear operation into a quadratic one, here is the version that does not" is a small argument, and arguments survive contact with a deadline better than commandments do.
The interesting crimes are not the beginner ones. Nobody needs a repository to be told that single-letter variable names are bad.
The interesting ones are the mistakes that look reasonable while you are making them. Code that is correct on your test data and quietly wrong on real data. Optimisations that make the common case faster and the rare case catastrophic. Abstractions added to prevent duplication that never arrived, which now cost more to understand than the duplication would have.
The best example I have of this is not in that repository at all. In a basketball prediction pipeline I built, an early model scored an AUC of 0.9666, which is close to excellent. It was cheating. One of its features held what a team shot during the game, so it was reading the result of the match it claimed to be predicting.
Nothing about that code looked wrong. It was well organised, it ran, it produced a number that suggested it was working better than expected. The mistake was conceptual, and the only reason it was caught is that the number was too good, which is a terrible detection method to have to rely on. Fixing it dropped the score to about 0.74. The pipeline now runs an automatic leakage check before any model sees the data, because the lesson only becomes durable when it turns into something the code enforces.
What I want from this, and from writing generally, is for the reasoning to be portable.
You cannot memorise enough rules to cover every situation you will meet. But if you understand what a particular mistake costs and why, you can recognise the shape of it somewhere new, in a language you have not used, in a problem nobody wrote a rule for.
That is why the complexity analysis is in there rather than a verdict. A verdict tells you what to do this time. An argument tells you how to think about the next one.
Deliberately terrible code, written on purpose and annotated with what it costs. Each entry carries the complexity analysis and the correct version beside it, so the anti-pattern is an argument for the rule rather than a list to memorise.
drawn on the mapSelf-improving NCAA basketball predictor - auto-fetches ESPN data, trains 6 models, eliminates data leakage, and runs a full analytics dashboard. No API key needed.
has a charter of its own