about:drewcsillag

Nov 14, 2021 - 4 minute read - programming

Yes, Programming is Hard

I saw the article in Communications of the ACM “What Does Saying That ‘Programming Is Hard’ Really Say, and About Whom?” and as a twenty-six year veteran of the profession, I thought “of course programming is hard! Duh!” I then spoke with a friend where after a bit said “Do they mean like writing? Writing isn’t hard, but writing a book is”.

So in a sense, no programming isn’t intrinsically hard I guess, but in practice it is. In practice the problem is ill defined and incomplete, the constraints will not be fully understood, tooling may not exist, or at least be unknown to you, systems will be buggy.

Yes there are programming “spaces” where things aren’t that hard, for example the programming that is putting formulas in a spreadsheet, but I think it’s mostly because in those cases, the problems that professional programmers encounter don’t exist in those spaces.

The half-life of usefulness of knowledge is stunningly short, so you must constantly learn. Library upgrades, language upgrades, IDE upgrades, OS upgrades, database upgrades and more.

Scale, cost, flaky tests (assuming tests even exist), comments that are missing or wrong. Error messages from tools are inscrutable. Buggy tools, systems, and over all complexity. So much source code! It’s amazing sometimes that any of it works.

Oh, but the victory when it first works is absolutely sublime, and you feel like the smartest human on the planet; even though it can be mere minutes later when you find something so mind-bogglingly stupid that make you marvel that you don’t forget to breathe from time to time.

Being woken in the middle of the night while oncall, playbooks that don’t exist or are wrong, bogus pages, flapping systems, badly behaving downstream systems, sleepy brain trying to understand what’s going on. Users who are hostile, and/or don’t know what they want. Builds are slow, fighting with code to try to find out what turns out to be a single character errror.

For simple cases, yes programming isn’t hard, but for the real world it gets hard, and quick. In the real world, we marvel when the tests actually pass on the first run, and are more suspicious that the test is wrong when it happens.

Network calls that fail, timeout, or just hang. Failures that seem impossible, the “one in a million” error that you realize happens multiple times a day because you get millions of requests per day. The API doesn’t work at all, or fails more than it should, or doesn’t return the data the docs promised it would, or returns duplicate data because reasons. Stampeding herds, race conditions, heisenbugs, memory leaks, infinite loops, hardware failures, emergent behavior, program crashes, downtime. Cosmic ray induced failures (really!), speed of light issues (really! Did you know it’s 26ms speed of light distance round trip from San Francisco to New York City? Ask me why I know), distributed systems and consistency failures. Latency problems, routing issues, service discovery, firewall rules, cable cuts, cascading failure, partial failure, egress and ingress costs. Schema changes, database performance quirks, missing indexes, data corruption, deadlocks, missing integrity constraints, submarine writes, tombstones, split brain, data inconsistencies, performance cliffs.

Non-deterministic builds, the upstream SHAs changed (even innocently), supply chain problems, how many languages (usually at least five: JavaScript, HTML, CSS, SQL, [at least one backend language])?! Which browsers to support? Don’t forget React, webpack (or yarn, or…), and less. Bazel, make, rake, ant, gradle, npm, maven, and cargo, oh my! Dependency hell, bandaids and duct tape, stone knives and bearskins, “That shouldn’t happen”, “wait, that actually works?!”, “It works on my machine”, “It worked yesterday”, “Why is this so slow?”

Clusters of machines that are mostly the same. Dockerfiles, kubernetes manifests, configuration files, command line switches, feature flags, A/B testing. Resource management, cloud service billing, utilization, instance types, reserved instances, capacities, service versions, regions, and availability zones. What does this option do? You’re doing it wrong. Logging, metrics, tracing, alerting, profiling, tuning, SLAs, SLOs, maintenance windows, upgrades, migrations. Use this new hot framework. Security is hard, doing it right: harder. Patches, OS upgrades, zero days, network policies, expiring certificates, vulnerabilty management, which version of TLS? FedRAMP, LiSaaS, GDPR, HIPAA, PCI, SOC2, ITAR, audits, remediations, scans, controls.

And while extensive, the above list is nowhere close to complete.

And all this is before you get to the human element issues of people management, project management, team coordination, etc.

Maybe in a hundred years when Moore’s law has ended and much of this has settled and be straightforward as other engineering disciplines, but for now, we’re learning. We’re more like the alchemists of old before they understood the basics of chemistry, and it’s hard. We’ve only been at this for seventy years or so. We don’t know doodly squat yet.

This is why programming is hard.