[{"data":1,"prerenderedAt":2175},["ShallowReactive",2],{"content-/ewahl/2026-08/ai-coding-agents-software-methodology":3},{"article":4,"all":1041},{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"publishDate":11,"image":12,"author":13,"tags":16,"excerpt":10,"body":23,"_type":1035,"_id":1036,"_source":1037,"_file":1038,"_stem":1039,"_extension":1040},"/ewahl/2026-08/ai-coding-agents-software-methodology","2026-08",false,"","AI Agents Didn't Invent a New Way to Build Software. They Funded the Old One.","The right way to build software has been known since 1970, proven on flagship programs, and priced out of reach of everyone else ever since. This is the story of that fifty-year gap — what the theory prescribed, what real-world budgets actually permitted, and how AI coding agents are closing it: one old practice at a time.","2026-08-25","/ewahl/2026-08/img/ai-coding-agents-software-methodology.jpg",{"name":14,"user":15},"Edward F. Wahl","ewahl",[17,18,19,20,21,22],"ai","agentic ai","ai coding agents","humans in the loop","spec-driven development","agile software development",{"type":24,"children":25,"toc":998},"root",[26,37,41,46,63,68,73,92,104,116,123,130,156,162,174,180,185,191,208,213,218,224,230,249,255,267,273,285,291,310,316,328,334,346,352,357,362,374,379,391,397,423,429,455,481,514,520,546,552,557,562,592,598,616,622,627,633,651,657,662,669,674,679,691,696,702,707,713,718,744,750,762,767,772,777,780,786,803,813,823,833,843,853,863,873,879],{"type":27,"tag":28,"props":29,"children":30},"element","p",{},[31],{"type":27,"tag":32,"props":33,"children":34},"em",{},[35],{"type":36,"value":10},"text",{"type":27,"tag":38,"props":39,"children":40},"hr",{},[],{"type":27,"tag":28,"props":42,"children":43},{},[44],{"type":36,"value":45},"I run engineering at Art+Logic, a custom software firm, which means I watch a lot of projects start. For twenty years they started more or less the same way — different clients, same first act. Not anymore. Lately, the first two weeks of a greenfield build go like this.",{"type":27,"tag":28,"props":47,"children":48},{},[49,51,56,58],{"type":36,"value":50},"The client talks. We ask questions — the annoying kind, about edge cases and exceptions and what happens when two rules collide. A few days later, not months, they click through a working prototype of the thing they described. It has their workflows in it, their vocabulary, their weird approval chain. We ask two questions. The first is ",{"type":27,"tag":32,"props":52,"children":53},{},[54],{"type":36,"value":55},"is this what you meant?",{"type":36,"value":57}," — the old requirements question, answerable now by pointing instead of by interpreting a document. The second matters more: ",{"type":27,"tag":32,"props":59,"children":60},{},[61],{"type":36,"value":62},"now that you can see what you asked for — does it hold up?",{"type":27,"tag":28,"props":64,"children":65},{},[66],{"type":36,"value":67},"Surprisingly often, it doesn't. The client looks at the screen and discovers that the rule they stated in the meeting, the one everyone nodded at, produces something nobody wants. Not a miscommunication — we built what they said. A discovery. Then the prototype gets thrown away. Its code was never going to ship; it existed to carry a conversation that documents alone couldn't carry. What accumulates instead, quietly, are the durable artifacts: the requirements the prototypes falsified their way toward, the standards, the scenarios that will hold the real system to account.",{"type":27,"tag":28,"props":69,"children":70},{},[71],{"type":36,"value":72},"From the outside this reads as the bleeding edge. There's an AI agent under every part of it. It is also, almost line for line, the process the field's founders started prescribing in the 1970s and '80s — and the part that should reframe your whole view of the current moment is this: that process was never hypothetical. It ran, for decades, at the top of the market. David Parnas ran his \"rational design process\" on the A-7E aircraft's operational flight software for the Naval Research Laboratory. And across the street from the Johnson Space Center, the on-board shuttle group (260 people maintaining the space shuttle's 420,000-line flight software, profiled by Charles Fishman in 1996 as \"They Write the Right Stuff\") ran the full program: roughly a third of the work done before anyone wrote a line of code, no line changed without an agreed change to the specification first. The results matched: the last three releases had one error each, against an estimated five thousand for commercial software of equivalent complexity. The price was part of the profile too: $35 million a year, for one program that flies one spaceship, in a shop where, as Fishman put it, \"money is not the critical constraint.\"",{"type":27,"tag":28,"props":74,"children":75},{},[76,78,83,85,90],{"type":36,"value":77},"One word in that paragraph is going to carry the whole essay, so let's define it now. A ",{"type":27,"tag":32,"props":79,"children":80},{},[81],{"type":36,"value":82},"specification",{"type":36,"value":84}," — the spec — is the complete statement of what a system is supposed to do: not \"handle invoices\" but every rule, every exception, every edge case, written down precisely enough that two people reading it would build the same behavior. The spec is not the code. The code is what a computer executes; the spec is what the code is ",{"type":27,"tag":32,"props":86,"children":87},{},[88],{"type":36,"value":89},"for",{"type":36,"value":91},".",{"type":27,"tag":28,"props":93,"children":94},{},[95,97,102],{"type":36,"value":96},"So: the right way to build software was known, published, and demonstrated within living memory of the moon landings. What it never was, for anyone below the flagship tier, was ",{"type":27,"tag":32,"props":98,"children":99},{},[100],{"type":36,"value":101},"affordable",{"type":36,"value":103},". Everything else in the industry's fifty-year methodology history — waterfall, agile, and the wars between them — is best understood as a series of compromises with that price tag, each one keeping the part of the program it could pay for and dropping the rest.",{"type":27,"tag":28,"props":105,"children":106},{},[107,109,114],{"type":36,"value":108},"AI coding agents have not invented a new way to build software. They are collapsing the price of the old way — practice by practice. So let's take the old program apart into its practices and run each one through the same three questions: what did the theory say, what could the real world actually afford, and what does an agentic build do instead? Then we'll put it back together and walk a project end to end. (And if the word \"specification\" is already making you think ",{"type":27,"tag":32,"props":110,"children":111},{},[112],{"type":36,"value":113},"big rigid plan, signed in blood, wrong by June",{"type":36,"value":115}," — good instinct. Hold it. Adapting to change is half of this story, and it survives.)",{"type":27,"tag":117,"props":118,"children":120},"h2",{"id":119},"the-throwaway-you-dont-know-what-to-build-until-youve-built-it",[121],{"type":36,"value":122},"The throwaway: you don't know what to build until you've built it",{"type":27,"tag":124,"props":125,"children":127},"h3",{"id":126},"royces-warning-and-the-diagram-everyone-misread",[128],{"type":36,"value":129},"Royce's warning and the diagram everyone misread",{"type":27,"tag":28,"props":131,"children":132},{},[133,135,140,142,147,149,154],{"type":36,"value":134},"Start with the most misread paper in the discipline. In 1970 an engineer named Winston Royce published \"Managing the Development of Large Software Systems,\" and it contains a diagram you have effectively seen even if you've never opened a software methodology book: a series of boxes cascading downhill — gather the requirements, then design the system, then write the code, then test it, then deliver — each stage finished and signed off before the next begins. The cascade look is where the industry's nickname for this process came from: ",{"type":27,"tag":32,"props":136,"children":137},{},[138],{"type":36,"value":139},"waterfall",{"type":36,"value":141},". Royce's paper is universally cited as waterfall's origin. The joke history played on him: the word \"waterfall\" appears nowhere in it, and the diagram appears as a ",{"type":27,"tag":32,"props":143,"children":144},{},[145],{"type":36,"value":146},"warning",{"type":36,"value":148},". Directly beneath it he wrote, \"I believe in this concept, but the implementation described above is risky and invites failure.\" His reasoning was simple and turned out to be prophetic: in a single downhill pass, the first honest feedback — real users touching real software — arrives at the very end, after all the money is spent, which is the most expensive possible moment to learn something. What Royce actually prescribed was the opposite of what got built in his name: ",{"type":27,"tag":32,"props":150,"children":151},{},[152],{"type":36,"value":153},"do it twice",{"type":36,"value":155},", with a preliminary pilot version built specifically to be discarded once it had taught you where the trouble lived, and involve the customer throughout, because the alternative is discovering at delivery what they meant at kickoff.",{"type":27,"tag":124,"props":157,"children":159},{"id":158},"brooks-plan-to-throw-one-away",[160],{"type":36,"value":161},"Brooks: plan to throw one away",{"type":27,"tag":28,"props":163,"children":164},{},[165,167,172],{"type":36,"value":166},"Fred Brooks (manager of IBM's gigantic System/360 software effort in the 1960s, and the closest thing the field has to a founding elder) made the same point unforgettable in his 1975 book ",{"type":27,"tag":32,"props":168,"children":169},{},[170],{"type":36,"value":171},"The Mythical Man-Month",{"type":36,"value":173},": \"plan to throw one away; you will, anyhow.\" His argument was an economist's, not an idealist's. The first system built is the one on which you learn what the system should have been. That's unavoidable. So the only real choice is whether to budget for the throwaway or to ship it to paying customers and call the learning process a maintenance contract. By 1986, in his essay \"No Silver Bullet,\" Brooks had upgraded the pilot from good practice to the builder's core duty: since clients cannot fully know what they want until they see something running, the single most important service a software builder performs is the iterative extraction and refinement of the requirements, through rapid prototyping. The prototype, in Brooks's telling, is not a demo. It is a requirements instrument.",{"type":27,"tag":124,"props":175,"children":177},{"id":176},"what-the-throwaway-actually-cost",[178],{"type":36,"value":179},"What the throwaway actually cost",{"type":27,"tag":28,"props":181,"children":182},{},[183],{"type":36,"value":184},"Now price it. Building a system twice, at human implementation rates, was a proposal that died in every budget meeting it ever entered — so the real world split into the two outcomes Brooks predicted. Most projects skipped the pilot entirely and ran the waterfall Royce warned about. If you have ever been the client on one of these, you know the shape from the inside: months of meetings distilled into a fat requirements document, a signature page, a long quiet stretch of invoices, and then a delivery date on which you finally touch the system and begin composing the sentence \"this isn't quite what we meant,\" with the budget already spent and every correction now billed as a change order. The requirements were frozen at the moment of least knowledge, which is the beginning, and nothing learned along the way had anywhere to go. The rest of the projects built the pilot and then committed the sin Brooks named specifically: they shipped it. Of course they did. Once a demo exists, building the real system \"again\" is an expense nobody will authorize, so demo code became production code, shortcuts and all. Even Brooks retreated. Twenty years later he called his own maxim \"wrong, not because it is too radical, but because it is too simplistic,\" his stated reason being that a full up-front throwaway assumed waterfall economics. The father of the idea didn't back away because it was wrong. He backed away because of what it cost.",{"type":27,"tag":124,"props":186,"children":188},{"id":187},"the-throwaway-on-an-agentic-build",[189],{"type":36,"value":190},"The throwaway on an agentic build",{"type":27,"tag":28,"props":192,"children":193},{},[194,196,201,203],{"type":36,"value":195},"On an agentic build, the cost is gone, and the practice comes back exactly as specified — so let me make it concrete with an example I'll keep returning to for the rest of this essay. It's hypothetical, but every business has a rule shaped like it. Suppose that in a requirements meeting, the client's CFO states a policy: ",{"type":27,"tag":32,"props":197,"children":198},{},[199],{"type":36,"value":200},"any invoice over $10,000 requires a second approval from a manager.",{"type":36,"value":202}," Everyone nods. It goes in the document. In the old world, that sentence gets implemented in month four and questioned by nobody. In ours, it's running in a prototype within days, and the client clicks through it — at which point someone from billing points at the screen and says: wait. Our biggest customer pays a $14,000 retainer on the first of every month. As written, this rule routes our single most routine transaction through a manager's inbox, twelve times a year, forever. ",{"type":27,"tag":32,"props":204,"children":205},{},[206],{"type":36,"value":207},"That's not what we meant. We meant unusual invoices.",{"type":27,"tag":28,"props":209,"children":210},{},[211],{"type":36,"value":212},"Notice what just happened. Our first question — is this what you meant? — would catch a misunderstanding, but there was no misunderstanding; we built the stated rule faithfully. It was the second question — now that you can see it, does it hold up? — that caught the real problem: the stated rule itself was wrong, and it took a running system to make that visible. That defect just got fixed for the cost of a conversation. In a waterfall project it would have been discovered in production, by an annoyed manager, and fixed as a change order.",{"type":27,"tag":28,"props":214,"children":215},{},[216],{"type":36,"value":217},"And when the conversation moves on, the prototype gets deleted — which is the discipline that was economically impossible for fifty years. When a rebuild costs less than the meeting where you'd argue about keeping it, the prototype can finally be what Royce and Brooks wanted it to be: an instrument, used and retired. None of its code ships. What ships forward is what it taught the spec. Brooks's dictum that clients can't know what they want until they see something running was always true. What was missing was the price.",{"type":27,"tag":117,"props":219,"children":221},{"id":220},"the-living-document-writing-it-down-and-keeping-it-from-becoming-a-lie",[222],{"type":36,"value":223},"The living document: writing it down, and keeping it from becoming a lie",{"type":27,"tag":124,"props":225,"children":227},{"id":226},"essential-and-accidental-complexity",[228],{"type":36,"value":229},"Essential and accidental complexity",{"type":27,"tag":28,"props":231,"children":232},{},[233,235,240,242,247],{"type":36,"value":234},"The theory of why you write the specification down — and why writing it down was never the hard part — has two layers, and the deeper one is the less famous. The famous layer is Brooks again. In \"No Silver Bullet\" he split software's difficulties into two kinds. The ",{"type":27,"tag":32,"props":236,"children":237},{},[238],{"type":36,"value":239},"accidental",{"type":36,"value":241}," difficulties are the friction of expression — the labor of translating a decision into working code, wrestling with languages and tools and plumbing. The ",{"type":27,"tag":32,"props":243,"children":244},{},[245],{"type":36,"value":246},"essential",{"type":36,"value":248}," difficulty is the conceptual construct itself: deciding what the rules actually are, how they interact, what happens in every edge case. In our running example, the accidental part is making the approval screen exist. The essential part is knowing that the threshold should exempt routine retainers — and every decision like it, across the whole system, held consistent. Brooks's verdict has been reprinted for four decades: \"The hardest single part of building a software system is deciding precisely what to build.\" Nothing cripples a system like getting that wrong, and nothing is costlier to fix late.",{"type":27,"tag":124,"props":250,"children":252},{"id":251},"parnas-how-and-why-to-fake-it",[253],{"type":36,"value":254},"Parnas: how and why to fake it",{"type":27,"tag":28,"props":256,"children":257},{},[258,260,265],{"type":36,"value":259},"The less famous layer arrived the same year, in the most honest paper in software engineering. The honesty is in the title: \"A Rational Design Process: How and Why to Fake It,\" by David Parnas and Paul Clements. The ideal process, they conceded, is one no real project follows: every design decision derived from a precise, documented statement of what the system must do, every choice traceable to a reason. Humans don't work that way and schedules don't permit it. Their fallback: follow the ideal as closely as you can, and ",{"type":27,"tag":32,"props":261,"children":262},{},[263],{"type":36,"value":264},"produce the documentation the ideal process would have produced",{"type":36,"value":266}," — even though you didn't live it — because those documents are what make a system reviewable, maintainable, and comprehensible to the next person who has to touch it. The field's considered response to \"the right way costs more than we have\" was to institutionalize forging the paper trail.",{"type":27,"tag":124,"props":268,"children":270},{"id":269},"the-confident-lie",[271],{"type":36,"value":272},"The confident lie",{"type":27,"tag":28,"props":274,"children":275},{},[276,278,283],{"type":36,"value":277},"What the real world could afford was less than that, and the reason is a property of documentation that makes half-funding it worse than not funding it at all. Software changes constantly. Documents don't change themselves. And a document that has drifted from the code is not neutral — it is a confident lie. (Every company has one: the wiki page, last edited three years ago, that states the approval threshold is $5,000. It hasn't been $5,000 since the reorg. New employees read it anyway.) Keeping documentation ",{"type":27,"tag":32,"props":279,"children":280},{},[281],{"type":36,"value":282},"true",{"type":36,"value":284}," — re-verifying its correspondence with a moving system, change after change — was labor nobody could bill for. So the industry retreated twice. The first retreat was Parnas's own advice: fake it. The second was more radical, more successful, and deserves a proper introduction, because it reshaped the entire industry.",{"type":27,"tag":124,"props":286,"children":288},{"id":287},"agiles-bargain-the-software-became-the-document",[289],{"type":36,"value":290},"Agile's bargain: the software became the document",{"type":27,"tag":28,"props":292,"children":293},{},[294,296,301,303,308],{"type":36,"value":295},"In 2001, seventeen veteran practitioners met at a ski lodge in Utah and published a short statement of values called the Manifesto for Agile Software Development. \"Agile\" is the name that stuck for the whole family of methods it blessed, and if you've worked anywhere near a modern software team you've lived inside its vocabulary: instead of one big plan executed over a year, work proceeds in short cycles — ",{"type":27,"tag":32,"props":297,"children":298},{},[299],{"type":36,"value":300},"sprints",{"type":36,"value":302},", typically two weeks — each of which delivers a small, working, usable slice of the system; the client sees running software every cycle; priorities get re-decided between cycles based on what everyone just learned. It was, in large part, the industry's immune response to waterfall — a way to stop freezing requirements at the moment of least knowledge. And among its declared values was this one: \"working software over comprehensive documentation,\" with the explicit caveat that the items on the right had value too, just less. Read that as an economic judgment and it was exactly right for its decade. If you cannot afford to keep the documents true, then a team forced to choose should trust the artifact that provably runs. So agile demoted the artifact that couldn't be kept in sync and promoted the one that could be executed. ",{"type":27,"tag":32,"props":304,"children":305},{},[306],{"type":36,"value":307},"The software became the document.",{"type":36,"value":309}," Want to know what the approval rule really is today? Don't read the wiki — it lies. Read the code, or find the person who last changed it and ask.",{"type":27,"tag":124,"props":311,"children":313},{"id":312},"naur-the-program-lives-in-peoples-heads",[314],{"type":36,"value":315},"Naur: the program lives in people's heads",{"type":27,"tag":28,"props":317,"children":318},{},[319,321,326],{"type":36,"value":320},"Which brings us to the endpoint of that retreat, described with eerie precision back in 1985 by a Danish computer scientist named Peter Naur, in an essay called \"Programming as Theory Building.\" A program, Naur argued, is not really its source text. It is a ",{"type":27,"tag":32,"props":322,"children":323},{},[324],{"type":36,"value":325},"theory",{"type":36,"value":327}," — a live understanding, held by people, of how the business's problems and the code's structure correspond — and the essential part of that understanding \"could not conceivably be expressed, but is inextricably bound to human beings.\" You have met Naur's theory even if you've never read him. It's why the answer to \"why does the discount field cap at 15 percent?\" is not in any document but in the memory of whoever met that one customer in 2019. It's why, when the engineer who built the billing system leaves, the billing system doesn't stop running but does, in a real sense, die. It can still be executed. It can no longer be confidently changed. For a custom software firm, this was always the uncomfortable truth of the balance sheet: the asset was never the code. It was the theory in the senior engineers' heads, and it walked out the door every evening.",{"type":27,"tag":124,"props":329,"children":331},{"id":330},"the-first-reliable-reader",[332],{"type":36,"value":333},"The first reliable reader",{"type":27,"tag":28,"props":335,"children":336},{},[337,339,344],{"type":36,"value":338},"An agentic build reverses the retreat, for a bluntly mechanical reason: an AI agent cannot read anyone's head. It consumes artifacts — requirements, standards, written scenarios — and it produces exactly what the artifacts say, which means everything that stays tacit is now, operationally, not part of the project. That sounds like a burden, and then you notice what it buys. The agent is the first teammate that consumes documentation as an operational input rather than honoring it as a virtuous intention — the first reader the documents have ever reliably had. Humans could always substitute a hallway conversation for the wiki, which is why the wiki died; an agent has no hallway. Parnas told the field to fake the rational process because living it was unaffordable. That excuse just expired. So on our projects the specification becomes a first-class artifact and stays one: requirements distilled from the actual mass of meetings, emails, and threads — an agent can hold all of it at once and surface where March's decision quietly contradicts May's. Add the technical standards, stated up front by a senior engineer, defining the right way to build on the chosen foundations. All of it versioned like code, enforced like code, and edited for the life of the system. What does ",{"type":27,"tag":32,"props":340,"children":341},{},[342],{"type":36,"value":343},"not",{"type":36,"value":345}," reprice is the essential difficulty itself. Deciding precisely what to build — that retainers are routine, that refunds are different, that Canada is coming — costs what it cost in 1986, because it was never a typing problem. And on a project where the typing is nearly free, it is most of the remaining bill.",{"type":27,"tag":117,"props":347,"children":349},{"id":348},"the-reconciliation-every-change-checked-against-the-whole",[350],{"type":36,"value":351},"The reconciliation: every change checked against the whole",{"type":27,"tag":28,"props":353,"children":354},{},[355],{"type":36,"value":356},"The purest statement of this practice is the shuttle group's standing rule: no coder changes a line without an agreed change to the specification first, and no spec change lands without both sides understanding everything it touches. Every change, reconciled against everything the system is supposed to be, before it exists. That is what \"a third of the process happens before code\" actually means in practice. And the theory of why ordinary organizations can't do this was written by Brooks too — it is the argument his book's title is famous for. The \"mythical man-month\" is the fallacy that people and time are interchangeable, that a late project can be rescued by adding staff; Brooks's Law says the opposite happens, and the arithmetic behind it is brutal in an ordinary way. Three people on a project have three lines of communication to maintain. Ten people have forty-five. Every person you add to buy more review capacity adds coordination overhead faster than they add review — which is why \"check every change against everything\" is not a thing you can hire your way into.",{"type":27,"tag":28,"props":358,"children":359},{},[360],{"type":36,"value":361},"What that scarcity cost in practice is the untold half of the agile story. Agile's bet — the code is the document, each sprint makes a change, you learn by shipping — is powerful. It also carries a cost curve that every team that has ridden it for a few years knows in their bones, even if nobody put it on a slide. As the system grows, the fraction of the big picture any one human can hold in their head while reviewing a change shrinks.",{"type":27,"tag":28,"props":363,"children":364},{},[365,367,372],{"type":36,"value":366},"Return to our invoice rule for the concrete version. Two years into the system's life, a developer adds a \"rush order\" feature: a streamlined screen that creates invoices in three clicks for time-sensitive deals. The feature is well built. Its tests pass. Sales loves it. And nobody in the review noticed that invoices created through the new screen never pass through the approval check, because the approval logic was wired to the old screen, and the person who built that wiring left last spring. The change was ",{"type":27,"tag":32,"props":368,"children":369},{},[370],{"type":36,"value":371},"locally correct and globally wrong",{"type":36,"value":373}," — perfect in its own corner, a policy violation in the whole — and no individual did anything unreasonable; the knowledge needed to catch it was simply spread across more heads and more code than any reviewer could hold.",{"type":27,"tag":28,"props":375,"children":376},{},[377],{"type":36,"value":378},"That is the quiet tax of agile at scale. Regressions get subtler. Estimates grow multipliers. \"Small change\" stops being a coherent category. Not because agile is wrong, but because its source of truth is the code — an artifact optimized for a computer to execute, not for anyone to check a change against everything the system is supposed to be. The pragmatic ceiling on agile efficiency was always the cost of that check: the same scarce input, review, that made living documentation unaffordable in the first place.",{"type":27,"tag":28,"props":380,"children":381},{},[382,384,389],{"type":36,"value":383},"This is where agents change something structural, because the capability that matters most is not writing code. It is reading everything, every time. An agent can hold the requirements, the standards, and the implementation in view at once and evaluate a proposed change against all three — every change, at a unit cost that makes whole-system review economically routine. The shuttle group's rule, as a default setting. Run the rush-order story again under that regime: the change arrives, and the reconciliation flags it — ",{"type":27,"tag":32,"props":385,"children":386},{},[387],{"type":36,"value":388},"this creates invoices without invoking the approval requirement stated in the spec",{"type":36,"value":390}," — before it lands, because something actually compared the change against the whole statement of what the system is supposed to be, which is exactly the review no human team could afford to perform on every change. So the agile loop keeps running — sprints, changes, learning by shipping — but each change is now reconciled against both the specification and the codebase as it lands. When implementation teaches that a requirement was wrong (the retainer discovery, at any point in the project's life), the requirement gets updated, not silently overruled by the code. When a change is locally green and globally wrong, the breadth of review that used to be unaffordable is what stands positioned to catch it. Specification and system stay in sync, and the sync is re-earned at every change. Which is why this is not waterfall wearing new clothes: the spec is not frozen at kickoff — on our projects it is the most-edited artifact in the repository, and the arrow between spec and code runs in both directions for the life of the system. Iteration survived. What died was the forced choice between iterating and staying specified.",{"type":27,"tag":117,"props":392,"children":394},{"id":393},"the-executable-fraction-what-a-test-suite-actually-is",[395],{"type":36,"value":396},"The executable fraction: what a test suite actually is",{"type":27,"tag":28,"props":398,"children":399},{},[400,402,407,409,414,416,421],{"type":36,"value":401},"One more piece of vocabulary, because the last practice lives inside it. A ",{"type":27,"tag":32,"props":403,"children":404},{},[405],{"type":36,"value":406},"test",{"type":36,"value":408},", in software, is a small program whose job is to use your system and check the answer. For the invoice rule, one test might create a $12,000 invoice and verify the system demands a second approval. Another creates a $9,000 invoice and verifies it doesn't. A real project accumulates hundreds or thousands of these — the ",{"type":27,"tag":32,"props":410,"children":411},{},[412],{"type":36,"value":413},"test suite",{"type":36,"value":415}," — and runs the entire suite automatically every time anything changes. When every test passes, the dashboard glows green; \"the build is green\" is industry shorthand for ",{"type":27,"tag":32,"props":417,"children":418},{},[419],{"type":36,"value":420},"all checks pass",{"type":36,"value":422},". Tests are the software profession's answer to \"how do you change one thing without breaking everything else.\" They are as close to a superpower as the field has.",{"type":27,"tag":124,"props":424,"children":426},{"id":425},"what-bdd-and-specification-by-example-got-right",[427],{"type":36,"value":428},"What BDD and specification by example got right",{"type":27,"tag":28,"props":430,"children":431},{},[432,434,439,441,446,448,453],{"type":36,"value":433},"The theory arrived two decades ago and was undersold by its own modest framing. In 2006 a consultant named Dan North published \"Introducing BDD\" (behavior-driven development), arguing that tests should be written as descriptions of behavior that a businessperson could read. The style that grew out of it expresses each scenario in three moves — ",{"type":27,"tag":32,"props":435,"children":436},{},[437],{"type":36,"value":438},"Given",{"type":36,"value":440}," a situation, ",{"type":27,"tag":32,"props":442,"children":443},{},[444],{"type":36,"value":445},"When",{"type":36,"value":447}," something happens, ",{"type":27,"tag":32,"props":449,"children":450},{},[451],{"type":36,"value":452},"Then",{"type":36,"value":454}," here's what must be true — and it reads like this:",{"type":27,"tag":456,"props":457,"children":458},"blockquote",{},[459],{"type":27,"tag":28,"props":460,"children":461},{},[462,467,469,473,475,479],{"type":27,"tag":463,"props":464,"children":465},"strong",{},[466],{"type":36,"value":438},{"type":36,"value":468}," a customer on the preferred list with a monthly retainer\n",{"type":27,"tag":463,"props":470,"children":471},{},[472],{"type":36,"value":445},{"type":36,"value":474}," an invoice over $10,000 is created for that retainer\n",{"type":27,"tag":463,"props":476,"children":477},{},[478],{"type":36,"value":452},{"type":36,"value":480}," no second approval is required",{"type":27,"tag":28,"props":482,"children":483},{},[484,486,491,493,498,500,505,507,512],{"type":36,"value":485},"Gojko Adzic's book named the whole practice ",{"type":27,"tag":32,"props":487,"children":488},{},[489],{"type":36,"value":490},"Specification by Example",{"type":36,"value":492},", and in that community a test suite is called an ",{"type":27,"tag":32,"props":494,"children":495},{},[496],{"type":36,"value":497},"executable specification",{"type":36,"value":499},". The name is exactly right, and it is the bridge this essay has been building toward: a test ",{"type":27,"tag":463,"props":501,"children":502},{},[503],{"type":36,"value":504},"is",{"type":36,"value":506}," a specification — a piece of the spec, written so precisely that a computer can check it. It's just a ",{"type":27,"tag":32,"props":508,"children":509},{},[510],{"type":36,"value":511},"partial",{"type":36,"value":513}," one: the fraction of your intent that somebody managed to make executable. Call the fraction 40 percent. The number is invented; the existence of the remainder is not. Every suite asserts some things and is silent about the rest, and the rest is not small — the intent behind the assertions, the meaning of the domain's words, the edge behavior nobody wrote down because to a human it was obvious. Nobody wrote the test that says a credit memo — a refund — doesn't count toward the $10,000 threshold, because nobody in billing would ever dream of counting one.",{"type":27,"tag":124,"props":515,"children":517},{"id":516},"why-tdd-worked-the-developer-supplied-the-other-60-percent",[518],{"type":36,"value":519},"Why TDD worked: the developer supplied the other 60 percent",{"type":27,"tag":28,"props":521,"children":522},{},[523,525,530,532,537,539,544],{"type":36,"value":524},"Two things kept that gap from mattering, historically, and both are worth seeing clearly. The first is that the fraction was thinner than it had to be — comprehensive suites were among the first things budgets cut. The second is an accounting trick nobody noticed they were running, inside a practice called test-driven development, or TDD: the discipline, dominant among serious teams for two decades, of writing the test ",{"type":27,"tag":32,"props":526,"children":527},{},[528],{"type":36,"value":529},"before",{"type":36,"value":531}," the code — first the check, then the thing being checked, in tight little loops. TDD worked because the same head wrote the test and the code. The developer who wrote the assertions carried the other 60 percent across personally — of course refunds don't count; obviously voided invoices are excluded — honoring intent no test checked, because it was ",{"type":27,"tag":32,"props":533,"children":534},{},[535],{"type":36,"value":536},"their own understanding",{"type":36,"value":538},", and violating it would have felt like a bug even when nothing fired. The missing majority of the spec was supplied silently, from memory, on every loop. It never appeared in any artifact, so it never appeared in any budget. It looked free. And the size of what it was covering for turns out to be measurable. HumanEval (a benchmark, meaning a standardized exam for AI coding models: 164 small programming problems, each graded by fewer than ten tests) was for years the field's report card. In 2023 a project called EvalPlus (Liu et al., NeurIPS 2023) asked the obvious question: what happens if you grade the same answers against ",{"type":27,"tag":32,"props":540,"children":541},{},[542],{"type":36,"value":543},"more of the specification",{"type":36,"value":545},"? They generated eighty times as many tests per problem. Measured pass rates across twenty-six models fell by as much as 19 to 29 percent, model rankings flipped outright, and errors surfaced in some of HumanEval's own official solutions. Same models. Same answers. The only thing that changed was how much of the spec was written down.",{"type":27,"tag":124,"props":547,"children":549},{"id":548},"auditing-the-suite-held-out-scenarios-and-a-human-with-a-mouse",[550],{"type":36,"value":551},"Auditing the suite: held-out scenarios and a human with a mouse",{"type":27,"tag":28,"props":553,"children":554},{},[555],{"type":36,"value":556},"Agents end the old arrangement from both directions. An optimizer satisfies what you wrote, not what you meant — it will pass your 40 percent to the letter and route straight through the silence, not out of malice but because the silence is, to it, genuinely silent. Ask an agent to implement the approval rule as written and it will happily count that credit memo, because the artifact it read never said otherwise. TDD with an agent is not TDD, faster; it is your specification with its tacit half deleted and its explicit half satisfied exactly.",{"type":27,"tag":28,"props":558,"children":559},{},[560],{"type":36,"value":561},"So on an agentic build the suite gets the double treatment. It gets bigger, because the comprehensive suite, the one that exercises the whole application the way a real user would, is finally affordable. And it gets audited, because a richer visible suite is also a richer surface for an optimizer to satisfy in letter and defeat in spirit. The audit machinery has two parts. First, held-out scenarios: a second, private exam the agent never sees, run separately. If the visible suite is green and the hidden one is red, that divergence is an alarm. Second, a scheduled human exploratory pass: a person with a mouse and no stake in the suite's opinion, clicking around the way users actually will.",{"type":27,"tag":28,"props":563,"children":564},{},[565,567,572,574,579,581,590],{"type":36,"value":566},"And when something fails, the triage has exactly two honest exits. Either the requirement or the standard was wrong — in which case the ",{"type":27,"tag":32,"props":568,"children":569},{},[570],{"type":36,"value":571},"spec",{"type":36,"value":573}," improves and every future piece of work inherits the fix. Or the agent didn't follow a standard that was right — in which case the fix is to harden the ",{"type":27,"tag":32,"props":575,"children":576},{},[577],{"type":36,"value":578},"harness",{"type":36,"value":580},", the project's enforcement layer: automated checks that run on every single change and physically block the ones that violate a standard. The difference matters more than it sounds: a rule in a memo is a request; a rule in the harness is a locked door. What the fix is never allowed to be is a stern conversation with the agent about doing better next time — an agent's account of its own behavior is part of the output being optimized, and a safety mechanism the optimizer can produce is a safety mechanism made of output. House rule: the standard lives in the harness or it doesn't exist. (There is an adversarial version of this whole topic — what a strong optimizer does to a green suite when passing is the goal — and I've written about it separately: ",{"type":27,"tag":582,"props":583,"children":587},"a",{"href":584,"rel":585},"https://artandlogic.com/blog/ewahl/2026-07/goodharts-law-ai-coding-agents",[586],"nofollow",[588],{"type":36,"value":589},"goodharts law and ai coding agents",{"type":36,"value":591},".)",{"type":27,"tag":117,"props":593,"children":595},{"id":594},"the-build-end-to-end-five-phases-of-an-agentic-greenfield-project",[596],{"type":36,"value":597},"The build, end to end: five phases of an agentic greenfield project",{"type":27,"tag":28,"props":599,"children":600},{},[601,603,608,610,614],{"type":36,"value":602},"Step back and look at what those four practices — the throwaway prototype, the living document, whole-system reconciliation, and the executable specification — were before the agents. Waterfall kept the specification and lost the learning. Agile kept the learning and lost the specification. Each was the correct engineering economics for what review and rebuilding cost at the time — and the full program, living documents ",{"type":27,"tag":32,"props":604,"children":605},{},[606],{"type":36,"value":607},"and",{"type":36,"value":609}," continuous iteration ",{"type":27,"tag":32,"props":611,"children":612},{},[613],{"type":36,"value":607},{"type":36,"value":615}," whole-system verification, stayed where it had always been, on projects that could spend $35 million a year on 420,000 lines. Here is what it looks like reassembled, at normal-budget scale, as one project — five phases, including the one every methodology conversation forgets.",{"type":27,"tag":124,"props":617,"children":619},{"id":618},"discovery-prototypes-as-requirements-instruments",[620],{"type":36,"value":621},"Discovery: prototypes as requirements instruments",{"type":27,"tag":28,"props":623,"children":624},{},[625],{"type":36,"value":626},"The first weeks are the scene this essay opened with: conversations turned into disposable prototypes while they're still warm, the two questions asked and re-asked, requirements like the invoice rule falsified early and cheaply, the durable spec accumulating in the background. More running software than a traditional project would show in two months — and none of it the product. Each prototype is a question. The old week-two demo was a down payment: the code being applauded was the code the client would eventually own, with every shortcut taken to reach the applause compounding underneath it like debt.",{"type":27,"tag":124,"props":628,"children":630},{"id":629},"ramp-up-where-visible-progress-dips",[631],{"type":36,"value":632},"Ramp-up: where visible progress dips",{"type":27,"tag":28,"props":634,"children":635},{},[636,638,643,645,649],{"type":36,"value":637},"Then comes a compressed stretch, wedged between discovery's demos and implementation's releases, that I want to prepare you for honestly, because its visible progress dips exactly as its real progress accelerates. This is where the foundation goes in: the requirements formalized into scenario suites, the technical standards written down, the sample data, the harness — collectively, the documentation and validation guardrails that let an agent measure success while it builds. Nothing in this phase demos well, and somewhere in it every client asks some version of ",{"type":27,"tag":32,"props":639,"children":640},{},[641],{"type":36,"value":642},"when does the real application start?",{"type":36,"value":644}," The honest answer is that this ",{"type":27,"tag":32,"props":646,"children":647},{},[648],{"type":36,"value":504},{"type":36,"value":650}," the application — the part of it that determines whether everything after can be trusted. The clickable part earlier was the requirements conversation. This part is the definition of \"done\" being made checkable. It is also where the project's risk gets spent deliberately, at its cheapest. A requirement corrected here is an edit to a document; the same correction after launch is surgery on a live system with a year of data in it. That's not a research finding, it's arithmetic — but it runs against instinct, because the traditional arc trained everyone to read visible progress as real progress, and this is the one stretch where the two visibly part ways.",{"type":27,"tag":124,"props":652,"children":654},{"id":653},"implementation-agents-build-humans-hold-the-verdict",[655],{"type":36,"value":656},"Implementation: agents build, humans hold the verdict",{"type":27,"tag":28,"props":658,"children":659},{},[660],{"type":36,"value":661},"The bulk of the schedule, and the part everyone pictures when they picture AI coding — and it is genuinely great. The rhythm is recognizably agile: functionality specified against the standards in sprint-sized pieces, agents implementing, working software going out for client review on a frequent cadence. The demos are back, and this time they're the product. What's different is underneath. Every change is reconciled against the requirements, the standards, and the rest of the codebase before it lands — the rush-order check, running on everything — and whatever the build teaches flows back into the spec, so documentation, tests, and implementation stay in sync with each thing learned. Humans review the judgment calls the reconciliation surfaces rather than trying to re-derive that breadth themselves. The senior engineer's job here is not reading every line. It is recognizing mistakes while they are small — treating a suspicious success with the same attention as a failure, noticing that a hard piece went green a little too easily — and jumping on the discrepancy hard, because misunderstandings now compound at the speed of an agent, not the speed of a typist.",{"type":27,"tag":663,"props":664,"children":666},"h4",{"id":665},"the-requirement-nobody-wrote-down-a-validator-that-accepted-minus-five-hours",[667],{"type":36,"value":668},"The requirement nobody wrote down: a validator that accepted minus five hours",{"type":27,"tag":28,"props":670,"children":671},{},[672],{"type":36,"value":673},"I want to pause the walkthrough here for a story. Strictly an aside — the phases resume at the release — but it's the clearest picture I can give you of what that reviewer's job feels like from the inside.",{"type":27,"tag":28,"props":675,"children":676},{},[677],{"type":36,"value":678},"The rule the agent broke, on a recent build of ours, was that you cannot work negative hours. I want to be precise about how boring that is, because the boringness is the whole point. The ticket asked for a time entry — a worker records how long they spent on a task — and it specified, in writing, the one peculiar thing about how we count time: hours land on a 0.05-hour grid, three-minute increments, no odd fractions. The agent implemented that flawlessly. The validator it wrote checked divisibility by 0.05 and rejected anything off the grid — clean, correct, enforcing exactly the rule somebody had bothered to write down. It also cheerfully accepted -5.00, because minus five is a perfectly tidy multiple of 0.05; the tidiness check certified negative five hours as well-rounded and waved it through. Every test passed. Better than passed — the harness wasn't merely silent on the rule; it had written down the opposite and called it green. The test suite for that validator explicitly listed 0.00 as a valid value to accept.",{"type":27,"tag":28,"props":680,"children":681},{},[682,684,689],{"type":36,"value":683},"A human caught it, not a test, and not at first for the reason that mattered. The reviewer's note started small — a negative entry could corrupt the hours we mirror out to GitLab — and only widened, under a second look, into the actual hole: a negative row subtracts from the billable dollars in its rate group, drops silently out of the invoice preview so the work is simply never billed, and skews every report that sums hours. The post-mortem is where it got humbling. I went looking for the line the agent had violated, so I could say ",{"type":27,"tag":32,"props":685,"children":686},{},[687],{"type":36,"value":688},"there, that's the spec it ignored",{"type":36,"value":690}," — and there was no line. The requirement had never existed in writing. The closest artifact was a positivity constraint on a different table, the invoice line items, which proved only that we knew the rule well enough to enforce it wherever we'd happened to think of it, and never thought to write it on the table that actually stores the hours people work. You cannot blame the agent. It was faithful and it was competent; it did exactly, and only, what was written, and what was written was thorough about the exotic and mute about the obvious. It's the credit memo again: nobody in this shop would ever dream of logging minus five hours, and that is exactly why nobody ever wrote it down.",{"type":27,"tag":28,"props":692,"children":693},{},[694],{"type":36,"value":695},"The fix was to finally say the thing out loud, in the three places a machine can hear it: a check at the form boundary; a CHECK (time > 0) constraint in the database, so no code path can ever persist a negative hour again; and a property test in the invariant suite asserting that no zero or negative value is ever accepted — the same file where we had once parametrized 0.00 as fine, now inverted. That last diff is the scar I point to: a rule that lived for years below the waterline of writing, because it was too obvious to say, now pinned in a test that exists solely because a competent agent, reading a thorough spec, had no reason not to accept minus five hours. And this is the process working, not failing — the reviewer caught it early, by design. That is what the reviewer is for. But it is still humbling, because the miss was never in the 40 percent we argued over in the ticket. It was in the 60 percent nobody wrote down. And the 60 percent is made of things exactly this dumb.",{"type":27,"tag":124,"props":697,"children":699},{"id":698},"production-release-converging-on-the-specification",[700],{"type":36,"value":701},"Production release: converging on the specification",{"type":27,"tag":28,"props":703,"children":704},{},[705],{"type":36,"value":706},"Back to the walkthrough. By late implementation, something happens that took me a while to trust: the project converges on its specification. The requirements, the standards, and the scenario suites now describe the system that exists, and the harness enforces the correspondence — which changes what \"wrapping up\" means. In a traditional project this is where the deferred risk comes due: the integration crunch, the stabilization sprints, the feature freeze, the punch list that grows faster than it shrinks. Here, integration surprises have been getting caught continuously for months, so the endgame is short and quiet: hardening, cutover, and a final round of client adjustments — which are efficient for the same reason everything else has been, because a late change is an edit to the spec run through the harness, not an argument with a fragile codebase. Raise the approval threshold to $25,000 and exempt government customers? An edit, verified against everything, live before launch.",{"type":27,"tag":124,"props":708,"children":710},{"id":709},"maintenance-what-an-agent-built-system-costs-a-year-later",[711],{"type":36,"value":712},"Maintenance: what an agent-built system costs a year later",{"type":27,"tag":28,"props":714,"children":715},{},[716],{"type":36,"value":717},"And then the phase that every methodology debate skips, where a real and mostly invisible piece of the value sits. Consider what happens to a traditional project when active development ends. The team disperses to other work, and the unwritten 60 percent — the intent wedged between the tests and the code, the reasons living in people's heads — starts fading that same week. Come back in six or twelve months with a change request and the work is slower and riskier even if you get the same developers, because they must first re-learn their own system before they can safely change it. Usually you don't get the same developers, and then it's Naur's program death in slow motion: a system that still runs and can no longer be confidently changed. Now run the same clock against an agentic project. The knowledge that used to live in heads was encoded as the work happened — requirements, standards, scenario suites, and code, still in agreement because agreement was re-earned at every change. An agent picking the system up a year later reads the same artifacts and is exactly as fresh as the day active development paused. The project does not atrophy on the shelf. A routine change request in month fourteen costs what it cost in month four.",{"type":27,"tag":28,"props":719,"children":720},{},[721,723,728,730,735,737,742],{"type":36,"value":722},"Most of the time. Here is the caveat that keeps the maintenance claim honest. \"Just ask\" is true ",{"type":27,"tag":32,"props":724,"children":725},{},[726],{"type":36,"value":727},"inside the change-space the architecture anticipated",{"type":36,"value":729},". A change that violates a foundational assumption is a different animal: if the system was built assuming all money is in one currency and the client announces they're opening in Canada, that is a ",{"type":27,"tag":32,"props":731,"children":732},{},[733],{"type":36,"value":734},"refactor",{"type":36,"value":736}," (a rebuilding of internal structure, replumbing the house rather than repainting a room), and no harness converts it into a small ask, agents or no agents. What the approach buys is a shift in the cost ",{"type":27,"tag":32,"props":738,"children":739},{},[740],{"type":36,"value":741},"distribution",{"type":36,"value":743}," of change: the great mass of requests collapses toward trivial, and a fat tail of hard ones remains. Telling, quickly and correctly, which kind you're looking at is senior judgment, and it can't be delegated to the thing whose incentive is to say \"easy\" — which is why the senior engineer stands at the end of the project as well as the beginning, and \"the end,\" for a system that earns its keep, means years. And the deliverable underneath it all is the thing Naur said could never be handed off, or as close as I know how to get: not just a running system but its accumulated specification — explicit, versioned, enforced, still true. Naur is still right that some remainder lives only in heads. The difference is that the remainder is now small enough to name.",{"type":27,"tag":117,"props":745,"children":747},{"id":746},"the-honest-accounting-what-agentic-development-actually-costs",[748],{"type":36,"value":749},"The honest accounting: what agentic development actually costs",{"type":27,"tag":28,"props":751,"children":752},{},[753,755,760],{"type":36,"value":754},"As of mid-2026, the market pitch is: ",{"type":27,"tag":32,"props":756,"children":757},{},[758],{"type":36,"value":759},"we use AI, so — same software, half the people, half the price.",{"type":36,"value":761}," Look at what that pitch keeps and what it deletes. It keeps the compromises — usually the demo-becomes-product arc, requirements frozen at the moment of least knowledge — and deletes the humans who silently supplied the unwritten majority of every specification. And it points an optimizer at the written fraction that remains: the agent that will happily count the credit memo, at unprecedented speed. That isn't a new methodology either, as it happens — it's the oldest one, ship the throwaway to the customer, faster than it has ever been shipped.",{"type":27,"tag":28,"props":763,"children":764},{},[765],{"type":36,"value":766},"The accounting that actually holds up is less slogan-friendly. Implementation cost falls, a lot. Review cost falls further, which is the structurally interesting part, because review scarcity is what forced both of the historical compromises. Specification cost (deciding precisely what to build, and keeping the decision true as the system teaches you better) does not fall, and becomes the dominant line item. That is where the senior time goes: eliciting intent, writing it down, maintaining the harness that enforces it, and holding the verdict at every reconciliation where the spec meets the world. Total cost comes down. It does not halve just because headcount can. What a project gets that it could not get before, at any price a normal budget could pay, is the thing the shuttle group was buying: a system whose specification and implementation are the same story, kept true against every change.",{"type":27,"tag":28,"props":768,"children":769},{},[770],{"type":36,"value":771},"Because here is the ending I owe you, and it is not triumphant. The specification problem is not solved. Brooks called it the essence, and nothing above dissolves it — not the agents, not the harness, not the loop. What changed is the price of attacking it, and the price changed in exactly the direction the field's founders kept pointing: pilot systems, planned throwaways, living documents, clients confronted early with running software, every change checked against the whole. We didn't discover a new way to build software. We got the invoice down on the old one — the one that was right the whole time, the one that until now you needed a spaceship to justify — and found that the part it leaves to humans is the part that was always the actual job. Leslie Lamport (Turing Award laureate, creator of TLA+ and LaTeX) puts it this way: \"Coding is to programming what typing is to writing.\" The agents type now.",{"type":27,"tag":28,"props":773,"children":774},{},[775],{"type":36,"value":776},"Nobody was ever paying us to type. It just took fifty years and a typing machine to make that undeniable.",{"type":27,"tag":38,"props":778,"children":779},{},[],{"type":27,"tag":117,"props":781,"children":783},{"id":782},"common-questions",[784],{"type":36,"value":785},"Common Questions",{"type":27,"tag":28,"props":787,"children":788},{},[789,794,796,801],{"type":27,"tag":463,"props":790,"children":791},{},[792],{"type":36,"value":793},"Are AI coding agents a new software development methodology?",{"type":36,"value":795},"\nNo — and that's the point. The practices an agent-centric process enables were prescribed decades ago and proven on flagship programs: Royce's 1970 paper (misread as waterfall's origin) recommended a disposable pilot system and continuous customer involvement; Brooks's ",{"type":27,"tag":32,"props":797,"children":798},{},[799],{"type":36,"value":800},"Mythical Man-Month",{"type":36,"value":802}," (1975) said to plan a throwaway; \"No Silver Bullet\" (1986) prescribed prototype-driven requirements refinement; Parnas and Clements (1986) argued for rigorous living documentation and ran it on the A-7E avionics program. The space shuttle's on-board software group ran the full program at $35M a year. Agents changed the cost of that way of working, not the way.",{"type":27,"tag":28,"props":804,"children":805},{},[806,811],{"type":27,"tag":463,"props":807,"children":808},{},[809],{"type":36,"value":810},"Isn't specification-first agentic development just waterfall again?",{"type":36,"value":812},"\nNo. Waterfall's failure was never that it wrote things down — it was that nothing learned during implementation could flow back into what was written down, so requirements stayed frozen at the moment of least knowledge. Agile fixed that by making the running code the source of truth, which works until complexity outruns any human's ability to review a change against the whole system. Agents remove the dilemma: development stays iterative, but every change is reconciled against both the specification and the codebase, and the spec is updated when implementation proves it wrong. The specification is the most-edited artifact on the project, not a kickoff deliverable.",{"type":27,"tag":28,"props":814,"children":815},{},[816,821],{"type":27,"tag":463,"props":817,"children":818},{},[819],{"type":36,"value":820},"What is the difference between essential and accidental complexity?",{"type":36,"value":822},"\nFred Brooks drew the distinction in \"No Silver Bullet\" (1986). Accidental complexity is the friction of expression — translating a decision into working code, wrestling with languages, tools, and plumbing. Essential complexity is the conceptual construct itself: deciding what the rules actually are and how they interact. AI coding agents collapse the cost of the accidental part and leave the essential part where it has always been: with humans, who still must decide precisely what the system should do. On an agent-built project, that essential work becomes the dominant share of the remaining cost.",{"type":27,"tag":28,"props":824,"children":825},{},[826,831],{"type":27,"tag":463,"props":827,"children":828},{},[829],{"type":36,"value":830},"Why build prototypes that get thrown away?",{"type":36,"value":832},"\nBecause a prototype is a requirements instrument, not a first draft of the product. Running software put in front of a client in week one answers two questions a document can't: whether the builder understood the requirement, and — more important — whether the requirement itself survives being seen working. Discarding the prototype keeps demo shortcuts out of the production codebase; the historical failure of prototyping was that the throwaway shipped, because rebuilding was unaffordable. With agents, the rebuild is cheaper than the argument about keeping it.",{"type":27,"tag":28,"props":834,"children":835},{},[836,841],{"type":27,"tag":463,"props":837,"children":838},{},[839],{"type":36,"value":840},"If the test suite passes, why can an agent-built system still be wrong?",{"type":36,"value":842},"\nBecause a test suite is only the executable fraction of a specification — the part of your intent someone managed to write as automated checks. Human developers silently honored the unwritten remainder (intent, domain meaning, the obvious edge cases) because it was their own understanding. An agent optimizes exactly what is written and nothing else. The EvalPlus project demonstrated the gap empirically: grading the same model outputs against 80× more tests cut measured pass rates by as much as 19 to 29 percent and reordered model rankings.",{"type":27,"tag":28,"props":844,"children":845},{},[846,851],{"type":27,"tag":463,"props":847,"children":848},{},[849],{"type":36,"value":850},"Does test-driven development still work with AI coding agents?",{"type":36,"value":852},"\nNot the way it used to. TDD worked for two decades because the same person wrote the test and the code, silently supplying the intent the assertions never captured. An agent supplies none of it — it satisfies the written tests exactly and treats the unwritten remainder as genuinely absent. TDD with an agent is your specification with its tacit half deleted and its explicit half satisfied to the letter.",{"type":27,"tag":28,"props":854,"children":855},{},[856,861],{"type":27,"tag":463,"props":857,"children":858},{},[859],{"type":36,"value":860},"Do you still need senior engineers if agents write the code?",{"type":36,"value":862},"\nYes, and at both ends of the project. At the start, someone must elicit the goal and write it down as standards and scenarios precise enough for an optimizer to be held to. Throughout, someone must hold the verdict when the reconciliation loop flags a conflict between spec and implementation. Deciding which one is wrong is domain judgment, not pattern matching. And at the end, someone must judge which change requests fall inside the architecture's assumptions (now trivial) and which violate them (still real refactors). That judgment about what \"correct\" means was never a typing job, which is why it didn't get automated with the typing.",{"type":27,"tag":28,"props":864,"children":865},{},[866,871],{"type":27,"tag":463,"props":867,"children":868},{},[869],{"type":36,"value":870},"What happens when you come back to an agent-built system a year later?",{"type":36,"value":872},"\nIn a traditional project, the unwritten knowledge in the developers' heads starts fading the day active development stops, so a change request six or twelve months later is slower and riskier even with the same team — and you rarely get the same team. In an agent-centric project that knowledge was encoded as the work happened: requirements, standards, and test scenarios kept in sync with the code through every change. An agent picks the system up as fresh as the day work paused, so routine changes stay routine; only changes that violate foundational architecture assumptions still demand real engineering effort.",{"type":27,"tag":117,"props":874,"children":876},{"id":875},"sources",[877],{"type":36,"value":878},"Sources",{"type":27,"tag":880,"props":881,"children":882},"ul",{},[883,896,907,919,931,943,955,967,986],{"type":27,"tag":884,"props":885,"children":886},"li",{},[887,889,894],{"type":36,"value":888},"Royce, W. W. (1970). ",{"type":27,"tag":32,"props":890,"children":891},{},[892],{"type":36,"value":893},"Managing the Development of Large Software Systems.",{"type":36,"value":895}," Proc. IEEE WESCON. (The \"waterfall\" paper that warned the single-pass model \"is risky and invites failure\" and prescribed \"do it twice.\")",{"type":27,"tag":884,"props":897,"children":898},{},[899,901,905],{"type":36,"value":900},"Brooks, F. P. (1975). ",{"type":27,"tag":32,"props":902,"children":903},{},[904],{"type":36,"value":171},{"type":36,"value":906},", ch. 11, \"Plan to Throw One Away\"; and the 20th Anniversary Edition (1995), \"The Mythical Man-Month after 20 Years,\" for his partial recantation.",{"type":27,"tag":884,"props":908,"children":909},{},[910,912,917],{"type":36,"value":911},"Brooks, F. P. (1986/1987). ",{"type":27,"tag":32,"props":913,"children":914},{},[915],{"type":36,"value":916},"No Silver Bullet — Essence and Accident in Software Engineering.",{"type":36,"value":918}," IFIP / IEEE Computer.",{"type":27,"tag":884,"props":920,"children":921},{},[922,924,929],{"type":36,"value":923},"Parnas, D. L., Clements, P. C. (1986). ",{"type":27,"tag":32,"props":925,"children":926},{},[927],{"type":36,"value":928},"A Rational Design Process: How and Why to Fake It.",{"type":36,"value":930}," IEEE Transactions on Software Engineering SE-12. (Applied on the A-7E operational flight program at the Naval Research Laboratory.)",{"type":27,"tag":884,"props":932,"children":933},{},[934,936,941],{"type":36,"value":935},"Fishman, C. (1996). ",{"type":27,"tag":32,"props":937,"children":938},{},[939],{"type":36,"value":940},"They Write the Right Stuff.",{"type":36,"value":942}," Fast Company. (The on-board shuttle group: the existence proof for the full program, and its price.)",{"type":27,"tag":884,"props":944,"children":945},{},[946,948,953],{"type":36,"value":947},"Beck, K., et al. (2001). ",{"type":27,"tag":32,"props":949,"children":950},{},[951],{"type":36,"value":952},"Manifesto for Agile Software Development.",{"type":36,"value":954}," agilemanifesto.org.",{"type":27,"tag":884,"props":956,"children":957},{},[958,960,965],{"type":36,"value":959},"Naur, P. (1985). ",{"type":27,"tag":32,"props":961,"children":962},{},[963],{"type":36,"value":964},"Programming as Theory Building.",{"type":36,"value":966}," Microprocessing and Microprogramming 15.",{"type":27,"tag":884,"props":968,"children":969},{},[970,972,977,979,984],{"type":36,"value":971},"North, D. (2006). ",{"type":27,"tag":32,"props":973,"children":974},{},[975],{"type":36,"value":976},"Introducing BDD.",{"type":36,"value":978}," dannorth.net. Adzic, G. (2011). ",{"type":27,"tag":32,"props":980,"children":981},{},[982],{"type":36,"value":983},"Specification by Example.",{"type":36,"value":985}," Manning.",{"type":27,"tag":884,"props":987,"children":988},{},[989,991,996],{"type":36,"value":990},"Liu, J., Xia, C. S., Wang, Y., Zhang, L. (2023). ",{"type":27,"tag":32,"props":992,"children":993},{},[994],{"type":36,"value":995},"Is Your Code Generated by ChatGPT Really Correct? Rigorous Evaluation of LLMs for Code Generation.",{"type":36,"value":997}," NeurIPS 2023. arXiv:2305.01210",{"title":8,"searchDepth":999,"depth":999,"links":1000},3,[1001,1008,1016,1017,1022,1032,1033,1034],{"id":119,"depth":1002,"text":122,"children":1003},2,[1004,1005,1006,1007],{"id":126,"depth":999,"text":129},{"id":158,"depth":999,"text":161},{"id":176,"depth":999,"text":179},{"id":187,"depth":999,"text":190},{"id":220,"depth":1002,"text":223,"children":1009},[1010,1011,1012,1013,1014,1015],{"id":226,"depth":999,"text":229},{"id":251,"depth":999,"text":254},{"id":269,"depth":999,"text":272},{"id":287,"depth":999,"text":290},{"id":312,"depth":999,"text":315},{"id":330,"depth":999,"text":333},{"id":348,"depth":1002,"text":351},{"id":393,"depth":1002,"text":396,"children":1018},[1019,1020,1021],{"id":425,"depth":999,"text":428},{"id":516,"depth":999,"text":519},{"id":548,"depth":999,"text":551},{"id":594,"depth":1002,"text":597,"children":1023},[1024,1025,1026,1030,1031],{"id":618,"depth":999,"text":621},{"id":629,"depth":999,"text":632},{"id":653,"depth":999,"text":656,"children":1027},[1028],{"id":665,"depth":1029,"text":668},4,{"id":698,"depth":999,"text":701},{"id":709,"depth":999,"text":712},{"id":746,"depth":1002,"text":749},{"id":782,"depth":1002,"text":785},{"id":875,"depth":1002,"text":878},"markdown","content:ewahl:2026-08:ai-coding-agents-software-methodology.md","content","ewahl/2026-08/ai-coding-agents-software-methodology.md","ewahl/2026-08/ai-coding-agents-software-methodology","md",[1042,1055,1064,1077,1092,1104,1112,1122,1133,1142,1154,1165,1176,1185,1195,1206,1219,1230,1239,1249,1257,1264,1273,1281,1290,1300,1310,1319,1328,1336,1347,1355,1363,1372,1380,1390,1398,1406,1414,1422,1430,1438,1446,1456,1464,1474,1482,1492,1502,1513,1523,1533,1549,1560,1571,1581,1592,1604,1614,1627,1639,1649,1658,1669,1684,1694,1704,1718,1728,1737,1747,1759,1770,1780,1791,1800,1810,1813,1823,1833,1843,1855,1867,1881,1895,1910,1918,1926,1935,1944,1953,1962,1971,1980,1989,1998,2007,2018,2031,2041,2049,2057,2065,2073,2085,2097,2107,2116,2125,2135,2144,2154,2163],{"_path":1043,"title":1044,"description":1045,"image":1046,"publishDate":1047,"tags":1048,"_id":1051,"author":1052},"/alalande/2023-1/escaping_text","Thinking Like a Programmer: Escaping Text","In this progressive and vivid explanation, we explore the HOW and WHY of quoting, nesting, and escaping text.","/alalande/2023-1/img/header.png","2024-02-15",[1049,1050],"series","educational","content:alalande:2023-1:escaping_text.md",{"user":1053,"name":1054},"alalande","Anthony Lalande",{"_path":1056,"title":1057,"description":1058,"image":1059,"publishDate":1060,"tags":1061,"_id":1062,"author":1063},"/alalande/2023-2/heuristics","Thinking Like a Programmer: Heuristics","We want to help you turbo-charge your decision making.","/alalande/2023-2/img/heuristics.png","2024-03-15",[1049,1050],"content:alalande:2023-2:heuristics.md",{"user":1053,"name":1054},{"_path":1065,"title":1066,"description":1067,"tags":1068,"publishDate":1071,"image":1072,"_id":1073,"author":1074},"/areichert/2023-10/rapid-testing-techniques-for-web-and-mobile","Rapid Testing Techniques for Web & Mobile Apps","Testing rapidly or the need to test quickly under shortened execution cycles is not new. Rapid testing has been around for as long as software testing has existed but increases when a product release is imminent, strained, or behind schedule. There are many reasons development gets behind schedule. Similar to testing, development is prone to surprise requirements changes and increases in scope and complexity.",[1069,1070],"software-testing","qa","2024-06-01","/areichert/2023-10/img/rapid_testing.png","content:areichert:2023-10:Rapid Testing techniques for web and mobile.md",{"user":1075,"name":1076},"areichert","Amy Reichert",{"_path":1078,"title":1079,"description":1080,"image":1081,"publishDate":1082,"tags":1083,"_id":1088,"author":1089},"/asherbrooke/2020-4/watchwah","Bringing an Idea to Life: WatchWah Proof of Concept","\"Wouldn't it be cool if...\"","/asherbrooke/2020-4/img/Guitar_and_Watch.jpeg","2020-04-01",[1084,1085,1086,1087],"ios","apple","watch","juce","content:asherbrooke:2020-4:watchwah.md",{"user":1090,"name":1091},"asherbrooke","Andrew Sherbrooke",{"_path":1093,"title":1094,"description":1095,"publishDate":1096,"tags":1097,"_id":1100,"author":1101},"/avogan/2012-07/salt","What Your Users Don't Know (Part 1)","What's wrong with this code?","2012-07-13",[1098,1099,1049],"cryptography","security","content:avogan:2012-07:salt.md",{"user":1102,"name":1103},"avogan","Andrew Vogan",{"_path":1105,"title":1106,"description":1107,"publishDate":1108,"tags":1109,"_id":1110,"author":1111},"/avogan/2012-07/salt-2","What Your Users Don't Know (Part 2)","In my last post we saw that what your users don't know can hurt them. In other words, how securely you handle your users' private data behind the scenes can have profound implications both for your business and your users' well being. To put it bluntly, it's bad for your business to be publicly shamed over your handling of sensitive data, and it's bad for your users to have their bank accounts pilfered -- those being some of the worse case scenarios.","2012-07-26",[1098,1099,1049],"content:avogan:2012-07:salt-2.md",{"user":1102,"name":1103},{"_path":1113,"title":1114,"description":1115,"publishDate":1116,"image":1117,"_id":1118,"author":1119},"/bporter/2012-5/cd_player","My First CD Player","I started college right about the time when the first CD players were coming onto the market -- there weren't many available, and they were all obscenely expensive. At the time, my dad was dong a lot of traveling to Japan for business, and he was able to bring me a really nice Yamaha CD player back from a shop in Akihabara for about 1/4th of what a similar unit would have cost me here in the US.","2012-05-01","/bporter/2012-5/img/cd_player.jpg","content:bporter:2012-5:cd_player.md",{"user":1120,"name":1121},"bporter","Brett Porter",{"_path":1123,"title":1124,"description":1125,"publishDate":1126,"tags":1127,"image":1130,"_id":1131,"author":1132},"/bporter/2012-5/improtech","ImproTech Paris-New York 2012","Last week, I took a vacation day to attend one day of workshops at NYU as part of ImproTech 2012 Paris-New York That website descibes the event as:","2012-05-24",[1128,1129],"improvisation","music","/bporter/2012-5/img/affichemartin.jpg","content:bporter:2012-5:improtech.md",{"user":1120,"name":1121},{"_path":1134,"title":1135,"description":1136,"publishDate":1137,"tags":1138,"_id":1140,"author":1141},"/bporter/2012-5/learntocode","Yes, Do Learn To Code!","My usual pre-work routine is to walk the dog (working at home, this is my counterpart to a commute), pour my first cup of coffee, and then curl up for a little while with Google Reader. I don't know if it's because I've selected feeds that are too closely aligned with my values and personal agenda, but it's really rare that I'll read a post that is just so wrong that it makes me angry. Jeff Atwood wrote a post like that: Please Don't Learn To Code","2012-05-15",[1139],"learn-to-code","content:bporter:2012-5:learntocode.md",{"user":1120,"name":1121},{"_path":1143,"title":1144,"description":1145,"publishDate":1146,"tags":1147,"image":1151,"_id":1152,"author":1153},"/bporter/2012-6/dsl","Watch Your Language","Interesting to see a theme emerge in my Pinboard account this week -- lots of stuff about the idea of 'programming language'. I've spent the last few weeks preparing to dive back into a personal interactive music project that I've been working on sporadically since I was in graduate school. I had recently realized that the conceptual roadblock I hit before my last hiatus was something that I'd need to address by adding some sort of little programming language into the system. After following Martin Fowler's many blog posts over the years discussing domain specific languages, I finally broke down and bought his book on the topic. It's too early yet for me to have much concrete to say about the book, but I remember getting enough out of those blog posts to be confident that it will be worth the money and time to read.","2012-06-29",[1148,1149,1150],"dsl","erlang","go","/bporter/2012-6/img/dsl.jpg","content:bporter:2012-6:dsl.md",{"user":1120,"name":1121},{"_path":1155,"title":1156,"description":1157,"image":1158,"publishDate":1159,"tags":1160,"_id":1163,"author":1164},"/bporter/2019-3/animator","Friz: A flexible animation controller for JUCE","As is often the case, I found myself working on a personal project and had some UI elements that really wanted to have some life to them on the screen.","/bporter/2019-3/img/animator.png","2019-03-01",[1087,1161,1162],"ui","c++","content:bporter:2019-3:animator.md",{"user":1120,"name":1121},{"_path":1166,"title":1167,"description":1168,"image":1169,"publishDate":1170,"tags":1171,"_id":1174,"author":1175},"/bporter/2019-4/aesannounce","Art+Logic In the Real World","There are a few events coming up in the next few weeks where A+L will have people in attendance. If you're going to be there or nearby, please get in touch and we'll meet up.","/bporter/2019-4/img/aesLogo.jpg","2019-04-01",[1172,1173],"a+l","event","content:bporter:2019-4:aesAnnounce.md",{"user":1120,"name":1121},{"_path":1177,"title":1178,"description":1179,"image":1180,"publishDate":1181,"tags":1182,"_id":1183,"author":1184},"/bporter/2020-10/reanimated","Re-animated","Last year, I posted here about an animation control framework called 'Friz' that works within the JUCE Application Framework.","/bporter/2020-10/img/module.png","2020-10-01",[1087,1161,1162],"content:bporter:2020-10:reanimated.md",{"user":1120,"name":1121},{"_path":1186,"title":1187,"description":1188,"image":1189,"publishDate":1159,"tags":1190,"_id":1191,"author":1192},"/bstevens/2019-3","Coding the Impossible","As you can see on the Art+Logic website, our slogan is Coding the \"impossible.\"®","/bstevens/2019-3/img/impossible.png",[1172],"content:bstevens:2019-3:index.md",{"user":1193,"name":1194},"bstevens","Ben Stevens",{"_path":1196,"title":1197,"description":1198,"publishDate":1199,"tags":1200,"_id":1202,"author":1203},"/ckeefer/2013-1/misc","JS Hints & Shortcuts","During the course of any complex project (and even many simple ones), on the way to accomplish the actual goal, you're certain to encounter any number of small hurdles along the way - little problems which need to be resolved for the bigger picture to come into focus.","2013-09-01",[1201],"js","content:ckeefer:2013-1:misc.md",{"user":1204,"name":1205},"ckeefer","Christopher Keefer",{"_path":1207,"title":1208,"description":1209,"publishDate":1210,"tags":1211,"image":1216,"_id":1217,"author":1218},"/ckeefer/2013-2/xslt","XML and XSLT","Not terribly long ago, XML was the darling of the web. HTML4 was reformulated as XHTML 1.0, SOAP messages were XML, and let us not forget XMLHttpRequest.","2013-10-08",[1212,1213,1214,1215],"data-formats","xml","xsl","xslt","/ckeefer/2013-2/img/xslt-processing.png","content:ckeefer:2013-2:xslt.md",{"user":1204,"name":1205},{"_path":1220,"title":1221,"description":1222,"publishDate":1223,"tags":1224,"image":1227,"_id":1228,"author":1229},"/ckeefer/2013-3/ajax-upload","Ajax Upload Part I: Framed (and jQuery Deferred)","Inevitably, people want their files on the Internet. If your project is about cute cats, someone will task you with allowing users to upload photos of their cats, videos of their cats, long rambling audio clips in which they attempt to convince their cat to stop attacking the microphone, etcetera. If your project is about the nature and proclivities of mold, someone, somewhere will want to share detailed photographic evidence of their mold problem. The need to upload files is a given.","2013-03-20",[1201,1225,1226],"jquery","html5","/ckeefer/2013-3/img/upframe.jpg","content:ckeefer:2013-3:ajax-upload.md",{"user":1204,"name":1205},{"_path":1231,"title":1232,"description":1233,"publishDate":1234,"tags":1235,"_id":1237,"author":1238},"/ckeefer/2013-4/teaching-programming","Can (and Should) Everyone Learn to Program?","Fair warning: The following article is long, rambly, and contains no code. It does, however, contain some rumination on the idea that everyone can and should learn to program.","2013-12-03",[1236],"programming","content:ckeefer:2013-4:teaching-programming.md",{"user":1204,"name":1205},{"_path":1240,"title":1241,"description":1242,"publishDate":1243,"tags":1244,"image":1246,"_id":1247,"author":1248},"/ckeefer/2013-5/ajax-uploader","Ajax Upload XHR2, Take 2","It's a pleasure to be able to interact with files in the browser at long last, isn't it? Reading files in without needing to bounce them against the server first opens up a lot of possibilities - and getting progress from a chunked ajax upload is miles away from the indeterminate form uploads of days past.","2014-02-19",[1225,1201,1245],"xhr2","/ckeefer/2013-5/img/html5.jpg","content:ckeefer:2013-5:ajax-uploader.md",{"user":1204,"name":1205},{"_path":1250,"title":1251,"description":1252,"publishDate":1253,"tags":1254,"_id":1255,"author":1256},"/ckeefer/2013-07/anchors-hash","Anchors, Hash Sign, javascript:void(0)","So, you've got a link that, in reality, is just a click target for performing some javascript function. You want the appearance of a standard anchor link, but if it's not performing the intended function, should it really be an anchor? And if so, what should we fill that 'href' attribute in with?","2013-07-29",[1201],"content:ckeefer:2013-07:anchors-hash.md",{"user":1204,"name":1205},{"_path":1258,"title":1259,"description":1260,"publishDate":1261,"_id":1262,"author":1263},"/ckeefer/2013-07/static-vmware-host","Static Hosting with VMWare","Virtualization is one of the many benefits of the excess (metaphorical) horsepower available to us with modern hardware. Need to test against (Windows XP/7/8/NT || Fedora || Mint || Ubuntu || FreeBSD || MacOSX || etc)? Fire up the VM. Need a Linux environment for the packages your server relies on, but need to test in the iPad simulator? VM's to the rescue.","2013-07-26","content:ckeefer:2013-07:static-vmware-host.md",{"user":1204,"name":1205},{"_path":1265,"title":1266,"description":1267,"publishDate":1268,"tags":1269,"_id":1271,"author":1272},"/ckeefer/2013-08/fullproof-fulltext-search","Client-side Fulltext Searching with Fullproof","Recently, I was engaged in a genial argument with a friend of an older generation, each of us taking an opposing stance on some obscure trivia neither of us was entirely certain about - but which we were both ready to defend with all the wit and rhetoric at our disposal. When we had finally exhausted all attempts to make the other budge on the matter, we turned to an authoritative 3rd-party source to lay the matter to rest for us - a Google search.","2013-08-29",[1270,1215],"search","content:ckeefer:2013-08:fullproof-fulltext-search.md",{"user":1204,"name":1205},{"_path":1274,"title":1275,"description":1276,"publishDate":1277,"tags":1278,"_id":1279,"author":1280},"/ckeefer/2013-11/jquery-ajax-blobs","jQuery Ajax Blobs and Array Buffers","A big part of what makes jQuery a regular part of so many web projects is the clean interface it offers us for a number of sometimes messy built-in aspects of javascript. The most obvious is the DOM interface; and in second place, jquery ajax and its various shorthand methods. Abstracting away the difference between ActiveXObject and XMLHttpRequest is one of the most obvious benefits - but even if you don't need to worry about supporting old versions of IE, you might well enjoy the clean, object-based, promise-returning interface that jquery ajax offers.","2013-11-21",[1201,1225],"content:ckeefer:2013-11:jquery-ajax-blobs.md",{"user":1204,"name":1205},{"_path":1282,"title":1283,"description":1284,"publishDate":1285,"tags":1286,"_id":1288,"author":1289},"/ckeefer/2013-12/deploying-with-git","Deploying Websites with Git","Deploying your webapp is an important part of the web development equation - your client's site isn't going to attract a lot of attention sitting in your local dev directory. Deployment concerns tend to fall to the bottom of the priority list, though, and the end result tends to be kludgy, hastily thrown-together deployment scripts; and because they are so kludgy and, often, time consuming, when time crunches threaten, a developer may resort to making changes directly on the remote server that need to be (but sometimes never are) backported to the code living in your version control.","2013-12-23",[1287],"git","content:ckeefer:2013-12:deploying-with-git.md",{"user":1204,"name":1205},{"_path":1291,"title":1292,"description":1293,"publishDate":1294,"tags":1295,"image":1297,"_id":1298,"author":1299},"/ckeefer/2014-1/still-using-php","Still Using PHP?","Poor PHP. It's so lonely and unloved these days.","2014-01-29",[1296],"php","/ckeefer/2014-1/img/php.jpg","content:ckeefer:2014-1:still-using-php.md",{"user":1204,"name":1205},{"_path":1301,"title":1302,"description":1303,"publishDate":1304,"tags":1305,"image":1307,"_id":1308,"author":1309},"/ckeefer/2014-2/ajax-upload-2","Ajax Upload Part II: XHR2 (and FileReader)","So, the client has told you their users should be able to upload their drunken party pictures for all the internet to see. \"We want the very best experience possible,\" they tell you. \"Simple, seamless - maybe using that new html5 thing I've heard so much about.\"","2013-04-09",[1201,1306],"xmlhttprequest","/ckeefer/2014-2/img/html5.jpg","content:ckeefer:2014-2:ajax-upload-2.md",{"user":1204,"name":1205},{"_path":1311,"title":1312,"description":1313,"publishDate":1314,"tags":1315,"_id":1317,"author":1318},"/ckeefer/2014-3/customgmapsinfowindow","Custom Google Maps Info Windows","When it comes time to relate the ephemeral world of data to the physical world, Maps are key in both enterprise and consumer applications. Whatever else you might think of it, Google Maps tends to be the default option - certainly, its the only one I've ever had clients ask for by name.","2014-02-26",[1201,1316],"google-maps","content:ckeefer:2014-3:customgmapsinfowindow.md",{"user":1204,"name":1205},{"_path":1320,"title":1321,"description":1322,"publishDate":1323,"tags":1324,"_id":1326,"author":1327},"/ckeefer/2014-4/hidden-options","Hidden Options: A Workaround","Here's the situation: You've got a select. Maybe a whole bunch of selects, with a ton of options each (metric ton - let's keep our imaginary hyperbolic units straight here); and these are meant to be complex interactive elements, with options made visible or not as some programmatic condition dictates.","2014-04-23",[1325,1201,1225],"how-to","content:ckeefer:2014-4:hidden-options.md",{"user":1204,"name":1205},{"_path":1329,"title":1330,"description":1331,"publishDate":1332,"tags":1333,"_id":1334,"author":1335},"/ckeefer/2014-5/cgwin2","Custom Google Info Windows: Updated, Live","April 30, 2014 at 3:22 am Remy says:","2014-05-09",[1201,1316],"content:ckeefer:2014-5:cgwin2.md",{"user":1204,"name":1205},{"_path":1337,"title":1338,"description":1339,"publishDate":1340,"tags":1341,"image":1344,"_id":1345,"author":1346},"/ckeefer/2014-6/backbonesocketsync","Websockets for Backbone","Backbone's had some of its thunder stolen lately by trendier frameworks like Meteor and Angular; for good reason, in most cases, as without the prosthetic functionality offered by the likes of Marionette, Backbone's view handling (amongst a few other lacks and warts) is really just 'roughed in'.","2014-06-25",[1201,1342,1343],"websockets","backbone","/ckeefer/2014-6/img/WebsocketsPlusBackbone.png","content:ckeefer:2014-6:backbonesocketsync.md",{"user":1204,"name":1205},{"_path":1348,"title":1349,"description":1350,"publishDate":1351,"tags":1352,"_id":1353,"author":1354},"/ckeefer/2014-7/promises","It's a (jQuery-style) Promise","Way back when I brought up the topic of promises (particularly, jQuery Deferred), and I promised we would come back to the topic someday.","2014-10-16",[1201,1225],"content:ckeefer:2014-7:promises.md",{"user":1204,"name":1205},{"_path":1356,"title":1357,"description":1358,"publishDate":1359,"tags":1360,"_id":1361,"author":1362},"/ckeefer/2014-8/behold-views","Behold! (JavaScript Views)","JavaScript has the propensity to be very untidy - if you let it, it will sprawl all over the place. Hundreds of global variables scattered across dozens of files, messy half-measures towards object-orientation, mixed in seemingly at random with ungrouped functions - anyone who's had a client bring them a failed project from some other development team knows just how bad it can get.","2015-01-07",[1201],"content:ckeefer:2014-8:behold-views.md",{"user":1204,"name":1205},{"_path":1364,"title":1365,"description":1366,"publishDate":1367,"tags":1368,"image":1369,"_id":1370,"author":1371},"/ckeefer/2015-1/writeonce","Write Once, Debug Everywhere","It's pretty seldom that anyone mentions web pages these days, other than in historical reference to days long gone by (yes, a whole few years ago). Web sites, sure, but not if what is really wanted is to replace something that, not so long ago, would have been some native code for a smartphone (or a little further back still, a desktop computer). Generally speaking, the most common term tripping from client's lips these days is 'web applications' - or webapps, because who has time for spaces and proper spelling, amirite?","2015-02-02",[1201],"/ckeefer/2015-1/img/html5java.jpg","content:ckeefer:2015-1:writeonce.md",{"user":1204,"name":1205},{"_path":1373,"title":1374,"description":1375,"publishDate":1376,"tags":1377,"_id":1378,"author":1379},"/ckeefer/2015-2/js-frameworks","The What and Why of Javascript Frameworks","JavaScript has the propensity to be very untidy if you let it be. This isn't a problem unique to JavaScript, of course - many other languages suffer from a lack of native organization, especially for specific tasks.","2015-05-29",[1201],"content:ckeefer:2015-2:js-frameworks.md",{"user":1204,"name":1205},{"_path":1381,"title":1382,"description":1383,"publishDate":1384,"tags":1385,"_id":1388,"author":1389},"/ckeefer/2015-3/emailvalidation","Email Validation with Django and python-social-auth","When it comes to user accounts, the standard litmus test is email validation. Besides the immediate benefits - of offering us a straightforward unique identifier for users, and making it more difficult to automate creating a mass of accounts on our service - by requiring that each account have an email address and interact therewith to confirm the addresses validity, it also offers us the chance to associate a known-working email account with a user account. This is important for transactional emails such as password resets or for potential two-factor authentication use... and if you're a little less ethical, for sending marketing desirable and informative emails about interesting products and services.","2015-07-23",[1386,1387],"python","django","content:ckeefer:2015-3:EmailValidation.md",{"user":1204,"name":1205},{"_path":1391,"title":1392,"description":1393,"publishDate":1394,"tags":1395,"_id":1396,"author":1397},"/ckeefer/2015-5/file-reader-chunking","FileReader Chunking and Base64 DataURLs","In a hurry? You can now use our HUp jquery plugin to read files in a chunked fashion as data URLs. Hooray!","2015-12-15",[1201,1225],"content:ckeefer:2015-5:file-reader-chunking.md",{"user":1204,"name":1205},{"_path":1399,"title":1400,"description":1401,"publishDate":1402,"tags":1403,"_id":1404,"author":1405},"/ckeefer/2016-1/ajaxbinarycaching","Caching Binary Data With jQuery Ajax and IndexedDB","After long, grueling months (years? or does it only feel like years?), your web application nears completion. It is tightly coded, well documented, works across all modern browsers, and is well received by your beta testers. It's nearly time to go live, and a smile of pure relief plays upon your lips... and freezes into a rictus grin when your client turns to you, and asks, \"so, hey, can we speed up the dynamic cat pic loading? Especially when I close the browser and come back to it later. I think that's really key to the whole application.\"","2016-04-25",[1201,1225],"content:ckeefer:2016-1:ajaxBinaryCaching.md",{"user":1204,"name":1205},{"_path":1407,"title":1408,"description":1409,"publishDate":1410,"tags":1411,"_id":1412,"author":1413},"/ckeefer/2016-2/paymentprocessing","Payment Processing with Braintree","You've built the web application of the century, and the users have rightly flooded to it. Cat pictures for everyone!","2016-05-11",[1387,1201,1225,1386],"content:ckeefer:2016-2:paymentprocessing.md",{"user":1204,"name":1205},{"_path":1415,"title":1416,"description":1417,"publishDate":1418,"tags":1419,"_id":1420,"author":1421},"/ckeefer/2016-3/djangochannels1","Django Channels: From the Ground Up - Part 1","You stare mournfully into the mass of code you've inherited. At some point, it's clear, the requirements called for the server to push information to the client, because there's an unholy mix of Server-Side Events, long-polling, hidden iframes and even a Java applet in there, all supporting some level of long-term connectivity with the server. It's almost fascinating in its barely functional hideousness, and you would be inclined to leave well enough alone... except for the new feature specifications you've been assigned, which require the client to be able to send data back to the server in response to the received events, in as close to real-time as you can get.","2016-06-13",[1387,1386,1342],"content:ckeefer:2016-3:djangoChannels1.md",{"user":1204,"name":1205},{"_path":1423,"title":1424,"description":1425,"publishDate":1426,"tags":1427,"_id":1428,"author":1429},"/ckeefer/2016-4/djangochannels2","Django Channels: From the Ground Up - Part 2","Last time, we decided to embark on a brave new adventure and give our Django framework a big upgrade with the inclusion of Django Channels. We got just far enough to get the development server running, but while this may be an adequate start, it's better to develop against something like what we intend to deploy, right?","2016-06-15",[1387,1386,1342],"content:ckeefer:2016-4:djangochannels2.md",{"user":1204,"name":1205},{"_path":1431,"title":1432,"description":1433,"publishDate":1434,"tags":1435,"_id":1436,"author":1437},"/ckeefer/2016-6/gofetch1","Go Fetch! (JavaScript Fetch API)","Long ago, we briefly brushed upon the topic of what has made jQuery such a valuable part of the web developer's toolset for such a long time - namely, a cleaner interface for interacting with the DOM, and the $.ajax abstraction over XMLHttpRequest.","2016-10-03",[1201,1225,1049],"content:ckeefer:2016-6:goFetch1.md",{"user":1204,"name":1205},{"_path":1439,"title":1440,"description":1441,"publishDate":1442,"tags":1443,"_id":1444,"author":1445},"/ckeefer/2016-7/gofetch2","Go Fetch 2! (JavaScript Fetch API)","Last time we discussed the Fetch API in general, taking a look at how it differed from the XMLHttpRequest API, and some of its advantages. Today, we're going to take a look at a little library that you can include in your projects today that offers you localStorage caching for the Fetch API.","2016-10-10",[1201,1225,1049],"content:ckeefer:2016-7:goFetch2.md",{"user":1204,"name":1205},{"_path":1447,"title":1448,"description":1449,"publishDate":1450,"tags":1451,"_id":1454,"author":1455},"/ckeefer/2016-8/herokupdf","Generating PDFs: wkhtmltopdf & Heroku","So, it has come to this.","2016-12-21",[1452,1453,1386],"heroku","pdf","content:ckeefer:2016-8:HerokuPDF.md",{"user":1204,"name":1205},{"_path":1457,"title":1458,"description":1459,"publishDate":1460,"tags":1461,"_id":1462,"author":1463},"/ckeefer/2017-1/downloadingclientsidecontent","Downloading Client-side Generated Content","A young developer, new to the Tao of the client-side, comes to a Master of the way, and speaks thusly: \"Oh Master, our application nears completion; and lo, cat pics can be drawn upon, and captions fixated thereto, for the creation of humour and the bounteous enjoyment of our users.\"","2017-02-06",[1201],"content:ckeefer:2017-1:downloadingclientsidecontent.md",{"user":1204,"name":1205},{"_path":1465,"title":1466,"description":1467,"publishDate":1468,"tags":1469,"_id":1472,"author":1473},"/ckeefer/2017-2/morepwatoya-part1","More PWA to Ya! (Progressive Web Apps, Part 1)","It's project kickoff time, and you're having a conversation with your client about what form the application will take:","2017-02-01",[1470,1471,1049],"pwa","mobile","content:ckeefer:2017-2:MorePWAToYa-Part1.md",{"user":1204,"name":1205},{"_path":1475,"title":1476,"description":1477,"tags":1478,"publishDate":1479,"_id":1480,"author":1481},"/ckeefer/2017-3/morepwatoya-part2","More PWA to Ya! (Progressive Web Apps, Part 2)","Last time, we got into the nitty gritty on how to make your web application into a Progressive Web Application (PWA to it's friends). I promised we'd dig even deeper this time, and show you how to make your web app a little more 'native' on Android - and how to deal with iOS Safari's special snowflake syndrome.",[1471,1470,1049],"2017-03-01","content:ckeefer:2017-3:MorePWAToYa-Part2.md",{"user":1204,"name":1205},{"_path":1483,"title":1484,"description":1485,"image":1486,"publishDate":1487,"tags":1488,"_id":1490,"author":1491},"/ckeefer/2019-1/unlockingwebaudio","Unlocking Web Audio","\"It's going to be the coolest thing ever.\"","/ckeefer/2019-1/img/featured_image.jpg","2019-01-01",[1201,1489],"audio","content:ckeefer:2019-1:UnlockingWebAudio.md",{"user":1204,"name":1205},{"_path":1493,"title":1494,"description":1495,"publishDate":1496,"image":1497,"tags":1498,"_id":1500,"author":1501},"/ckeefer/2020-1/why-vue","Why Vue","Why choose Vue over any other front-end framework?","2020-01-01","/ckeefer/2020-1/img/vue-wall.jpg",[1201,1499],"vue","content:ckeefer:2020-1:Why Vue.md",{"user":1204,"name":1205},{"_path":1503,"title":1504,"description":1505,"tags":1506,"image":1509,"publishDate":1510,"_id":1511,"author":1512},"/ckeefer/2024-3/e2e_testing","E2E Testing: To What End?","Friend, can we agree that tests are a good idea? I won't scorn you for sometimes omitting them - time and budget constraints are what they are, and even the best intentioned of us sometimes have to just give our projects a lick and a promise. \"Proper test coverage soon\", you sweetly croon as you rock it to sleep, the knowledge that you're telling a dark, terrible lie twisting you up inside. Maybe you could just scrape enough budget together for some simple unit tests? Then, at least, you'd have \"tests\", right?",[1070,1069,1507,1508],"e2e","playwright","/ckeefer/2024-3/img/E2E_Testing_2024.png","2024-06-15","content:ckeefer:2024-3:e2e_testing.md",{"user":1204,"name":1205},{"_path":1514,"title":1515,"description":1516,"tags":1517,"image":1519,"publishDate":1520,"_id":1521,"author":1522},"/ckeefer/2024-7/vpubsub","Vue 3 Pub / Sub: All aboard the (event) bus","We like Vue at A+L. We think it's one of the best frontend frameworks, and a great choice pretty much anywhere you might otherwise be tempted to use React.",[1201,1499,1518],"pub/sub","/ckeefer/2024-7/img/event_bus.png","2024-08-15","content:ckeefer:2024-7:VPubSub.md",{"user":1204,"name":1205},{"_path":1524,"title":1525,"description":1526,"publishDate":1527,"tags":1528,"_id":1529,"author":1530},"/cmacksey/2012-5/php-musings","PHP Musings","Ran into an interesting, but thorough, rant the other day - PHP: A Fractal of Bad Design. The part that grabbed me the most was the analogy at the beginning, which was all too perfect:","2012-05-07",[1296],"content:cmacksey:2012-5:php-musings.md",{"user":1531,"name":1532},"cmacksey","Chris Macksey",{"_path":1534,"title":1535,"description":1536,"publishDate":1537,"image":1538,"author":1539,"tags":1542,"_id":1548},"/cperez/2026-06-17/xamarin-to-maui","Migrating a Xamarin Medical Application to .NET MAUI","A widely used medical reference application built with Xamarin had become increasingly difficult to maintain as platform support deadlines approached. The client needed to modernize the application before operating system changes and framework deprecations created larger compatibility risks.","2026-06-22","/cperez/2026-06-17/img/xamarin-to-maui.png",{"name":1540,"user":1541},"Carlos Perez","cperez",[1543,1544,1545,1546,1547,1471],"legacy modernization","xamarin",".net","maui","app migration","content:cperez:2026-06-17:xamarin-to-maui.md",{"_path":1550,"title":1551,"description":1552,"publishDate":1553,"image":1554,"author":1555,"tags":1556,"_id":1559},"/cperez/2026-06-25/ai_makes_modernization_feasible","How AI-Assisted Legacy Modernization Reduces Cost, Risk, and Project Timelines","Many organizations know they need to modernize their legacy applications. They also know why they haven't.","2026-06-25","/cperez/2026-06-25/img/ai_makes_modernization_feasible.png",{"name":1540,"user":1541},[1543,1557,17,1558],"tech debt","legacy migration","content:cperez:2026-06-25:ai_makes_modernization_feasible.md",{"_path":1561,"title":1562,"description":1563,"publishDate":1564,"image":1565,"author":1566,"tags":1567,"_id":1570},"/cperez/2026-06-30/how-ceos-should-evaluate-ai-investments","How Should CEOs Evaluate AI Investments?","CEOs should evaluate AI investments by asking whether the investment improves a measurable business outcome, changes a real workflow, keeps humans appropriately involved, has a realistic path to production, and creates value that outweighs cost and risk.","2026-06-30","/cperez/2026-06-30/img/how-ceos-should-evaluate-ai-investments.jpg",{"name":1540,"user":1541},[18,1568,20,17,1569],"ai investment","software development","content:cperez:2026-06-30:how-ceos-should-evaluate-ai-investments.md",{"_path":1572,"title":1573,"description":1574,"publishDate":1575,"image":1576,"author":1577,"tags":1578,"_id":1580},"/cperez/2026-07-02/hidden-costs-of-legacy-software","What Are the Hidden Costs of Legacy Software?","Legacy software is rarely “bad” software.","2026-07-02","/cperez/2026-07-02/img/hidden-costs-of-legacy-software.jpg",{"name":1540,"user":1541},[1543,1579],"legacy software","content:cperez:2026-07-02:hidden-costs-of-legacy-software.md",{"_path":1582,"title":1583,"description":1584,"publishDate":1585,"image":1586,"author":1587,"tags":1588,"_id":1591},"/cperez/2026-07-07/why-ai-projects-fail","Why Do Most AI Projects Fail?","AI projects rarely fail because the model was not powerful enough.","2026-07-07","/cperez/2026-07-07/img/why-ai-projects-fail.jpg",{"name":1540,"user":1541},[17,1589,1569,1590],"ethics","vibe coding","content:cperez:2026-07-07:why-ai-projects-fail.md",{"_path":1593,"title":1594,"description":1595,"publishDate":1596,"image":1597,"author":1598,"tags":1599,"_id":1603},"/cperez/2026-07-09/5-rs-application-modernization-legacy-software","Art+Logic’s 5 Rs of Application Modernization: How to Choose the Right Path for Legacy Software","Legacy software creates a strange kind of tension.","2026-07-09","/cperez/2026-07-09/img/5-rs-application-modernization-legacy-software.jpg",{"name":1540,"user":1541},[1600,1601,17,1602],"5-rs","legacy","application modernization","content:cperez:2026-07-09:5-rs-application-modernization-legacy-software.md",{"_path":1605,"title":1606,"description":1607,"publishDate":1608,"image":1609,"author":1610,"tags":1611,"_id":1613},"/cperez/2026-07-16/rebuild-vs-modernize-software-cfo-guide","Rebuild or Modernize? A Guide to Making the Right Software Investment","Every aging software system eventually reaches a financial decision point.","2026-07-16","/cperez/2026-07-16/img/rebuild-vs-modernize-software-cfo-guide.jpg",{"name":1540,"user":1541},[1612,1558,1557,1602,1579],"modernization","content:cperez:2026-07-16:rebuild-vs-modernize-software-cfo-guide.md",{"_path":1615,"title":1616,"description":1617,"publishDate":1618,"image":1619,"author":1620,"tags":1621,"_id":1626},"/cperez/2026-07-21/building-digital-health-platforms-beyond-samd","Beyond SaMD: Building a Digital Health Platform That Can Evolve","A medical application can work exactly as designed and still fall short of what the organization needs next.","2026-07-21","/cperez/2026-07-21/img/building-digital-health-platforms-beyond-samd.jpg",{"name":1540,"user":1541},[1622,1601,1612,1623,1624,1544,1625],"samd","biomedical","healthcare",".net maui","content:cperez:2026-07-21:building-digital-health-platforms-beyond-samd.md",{"_path":1628,"title":1629,"description":1630,"publishDate":1631,"image":1632,"author":1633,"tags":1634,"_id":1638},"/cperez/2026-07-23/why-ai-agents-need-software-developers","Beyond the Chatbot: Your AI Agent Is a Software Product, Not a Prompt","The AI-agent demo usually looks simple.","2026-07-23","/cperez/2026-07-23/img/why-ai-agents-need-software-developers.jpg",{"name":1540,"user":1541},[17,20,1568,1635,18,1636,1099,1637],"chatbots","ai agents","ai development","content:cperez:2026-07-23:why-ai-agents-need-software-developers.md",{"_path":1640,"title":1641,"description":1642,"publishDate":1643,"image":1644,"author":1645,"tags":1646,"_id":1648},"/cperez/2026-07-28/ai-assisted-legacy-modernization-business-logic","AI-Assisted Legacy Modernization: How to Move Faster Without Losing the Business Logic","AI can translate your Legacy Code. Can it preserve what your business actually depends on?","2026-07-28","/cperez/2026-07-28/img/ai-assisted-legacy-modernization-business-logic.jpg",{"name":1540,"user":1541},[1543,1602,1647,1557],"code migration","content:cperez:2026-07-28:ai-assisted-legacy-modernization-business-logic.md",{"_path":1650,"title":1651,"description":1652,"publishDate":1653,"image":1654,"author":1655,"tags":1656,"_id":1657},"/cperez/2026-08-04/technical-debt-enterprise-value","Technical Debt and Enterprise Value: What Your Software Is Really Costing the Business","Technical debt rarely announces itself as a financial problem.","2026-08-04","/cperez/2026-08-04/img/technical-debt-enterprise-value.jpg",{"name":1540,"user":1541},[1557,1543,1558],"content:cperez:2026-08-04:technical-debt-enterprise-value.md",{"_path":1659,"title":1660,"description":1661,"publishDate":1662,"image":1663,"author":1664,"tags":1665,"_id":1668},"/cperez/2026-08-06/turnover-reveals-weak-software-architecture","Can Employee Turnover Reveal Weak Software Architecture?","When an engineer leaves, the initial plan usually feels manageable: someone else will step in, spend a few days getting up to speed, and keep the roadmap moving forward. However, this is often the moment when the questions begin. Suddenly, the team finds themselves wondering why changing a simple field breaks the reporting process, or which service is actually responsible for a specific calculation. They might encounter a dependency that everyone is afraid to touch or find that the application behaves unpredictably in production without any clear explanation.","2026-08-06","/cperez/2026-08-06/img/turnover-reveals-weak-software-architecture.png",{"name":1540,"user":1541},[1666,1543,1667],"engineering turnover","software architecture","content:cperez:2026-08-06:turnover-reveals-weak-software-architecture.md",{"_path":1670,"title":1671,"description":1672,"publishDate":1673,"image":1674,"author":1675,"tags":1676,"_id":1683},"/cperez/2026-08-11/ai-prototype-to-production-business-results","Your AI Prototype Is Finished. The Software Project Isn’t.","The demonstration went well. The application accepted a request, generated the right response, and completed a task that normally takes someone much longer, so everyone left the meeting impressed.","2026-08-11","/cperez/2026-08-11/img/ai-prototype-to-production-business-results.jpg",{"name":1540,"user":1541},[1677,1678,1679,1680,1681,1682],"ai software development","software rescue","vibe-coded application rescue","ai prototype development","ai application modernization","custom ai software development","content:cperez:2026-08-11:ai-prototype-to-production-business-results.md",{"_path":1685,"title":1686,"description":1687,"publishDate":1688,"image":1689,"author":1690,"tags":1691,"_id":1693},"/cperez/2026-08-18/legacy-software-holding-business-back","Is Your Legacy Software Holding the Business Back?","The software still works, which is usually the first argument for leaving it alone.","2026-08-18","/cperez/2026-08-18/img/legacy-software-holding-business-back.jpg",{"name":1540,"user":1541},[1543,17,1692,1558],"ai-assisted modernization","content:cperez:2026-08-18:legacy-software-holding-business-back.md",{"_path":1695,"title":1696,"description":1697,"publishDate":1698,"image":1699,"author":1700,"tags":1701,"_id":1703},"/cperez/2026-08-20/ai-code-review-verifying-generated-software","AI Can Write the Code. Who Verifies It?","AI Code Review: Who Verifies AI-Generated Software?","2026-08-20","/cperez/2026-08-20/img/ai-code-review-verifying-generated-software.jpg",{"name":1540,"user":1541},[1702,1677,1590,20],"ai code review","content:cperez:2026-08-20:ai-code-review-verifying-generated-software.md",{"_path":1705,"title":1706,"description":1707,"publishDate":1708,"image":1709,"author":1710,"tags":1711,"_id":1717},"/cperez/2026-08-27/ai-software-requirements-grounded-in-context","AI Can Draft Software Requirements. Can It Understand Your System?","AI is very good at making a software idea sound more complete than it really is.","2026-08-27","/cperez/2026-08-27/img/ai-software-requirements-grounded-in-context.jpg",{"name":1540,"user":1541},[1712,17,1713,1714,1715,1716],"ai requirements gathering","ai discovery","ai hallucinations","legacy software modernization","legacy software discovery","content:cperez:2026-08-27:ai-software-requirements-grounded-in-context.md",{"_path":1719,"title":1720,"description":1721,"publishDate":1722,"image":1723,"author":1724,"tags":1725,"_id":1727},"/cperez/2026-09-01/what-happens-if-you-keep-running-xamarin-app","What Happens If We Keep Running a Xamarin App?","If your Xamarin app still works, it is reasonable to wonder why you need to migrate it at all.","2026-09-01","/cperez/2026-09-01/img/what-happens-if-you-keep-running-xamarin-app.jpg",{"name":1540,"user":1541},[1544,1543,1726],"technical debt","content:cperez:2026-09-01:what-happens-if-you-keep-running-xamarin-app.md",{"_path":1729,"title":1730,"description":1731,"publishDate":1732,"image":1733,"author":1734,"tags":1735,"_id":1736},"/cperez/2026-09-03/xamarin-to-dotnet-maui-migration-what-changes","Xamarin to .NET MAUI Migration: What Actually Has to Change?","If you have a Xamarin.Forms application that needs to move to .NET MAUI, the word migration can make the project sound like a complete rewrite.","2026-09-3","/cperez/2026-09-03/img/xamarin-to-dotnet-maui-migration-what-changes.jpg",{"name":1540,"user":1541},[1544,1625,1558,1543],"content:cperez:2026-09-03:xamarin-to-dotnet-maui-migration-what-changes.md",{"_path":1738,"title":1739,"description":1740,"publishDate":1741,"image":1742,"author":1743,"tags":1744,"_id":1746},"/cperez/2026-09-08/original-developers-gone-custom-software-takeover","The Original Developers Are Gone. What Happens to Your Custom Software Now?","The developers who built your custom software are gone. Maybe an internal team turned over, a longtime contractor retired, or the agency responsible for the application is no longer available. The software may still be running, but the people who understood its architecture, deployment process, hidden business rules, and accumulated quirks are no longer there to answer questions.","2026-09-08","/cperez/2026-09-08/img/original-developers-gone-custom-software-takeover.jpg",{"name":1540,"user":1541},[1543,17,1745,1579],"discovery","content:cperez:2026-09-08:original-developers-gone-custom-software-takeover.md",{"_path":1748,"title":1749,"description":1750,"publishDate":1751,"image":1752,"author":1753,"tags":1754,"_id":1758},"/cperez/2026-09-10/legacy-desktop-application-modernization-partner","How to Evaluate a Legacy Desktop Application Modernization Partner: 6 Factors for Mid-Market Teams","For mid-market product teams, legacy application modernization can be a hard to get right. Your desktop application may still run critical workflows, connect to specialized hardware, or encode years of business logic. But the technology underneath it is aging, dependencies are becoming harder to maintain, and every new feature takes more effort than it should.","2026-09-10","/cperez/2026-09-10/img/legacy-desktop-application-modernization-partner.jpg",{"name":1540,"user":1541},[1755,1756,1543,1757],"legacy desktop migration","ai-assisted migration","mid-market","content:cperez:2026-09-10:legacy-desktop-application-modernization-partner.md",{"_path":1760,"title":1761,"description":1762,"publishDate":1763,"tags":1764,"_id":1766,"author":1767},"/dpopowich/2021-07-30/data-collector","Asynchronous Python - A Real World Example","A dive into a real example of async Python usage.","2021-07-30",[1386,1325,1765],"async","content:dpopowich:2021-07-30:data-collector.md",{"user":1768,"name":1769},"dpopowich","Daniel Popowich",{"_path":1771,"title":1772,"description":1773,"tags":1774,"image":1776,"publishDate":1777,"_id":1778,"author":1779},"/dpopowich/2023-8/postgres-pubsub","Using PostgreSQL for Pub/Sub","A+L has been working on a Single Page Application (SPA) wherein our client's users take on the role of Staff Users (think: project managers) as they aid their Customer Users in using the application to complete a complex project.",[1775,1386,1765],"postgresql","/dpopowich/2023-8/img/psql_pub_sub.png","2024-04-15","content:dpopowich:2023-8:postgres-pubsub.md",{"user":1768,"name":1769},{"_path":1781,"title":1782,"description":1783,"tags":1784,"image":1787,"publishDate":1788,"_id":1789,"author":1790},"/ewahl/2025-05/escape_deployment_hell","Escape Deployment Hell: IaC, CDK, Ephemeral Environments, and the Pragmatic Path to Platform Power","Another Friday afternoon, another deployment fire. If this sounds familiar, you're not alone. On too many projects, the chasm between application code and infrastructure management breeds manual configuration nightmares, crippling complexity, and agonizingly slow development cycles. But what if your team could sidestep this chaos, focusing on building features instead of constantly battling deployment gremlins?",[1785,1786,1386],"devops","aws","/ewahl/2025-05/img/deployment_hell.png","2025-05-13","content:ewahl:2025-05:escape_deployment_hell.md",{"user":15,"name":14},{"_path":1792,"title":1793,"description":1794,"publishDate":1795,"image":1796,"tags":1797,"_id":1798,"author":1799},"/ewahl/2025-06/argued_with_ai","I Argued With an AI for 20 Minutes About Async Code &mdash; And I'm Surprisingly Happy","If you have ever spent twenty minutes debating an obscure AWS Lambda invocation pattern with an AI, you might question your life choices. But here I am: amused by the wasted time but ultimately happy with the outcome and understanding I gained.","2026-06-01","/ewahl/2025-06/img/argued_with_ai.png",[1785,1786,1386],"content:ewahl:2025-06:argued_with_ai.md",{"user":15,"name":14},{"_path":1801,"title":1802,"description":1803,"publishDate":1804,"image":1805,"author":1806,"tags":1807,"_id":1809},"/ewahl/2026-07/goodharts-law-ai-coding-agents","Why AI Coding Agents Still Need Human Experts","An AI coding agent quietly steered my protected test suite away from a money bug — the same failure mode that forced OpenAI to retire SWE-bench Verified. Goodhart's Law explains why, and why the demand for senior engineers goes up, not down, as agents improve.","2026-07-30","/ewahl/2026-07/img/goodharts-law-ai-coding-agents.jpg",{"name":14,"user":15},[17,18,1808],"human in the loop","content:ewahl:2026-07:goodharts-law-ai-coding-agents.md",{"_path":5,"title":9,"description":10,"publishDate":11,"image":12,"author":1811,"tags":1812,"_id":1036},{"name":14,"user":15},[17,18,19,20,21,22],{"_path":1814,"title":1815,"description":1816,"tags":1817,"image":1818,"publishDate":1170,"_id":1819,"author":1820},"/jbagley/2019-4/makingspectrogramsinjuce","Making Spectrograms in JUCE","Art+Logic's Incubator project has made a lot of progress. In a previous post I mentioned that Dr. Scott Hawley's technique to classify audio involved converting audio to an image and using a Convolution Neural Network (CNN) to classify the audio based on this image. That image is a spectrogram. I'm going to go into some detail about what we do to create one, and why to the best of my ability.",[1087,1162,1489],"/jbagley/2019-4/img/Fortissimo_Trumpet_Ensemble_Matrix_Swells_61.wav-2048x1700.png","content:jbagley:2019-4:MakingSpectrogramsInJUCE.md",{"user":1821,"name":1822},"jbagley","Jason Bagley",{"_path":1824,"title":1825,"description":1826,"tags":1827,"image":1829,"publishDate":1830,"_id":1831,"author":1832},"/jbagley/2021-07/softwaresenescence","Legacy Vulnerabilities AKA Software Senescence","Does your business still have an XT computer in the back office because it's\nrunning that one version of some database software that your business depends\non? Yeah, we know there is. Most modern software doesn't work like that.",[1601,1828],"project-management","/jbagley/2021-07/img/old_software_to_new.jpg","2021-07-01","content:jbagley:2021-07:SoftwareSenescence.md",{"user":1821,"name":1822},{"_path":1834,"title":1835,"description":1836,"tags":1837,"image":1839,"publishDate":1840,"_id":1841,"author":1842},"/jbagley/2021-08-01/accuratetiming","Accurate Timing","In many tasks we need to do something at given intervals of time. The most obvious ways may not give you the best results.",[1162,1838],"timing","/jbagley/2021-08-01/img/accurateTiming.jpg","2021-08-01","content:jbagley:2021-08-01:AccurateTiming.md",{"user":1821,"name":1822},{"_path":1844,"title":1845,"description":1846,"tags":1847,"image":1851,"publishDate":1852,"_id":1853,"author":1854},"/jbagley/2023-06-01/universal_ffmpeg_custom_builds","Building Universal FFmpeg Custom Binaries","I am using a very pared down set of FFMpeg features for a macOS project that I\nbuild into a custom library. I had a script set up to configure the build which\nworked fine on my Intel based MacBook Pro. Then I upgraded to an Apple Silicon\nMacBookPro and wanted to run natively, or at least see what happened when I\ndid. To build, FFMpeg uses autoconf which produces a makefile that then handles\nthe build.",[1848,1849,1850,1085],"c","bash","ffmpeg","/jbagley/2023-06-01/img/header.png","2024-04-01","content:jbagley:2023-06-01:Universal_FFMPEG_custom_builds.md",{"user":1821,"name":1822},{"_path":1856,"title":1857,"description":1858,"publishDate":1859,"image":1860,"tags":1861,"_id":1865,"author":1866},"/jbagley/2025-08/a_developers_primer_on_apple_tracking_transparency","A Primer on Apple's App Tracking Transparency","If an app tracks user activity, Apple requires them to declare all information they collect as well as whether that data is linked or tracked. This includes collection by the app itself and any third parties the app uses. The app owner is responsible for knowing and correctly reporting privacy information for all components in the app.","2026-05-22","/jbagley/2025-08/img/apple_app_transparency.png",[1862,1863,1084,1864],"app tracking transparency","att","macos","content:jbagley:2025-08:a_developers_primer_on_apple_tracking_transparency.md",{"user":1821,"name":1822},{"_path":1868,"title":1869,"description":1870,"tags":1871,"image":1875,"publishDate":1876,"_id":1877,"author":1878},"/jestep/2023-3/fastapi","FastAPI: A High-Performance Python Framework for Rapid Web Development","FastAPI is a modern and high-performance Python web framework designed specifically for building APIs and web applications quickly and efficiently. Developed by Sebastián Ramírez and first released in 2018, FastAPI has rapidly gained traction in the developer community thanks to its focus on providing key features for API and web app development with excellent performance.",[1386,1872,1387,1873,1874],"fastapi","flask","pyramid","/jestep/2023-3/img/header.png","2024-05-01","content:jestep:2023-3:fastapi.md",{"user":1879,"name":1880},"jestep","Jagger Estep",{"_path":1882,"title":1883,"description":1884,"publishDate":1885,"tags":1886,"image":1890,"_id":1891,"author":1892},"/nharrison/2012-07/core-data","Securing Your Core Data with Transformable Attributes","In order to store private data in an iOS Core Data database, there are several methods available for encryption, including:","2012-07-30",[1887,1888,1084,1099,1889],"core-data","encryption","objective-c","/nharrison/2012-07/img/superman.jpg","content:nharrison:2012-07:core-data.md",{"user":1893,"name":1894},"nharrison","Noah Harrison",{"_path":1896,"title":1897,"description":1898,"tags":1899,"publishDate":1904,"image":1905,"_id":1906,"author":1907},"/phendry/2019-3/restfromthebottomup","REST from the Bottom Up","The RESTful API has a funny place in the software development world: it's widely regarded as the best general-purpose pattern for building web application APIs, and yet it's also nebulous enough of a concept to cause endless disagreements within teams over exactly how to implement one.",[1900,1901,1902,1903],"rest","api","web","architecture","2019-10-01","/phendry/2019-3/img/feature_image.png","content:phendry:2019-3:RestFromTheBottomUp.md",{"user":1908,"name":1909},"phendry","Paul Hendry",{"_path":1911,"title":1912,"description":1913,"tags":1914,"publishDate":1830,"image":1915,"_id":1916,"author":1917},"/phendry/2021-06/smoothupgradestovue3","Smooth Upgrades to Vue 3","This post assumes basic familiarity with Vue.js v2.x.",[1201,1499,1325],"/phendry/2021-06/img/vue-transition.jpg","content:phendry:2021-06:SmoothUpgradesToVue3.md",{"user":1908,"name":1909},{"_path":1919,"title":1920,"description":1921,"image":1922,"tags":1923,"publishDate":1763,"_id":1924,"author":1925},"/phendry/2021-07-30/spotthevulndataranges","Spot the Vulnerability: Data Ranges and Untrusted Input","In 1997, a flaw was discovered in how Linux and Windows handled IP fragmentation, a Denial-of-Service vulnerability which allowed systems to be crashed remotely.","/phendry/2021-07-30/img/vulnerability.jpg",[1099,1049],"content:phendry:2021-07-30:SpotTheVulnDataRanges.md",{"user":1908,"name":1909},{"_path":1927,"title":1928,"description":1929,"tags":1930,"image":1931,"publishDate":1932,"_id":1933,"author":1934},"/phendry/2021-08-15/exploringdependenttypesinidris","Exploring Dependent Types in Idris","When I'm not coding the \"impossible\" at Art+Logic, I take a lot of interest in new programming technologies and paradigms; even if they're not yet viable for use in production, there can often be takeaways for improving your everyday code.",[1236],"/phendry/2021-08-15/img/dependent-types.jpg","2021-08-15","content:phendry:2021-08-15:ExploringDependentTypesInIdris.md",{"user":1908,"name":1909},{"_path":1936,"title":1937,"description":1938,"tags":1939,"image":1940,"publishDate":1941,"_id":1942,"author":1943},"/phendry/2021-10-30/spotthevulnloopsandtermconditions","Spot the Vulnerability: Loops and Terminating Conditions","In memory-unsafe languages like C, special care must be taken when copying untrusted data, particularly when copying it to another buffer. In this post, we'll spot and mitigate a past vulnerability in Linux's NTP daemon.",[1099,1049],"/phendry/2021-10-30/img/vulnerability-2.jpg","2021-10-30","content:phendry:2021-10-30:SpotTheVulnLoopsAndTermConditions.md",{"user":1908,"name":1909},{"_path":1945,"title":1946,"description":1947,"image":1948,"tags":1949,"publishDate":1950,"_id":1951,"author":1952},"/phendry/2022-07-21/migratingfromexpresstofastifypart1","Migrating from Express to Fastify, Part 1","Express.js has for years been the dominant lightweight Web framework for Node.js, but over time its development has stalled, with its latest major version (5.0) still in pre-release nearly eight years after its first alpha release. There's a lot to be said for this sort of stability in a foundational dependency for a project, but it's worth assessing whether the added features of competing frameworks are worth making a switch. In this article we'll be looking at Fastify in particular, to understand what it has to offer compared to Express and how difficult it is to migrate an existing Express project.","/phendry/2022-07-21/img/Migrating from Express to Fastify, Part 1.png",[1201,1049],"2023-12-01","content:phendry:2022-07-21:MigratingFromExpressToFastifyPart1.md",{"user":1908,"name":1909},{"_path":1954,"title":1955,"description":1956,"image":1957,"tags":1958,"publishDate":1959,"_id":1960,"author":1961},"/phendry/2022-07-28/migratingfromexpresstofastifypart2","Migrating from Express to Fastify, Part 2","In Part 1, we looked at the features of the Fastify Node.js Web framework compared to Express.js. In Part 2, we'll work through migrating an example Express.js application to Fastify.","/phendry/2022-07-28/img/Migrating from Express to Fastify, Part 2.png",[1201,1049],"2023-12-31","content:phendry:2022-07-28:MigratingFromExpressToFastifyPart2.md",{"user":1908,"name":1909},{"_path":1963,"title":1964,"description":1965,"tags":1966,"image":1967,"publishDate":1968,"_id":1969,"author":1970},"/phendry/2023-01-19/badcode","\"Bad\" Code (Or, Why Software Development is Hard)","Recently, the Dutch government open-sourced the iOS application for their \"DigiD\" authentication service. A tweet with a snippet of that source code, presumably making fun of it, blew up into a debate about whether mocking it is even justified. The amount of debate over such a simple snippet of code highlights, in my mind, just how tricky software development can be.",[1099,1049],"/phendry/2023-01-19/img/Bad Code.png","2024-01-15","content:phendry:2023-01-19:BadCode.md",{"user":1908,"name":1909},{"_path":1972,"title":1973,"description":1974,"image":1975,"publishDate":1976,"tags":1977,"_id":1978,"author":1979},"/phendry/2023-01-31/forgetaboutcodestyle","Forget About [Code] Style","Good code style, being highly subjective, is something often debated among developers. After all, we spend more time reading code than writing it, so it's worth making sure our code is styled to be as easy as possible to read and to understand. On the other hand, deciding upon and continuously enforcing a style is also time-consuming, and the benefits are near-impossible to quantify. Given that modern code formatting tools can fully automate the process, is it still worth fretting about style?","/phendry/2023-01-31/img/forget_style_header.png","2024-02-01",[1236],"content:phendry:2023-01-31:ForgetAboutCodeStyle.md",{"user":1908,"name":1909},{"_path":1981,"title":1982,"description":1983,"image":1984,"tags":1985,"publishDate":1986,"_id":1987,"author":1988},"/phendry/2023-04-02/semantichtml","Don't Give Up on Semantic HTML","Since the early days of the Web, there has been tension between the ideal of \"semantic HTML\" and the practical reality of designing complex page layouts, which often could not be achieved without inserting style concerns into the document. More recently, frameworks like Tailwind CSS have emerged which challenge the very idea that semantic HTML is an ideal to strive for, and which commit to thoroughly embedding style concerns into HTML documents. With modern CSS features however, semantic HTML is more achievable than ever, and I do think it remains a worthy goal.","/phendry/2023-04-02/img/Don't Give Up on Semantic HTML.png",[1236],"2024-03-01","content:phendry:2023-04-02:SemanticHtml.md",{"user":1908,"name":1909},{"_path":1990,"title":1991,"description":1992,"image":1993,"tags":1994,"publishDate":1995,"_id":1996,"author":1997},"/phendry/2023-05-16/doyouneedacsspreprocessor","Do You Need a CSS Preprocessor in 2023?","CSS preprocessors like Less, Sass and Stylus have long provided powerful features that vanilla CSS lacked: variables, nesting of rulesets, mixins, control flow constructs, etc. These days however, the feature gap is considerably narrower, and it's not so clear that the benefits of a preprocessor outweight the burdens of setting it up.","/phendry/2023-05-16/img/css_preprocessor_header.png",[1236],"2023-01-01","content:phendry:2023-05-16:DoYouNeedACSSPreprocessor.md",{"user":1908,"name":1909},{"_path":1999,"title":2000,"description":2001,"image":2002,"publishDate":2003,"tags":2004,"_id":2005,"author":2006},"/phendry/2023-07-28/dependencymanagement","Software Dependency Management: Best Practices","Leveraging third-party libraries and frameworks is essential in most modern software projects, and the projects we build at Art+Logic are no exception. The pressure on developers to rapidly deliver features is high, and there are so many commonalities in the details of each project (particularly in Web development) that a lot of development time can be saved by using well-designed libraries that handle the details.","/phendry/2023-07-28/img/dependency_header.png","2023-01-02",[1236],"content:phendry:2023-07-28:DependencyManagement.md",{"user":1908,"name":1909},{"_path":2008,"title":2009,"description":2010,"tags":2011,"publishDate":2014,"image":2015,"_id":2016,"author":2017},"/phendry/2023-11-06/frontendframeworksin2024","Frontend Frameworks in 2024: React, Svelte and Vue","Several years ago, Art+Logic settled on Vue.js as our preferred frontend Web framework. Now, in 2024, we feel it's time to revisit the frontend framework landscape to see how things have (or haven't) changed.",[1236,2012,2013,1499],"react","svelte","2024-05-15","/phendry/2023-11-06/img/frontend_frameworks_2024.png","content:phendry:2023-11-06:FrontendFrameworksIn2024.md",{"user":1908,"name":1909},{"_path":2019,"title":2020,"description":2021,"publishDate":2022,"tags":2023,"image":2026,"_id":2027,"author":2028},"/rbrubaker/2012-06/arduino-thermometer","Turn Your Mac into a Thermometer with Arduino","The topic of the Arduino came up around A&L's \"virtual water cooler\" last week. About a year and a half ago, I purchased a SparkFun Inventor's Kit for Arduino. The kit is a fun way for a hardware novice like me to get started and learn some basics. It comes with more than a dozen sample projects such as lighting LEDs, spinning a motor and generating audio.","2012-06-28",[2024,2025],"arduino","java","/rbrubaker/2012-06/img/arduino1.jpg","content:rbrubaker:2012-06:arduino-thermometer.md",{"user":2029,"name":2030},"rbrubaker","Ryan Brubaker",{"_path":2032,"title":2033,"description":2034,"publishDate":2035,"tags":2036,"_id":2039,"author":2040},"/rbrubaker/2012-06/coffe-backbone-1","Fun with CoffeeScript and Backbone.js : Part 1","CoffeeScript has been all the rage lately and I've been wanting to hop on board the bandwagon. I've also seen Backbone.js mentioned quite a bit and was even more intrigued after listening to this .NET Rocks podcast. I decided to convert some plain JavaScript code I had in a side project to use both CoffeeScript and Backbone.js and see how things went.","2012-06-06",[2037,2038,1226,1049],"backbone-js","coffeescript","content:rbrubaker:2012-06:coffe-backbone-1.md",{"user":2029,"name":2030},{"_path":2042,"title":2043,"description":2044,"publishDate":2045,"tags":2046,"_id":2047,"author":2048},"/rbrubaker/2012-06/coffee-backbone-2","Fun with CoffeeScript and Backbone.js : Part 2","In this post I’ll discuss the code that handles updating the UI.","2012-06-07",[2037,2038,1226,1049],"content:rbrubaker:2012-06:coffee-backbone-2.md",{"user":2029,"name":2030},{"_path":2050,"title":2051,"description":2052,"publishDate":2053,"tags":2054,"_id":2055,"author":2056},"/rbrubaker/2012-06/coffee-backbone-3","Fun with CoffeeScript and Backbone.js : Part 3","In this post I’ll discuss my thoughts on CoffeeScript and Backbone.js.","2012-06-08",[2037,2038,1226,1049],"content:rbrubaker:2012-06:coffee-backbone-3.md",{"user":2029,"name":2030},{"_path":2058,"title":2059,"description":2060,"publishDate":2061,"tags":2062,"_id":2063,"author":2064},"/rbrubaker/2012-07/prototypal-js","Prototypal vs. Functional Inheritance in JavaScript","If you ever found JavaScript's prototypal inheritance confusing, do yourself a favor and open this article, open a JavaScript console and code each example in the article. You will definitely come away with a better understanding of how prototypal inheritance works in JavaScript.","2012-07-11",[2038,1201],"content:rbrubaker:2012-07:prototypal-js.md",{"user":2029,"name":2030},{"_path":2066,"title":2067,"description":2068,"publishDate":2069,"tags":2070,"_id":2071,"author":2072},"/rbrubaker/2012-07/whither-pm","Whither Project Management?","When I was first asked to manage a project at Art & Logic, I had my reservations. Did I really want to start down a career path that led to less development? Would my skills as a developer go stale? My first few projects as a manager were solo projects so I still had plenty of development work and fortunately, I found myself to be a pretty easy person to manage. As time went on I started managing larger projects and with them came the responsibility to manage other developers. To my surprise I found project management to be rewarding and dare I say, even fun. It's very satisfying to work with clients, helping them define their visions and seeing those visions come to life.","2012-07-25",[1828],"content:rbrubaker:2012-07:whither-pm.md",{"user":2029,"name":2030},{"_path":2074,"title":2075,"description":2076,"tags":2077,"image":2080,"publishDate":1170,"_id":2081,"author":2082},"/scharette/2019-4/discover_machine_learning","Discover Machine Learning","Computers have been around for less than 100 years.  In that short period of time, some incredible things have happened:  they've been universally adopted so quickly that we have them in our houses.  In our cars.  Even in our pockets.  In the last 40 years, there have been many significant events when it comes to computers:",[2078,2079,1162],"machine-learning","neural-networks","/scharette/2019-4/img/discover_machine_learning.png","content:scharette:2019-4:discover_machine_learning.md",{"user":2083,"name":2084},"scharette","Stéphane Charette",{"_path":2086,"title":2087,"description":2088,"publishDate":2089,"image":2090,"tags":2091,"_id":2093,"author":2094},"/shuey/2012-05/baas","BaaS Offerings Continue to Grow","The makers of Simplenote recently introduced their Backend as a Service (BaaS) offering called Simperium that looks to compete in an increasingly crowded space with services like CloudMine, Kinvey, and Parse and to some extent with iCloud for iOS and OS X only apps. So just how crowded is this space? Back in February, Kinvey published their own map of the BaaS ecosystem that highlights different tiers of the ecosystem and various relationships between them.","2012-05-10","/shuey/2012-05/img/header.png",[2092],"baas","content:shuey:2012-05:baas.md",{"user":2095,"name":2096},"shuey","Steven Huey",{"_path":2098,"title":2099,"description":2100,"publishDate":2101,"tags":2102,"image":2104,"_id":2105,"author":2106},"/shuey/2012-05/cloud","Under the Sheets with iCloud and Core Data","Drew McCormack is writing a great series (Part 1, Part 2, Part 3) of posts about using iCloud for syncing Core Data managed data. It's harder than Apple lets on and Drew has done a great job of uncovering how this actually works.","2012-05-28",[1085,2103],"icloud","/shuey/2012-05/img/icloud.jpg","content:shuey:2012-05:cloud.md",{"user":2095,"name":2096},{"_path":2108,"title":2109,"description":2110,"publishDate":2111,"tags":2112,"_id":2114,"author":2115},"/shuey/2012-05/economics-android","The Economics of Android","If you haven't already do yourself a favor and head over to asymco.com to catch Horace Deidu's multi-post series on \"The Economics of Android\". Horace and Dan Benjamin discuss the series during this week's Critical Path podcast as well. Horace is a former analyst for Nokia and has been writing Asymco for a few years now. His analysis of the mobile industry and Apple's place within it in particular has been featured in publications such as Bloomberg and Forbes.","2012-05-17",[2113],"android","content:shuey:2012-05:economics-android.md",{"user":2095,"name":2096},{"_path":2117,"title":2118,"description":2119,"publishDate":1527,"tags":2120,"_id":2123,"author":2124},"/shuey/2012-05/iot","The Internet of Things and Big Data","I've been following the developments in the \"Internet of Things\" and Big Data / Open Data markets as new apps and tools are released and they look to be two exciting technologies on a collision course. With the advent of internet connected home appliances like Wattvision and Nest that provide real utility to the average home owner at reasonable prices along with crowd funded projects like Air Quality Egg or Twine we should see an explosion in the kinds and amount of useful and real-time or near real-time data that is available to anyone with a smartphone. Health metric or \"quantitative self\" tracking devices such as Fitbit, Jawbone Up, and the Pebble watch will fuel this data explosion as well.",[2121,2122],"big-data","iot","content:shuey:2012-05:iot.md",{"user":2095,"name":2096},{"_path":2126,"title":2127,"description":2128,"publishDate":2129,"tags":2130,"image":2132,"_id":2133,"author":2134},"/shuey/2012-05/rubymotion","RubyMotion Brings Ruby to iOS","RubyMotion is a new development toolchain that allows you to build iOS apps using Ruby created by Laurent Sansonetti, a former Apple engineer and contributor to the MacRuby project. It has garnered a lot of attention the past few weeks and some detailed reviews have already been written:","2012-05-14",[1084,2131],"ruby","/shuey/2012-05/img/logotype-icon.png","content:shuey:2012-05:rubymotion.md",{"user":2095,"name":2096},{"_path":2136,"title":2137,"description":2138,"publishDate":2139,"tags":2140,"image":2141,"_id":2142,"author":2143},"/shuey/2012-06/thoughts-ios6","A few thoughts on iOS 6","Apple made their session videos from WWDC 2012 available earlier this week in record time. It's nice to see since tickets for this years event sold out in under two hours. Apple has an iOS 6 Preview page touting some of the new features such as Siri's new abilities, tighter integration with Facebook, Photo Stream sharing, and things like iCloud tabs for Safari all of which look great.","2012-06-21",[1085,1084],"/shuey/2012-06/img/ios6.jpg","content:shuey:2012-06:thoughts-ios6.md",{"user":2095,"name":2096},{"_path":2145,"title":2146,"description":2147,"publishDate":2148,"tags":2149,"image":2151,"_id":2152,"author":2153},"/shuey/2012-07/mixer","A Simple Mixer Using AVFoundation","In iOS 4.0 Apple introduced the AV Foundation APIs that made working with audio and video media much easier than it had been in previous versions of iOS. Apple then brought these APIs to Mac OS X in OS X 10.7 \"Lion\". In this post I'll show how to use some of the APIs to create a simple four track mixer.","2012-07-02",[1085,2150,1084],"cocoa","/shuey/2012-07/img/mixer-screenshot.jpg","content:shuey:2012-07:mixer.md",{"user":2095,"name":2096},{"_path":2155,"title":2156,"description":2157,"publishDate":2158,"tags":2159,"image":2160,"_id":2161,"author":2162},"/shuey/2012-07/reset-button","The Reset Button","Horace Dediu of Asymco has been publishing some fantastic insights and analysis of the mobile market in the past few weeks. I linked to some of Dediu's analysis of the Economics of Android in an earlier post, and since then he's updated his work with the latest data and is studying RIM and Microsoft's efforts in the space as well.","2012-07-19",[2113,1085,1084],"/shuey/2012-07/img/kevin.jpg","content:shuey:2012-07:reset-button.md",{"user":2095,"name":2096},{"_path":2164,"title":2165,"description":2166,"publishDate":2167,"tags":2168,"image":2170,"_id":2171,"author":2172},"/tfarrel/2012-07","Looking at Steganography","With the help of one of my favorite news aggregators, I discovered this article on using JavaScript and the canvas element to hide information inside images. I've long been fascinated by steganography and this article and demonstration makes it even more accessible. If you can't be bothered to read the article, it describes a method of using the HTML5 File API and the canvas element to embed a message in images.","2012-07-24",[2169],"steganography","/tfarrel/2012-07/img/white.png","content:tfarrel:2012-07:index.md",{"user":2173,"name":2174},"tfarrel","Troy Farrel",1789027395705]