← Writing

Systems books I still use

I still open these books when I have to reason about a system I can inspect and run locally.

I default to open source and local control. I have been around long enough to watch platform books expire with the next release cycle, and I keep the ones that still help me run a stack I can inspect.

The five titles below are those books. I open them when I need to think about a stack I still have to run.

The Mythical Man-Month, Frederick Brooks

Brooks is blunt about why adding people to a late project makes it later. The new people need time to learn the system, and the people already on the work spend that time teaching instead of finishing. Coordination grows with every extra pair of hands. The calendar does not move left.

I will say that again in the language I used on a LAMP desk. A late storefront does not get earlier because two more PHP contractors can type. Those contractors still have to learn the include graph, and someone who already knows that graph has to walk them through the catalog connection. While that walk happens, the checkout include sits.

I watched that play out on a shipping deadline years ago. Leadership brought in contractors to help close a storefront that had already missed one date. I spent mornings onboarding and afternoons watching the same bugs return in a new file. The release slid anyway. Brooks had already named the failure mode. I was late learning the vocabulary.

He also separates design from typing. On a LAMP box I administered, PHP was the part people could see. MySQL was the part that quietly decided whether the site stayed up. Schema choices made in a hurry outlast every template refactor. Brooks does not mention mysqli or PDO. He does not need to. The hard work happens before anyone commits a line.

Take the week when product wanted a Friday launch and engineering still had not decided whether a line item lived in the order row or in a child table. I drew the child table on a whiteboard, then left the room to onboard a contractor on the checkout include. When I came back, someone had stuffed SKUs into a VARCHAR on the order row so the page would render. That column is still in dumps I have seen years later. Adding people bought us a shortcut the next person had to live with.

I still open Brooks before I agree that more hands will simplify a schema.

SQL Antipatterns, Bill Karwin

Karwin writes for people who learned SQL on the job and never got a second opinion. I was one of them. I spent years on mysql_* calls in PHP before mysqli and PDO became the obvious path forward. The queries worked until they did not, usually under load or after a schema change nobody documented.

I will say that again in the language of those includes. I learned joins by breaking production. Nobody sat me down and asked whether a column should be a relation. The pages rendered, and the schema debt waited for a sale weekend.

The book names the patterns I kept meeting on client boxes. Overly wide tables show up when every new feature adds a column instead of a relation. I have wasted nights on nulls that meant two different things in the same column. String identifiers are a quieter mess. I have joined on a SKU that had two spellings because nobody had made the identifier a key.

When I moved a storefront from mysql_* to mysqli, the connection finally lived in one include I could lock down. Prepared statements made a failed query readable on a box I still had to keep up. The antipatterns stayed in the tables. A TEXT column still held a comma-separated list of category IDs because an early developer had treated a list as a string.

Take the Friday when a client wanted a report that counted orders by category after a sale weekend. PHP exploded the TEXT field in a loop that also ran on every product page under load. I built a junction table on a spare box and backfilled it from the TEXT column, then pointed the report at a JOIN I could explain. The pages got faster because the schema finally told the truth.

I still open Karwin when a convenient column should have been a relation.

Designing Data-Intensive Applications, Martin Kleppmann

If you build something that stores or moves data, and that covers almost everything now, this is the modern backbone text. Kleppmann writes about how storage systems copy data and what happens when those copies disagree. He does not pretend one architecture fits every workload.

When someone proposes new data layers in a single afternoon, I want to know which problem each layer solves. The book gives me language for that conversation before we pick tools.

I have watched this cycle in LAMP shops for a long time. A catalog feels cramped, so a meeting produces a new store before anyone has read EXPLAIN on the slow query. Frameworks rise and fall around the same tables. CakePHP and CodeIgniter books left my shelf when those stacks left the clients. The data questions stayed.

I will put Kleppmann in the language I still use on a MySQL box. You can ask whether two writes can land in a different order without buying a stream platform. You need to know what your primary promises after a crash, and whether the replica you read from is allowed to lag. Those questions survive a vendor rename.

Take the afternoon a vendor wanted a document store for product attributes because the MySQL catalog felt tight. The pressure was an entity-attribute-value table with no covering index, plus a PHP loop that issued one query per attribute. I asked which consistency problem the new store would solve. Nobody had one. We added the index and collapsed the loop into a JOIN, and the catalog stayed on the box I could dump.

I open Kleppmann when a slide deck arrives with layers I cannot name on hardware I run. If I cannot point to the machine that holds a copy, I treat the layer as unfinished.

Working Effectively with Legacy Code, Michael Feathers

Feathers teaches change under uncertainty in legacy code. He shows how to carve testable seams into tangled files so a system survives long enough to be rewritten properly. The rewrite can wait. The seam is the part you can defend.

Most of the PHP I inherited was a stack of includes with a global database handle. A change in one file moved a total in another. I used to rewrite from the checkout inward and miss a Friday. Feathers gave me a smaller move. Find the place the new behavior must live, and isolate enough of it that you can run it without booting the whole cart.

In an era of generated patches and quick migrations, the book is a reminder that maintainability is a decision you make when you are tired and tempted to ship the hack. I will accept help from a tool. If I cannot read what the tool wrote, I borrowed the work at interest. A generated hunk that I cannot explain on Monday is a debt I already know how to service.

Take the payment method we had to add to a PHP shop whose checkout lived in one long include. The include mixed tax with a credit-card post in the same function. I extracted the order total into a function I could call from a small script, then wrote two cases around a cart I invented in that script. I wired the new method through that function and left the rest of the include alone. The site shipped the new method without a rewrite.

Feathers is the book I open when a file looks too large to touch. The next change can still be small if I can name the seam.

The Clean Coder, Robert C. Martin

Martin writes about professional conduct. He argues for saying no when the schedule is fiction. He wants time left to think, and an estimate you can defend after you have given it.

I find the book useful when a team confuses velocity with motion. Shipping daily and learning nothing is still failure. The book gives you phrases for the conversations you were going to avoid.

Craft is the part I keep. Fundamentals are the part I still practice on a LAMP box. The title is a reminder that I own the result. If a tool writes a PDO wrapper I cannot read, I have not finished the job. I have borrowed someone else’s homework.

I have watched frameworks promise that the craft would live in the framework. Some of those frameworks are gone. The estimate conversations are not. A client still asks for Friday. I still have to say what I can stand behind on Friday without lying about Saturday.

Take the week a generated refactor offered to replace every mysql_* call in a catalog include. The diff was long and the names were clean. I read the first twenty lines and could not tell where the DSN lived, so I stopped the merge. I moved the connection into one file I already trusted, then changed the calls by hand in the two scripts that ran on the checkout path. The rest waited. I could defend that estimate because I had read the path I was going to ship.

Martin is useful on the days I want to look busy. Looking busy is cheap. Owning the files is the work.

What still earns a place on the shelf

The industry will keep shipping new nouns. Platform books expire with the next release cycle because they teach a vendor’s current names. I have owned PHP 4 paperbacks that could not help me on PHP 5. I have owned MySQL books that stopped matching the storage engine on the box. Framework titles left with the frameworks. Those books did a job for a season.

These five still help me run a stack I can inspect. I open Brooks when a room wants a hiring plan for a hole in the schema. I open Karwin when a column is doing the work of a table. If a title still helps me name the machine I can touch, it stays.

I keep these titles for the same open source habit. I want files I can open on a machine I administer.

On a Monday last winter a storefront I still watch went soft after a weekend sale. The catalog queries piled up, and the PHP error log pointed at a product filter that had been rewritten on Friday. The rewrite added a column and left the old TEXT list in place, so two sources of truth fought under load. I used Karwin’s habit first and named the antipattern, then picked the relation that should have existed. I used Brooks second and did not call for another pair of hands. I made the schema decision on a spare box and backfilled there. I cut over when the JOIN was boring. The questions on that ticket were the ones these books trained.

I keep the five titles because they still earn the space. When the next platform book arrives, I will read the chapter that names a machine I can touch. The rest can wait.