Category: Development

Programming, software architecture, technical experimentation, tools, platforms, and building things with technology.

  • Practice Note: When AI Removes the Implementation Friction

    Several years ago, I started experimenting with controlling a model railway through a Roco Z21 command station.

    Looking back, I was really trying to solve three problems at once.

    I wanted to show that coding could be easy and fun by using it to control something physical. I wanted to make a complicated German-language protocol specification more accessible to an international audience by explaining it in English. And I wanted to learn Python and refresh my own coding skills.

    That meant implementing the Z21 protocol was not just scaffolding.

    It was part of the purpose of the exercise.

    My first experiment was simple: retrieve the Z21 serial number. But even that meant understanding the protocol, byte ordering and UDP communication, then translating all of it into Python.

    As the project grew, so did the scaffolding. Incoming packets could contain multiple messages, so I needed to split them. Different messages needed dispatching. Some information arrived asynchronously. Feedback modules reported track occupancy. Locomotive control introduced another protocol carried through the Z21 protocol.

    Along the way I also started experimenting with functional programming, refactoring, behavioral examples and automated tests.

    All of that was useful. But I was simultaneously learning the protocol, learning Python, designing the software, debugging it, documenting it and trying to automate a railway.

    Returning to the same problem

    Several years later, I came back to the project.

    The railway has not fundamentally changed. Neither has the protocol.

    The development environment has.

    Today I can give AI the Z21 protocol specification and ask how to retrieve the serial number. It can find the relevant section, interpret it, explain the request and response and produce a candidate implementation.

    But code generation is only a small part of what changed.

    I could also give AI my old implementations. It found bugs in code I had written, compared my interpretation with the specification, suggested improvements and helped reconstruct what I had been trying to do.

    Where I had previously become stuck, it could suggest possible ways forward.

    When I wanted to develop without depending on the physical command station, it helped design a small Z21 simulator over UDP on localhost.

    When I wanted to return to automated testing, it could help translate acceptance criteria into Python unittest tests.

    And when an answer looked questionable, I could challenge it.

    That matters. AI was not always right. I corrected its reconstruction of the history of some of my old experiments, and I questioned its interpretation of parts of the protocol.

    The point is not that AI provides trustworthy answers automatically.

    The point is that it removes a great deal of friction.

    Three problems that largely disappeared

    The contrast with the original project is striking.

    Previously, I wanted to make coding accessible, translate a German specification for an international audience and learn Python while refreshing my programming skills.

    Today, none of those needs to be a prerequisite for the real experiment.

    Roco published the specification finally in English. AI can help produce and inspect Python. If I encounter a language feature or protocol detail I do not understand, I can investigate it at the moment it becomes relevant.

    Technical knowledge has not disappeared. AI can supply implementation proposals on demand, but my understanding of what good software looks like becomes what allows me to direct, challenge and improve those proposals.

    But much of it has moved from being a prerequisite to being an on-demand resource.

    That changes where I can spend my attention.

    Before, the path often looked like this:

    intent → documentation → technical understanding → implementation → debugging → experiment

    Now it can look more like this:

    intent → user story → acceptance criteria → automated tests → implementation → experiment → observation and learning

    All AI assisted. The implementation is still there. So is the technical knowledge behind it. But they no longer need to dominate the work.

    That leaves more room for the questions I actually care about:

    What am I trying to achieve?

    What behavior do I require?

    How will I know that it works?

    What assumptions am I making?

    What did I learn from the result?

    Not just programming

    I recognize the same pattern when working with AI on Practice Notes and other documents.

    I bring intent, observations and source material. AI helps analyze, retrieve, compare, synthesize and draft. I inspect the result, challenge it, provide more evidence and iterate.

    The artifact may be prose instead of Python, but the pattern is similar:

    intent → AI-assisted interpretation → AI-generated candidate artifact → judgment → evidence → revision

    For software, some of that evidence can be executable. User stories preserve intent. Acceptance criteria describe expected behavior. Automated tests make those expectations executable. A simulator provides a controlled test environment. Eventually, the physical model railway layout provides another form of evidence.

    AI can help throughout that chain without becoming the authority on whether the result is correct.

    From implementation to intent

    The first time around, implementing the Z21 protocol was part of the exploration.

    I wanted to understand it, explain it and learn how to implement it.

    This time, I do not particularly need to rediscover how to implement a binary railway protocol.

    I want to explore what I can do with it.

    Earlier, I explored how to implement the Z21 protocol.

    This time, I can explore what I want to do with it.

    And perhaps that is the broader lesson:

    AI does not merely make implementation faster. It can move implementation knowledge from a prerequisite toward an on-demand resource, allowing more attention to move toward intent, evidence, judgment and learning.

  • Practice Note: How many systems did you retire last year?

    Organizations often associate continuity with keeping systems, products, or capabilities running. Yet continuity can require the opposite: knowing when something can safely cease to exist.

    A mature portfolio does not only make informed decisions about what to add. It also makes informed decisions about what to remove.

    One provocative measure of product-portfolio maturity is therefore the number of systems an organization has been able to retire. The measure should not be taken literally—retiring more systems is not inherently better—but the reasoning behind it is revealing. Retiring a system confidently requires understanding what the system still contributes and what depends upon it.

    Consider an old mainframe environment.

    Over many years, applications may have been migrated elsewhere. New development has stopped. Most known business functionality has disappeared. The organization believes that the mainframe has effectively become redundant.

    Yet it remains operational. Why? Because nobody is sufficiently confident that it can be switched off.

    There might still be a batch process running somewhere. An obscure interface may still exchange data with another system. A business process performed only once a year may depend upon it. Some responsibility may have been assumed to have migrated but never actually did.

    The organization does not know that the mainframe is necessary. It does not know that it is unnecessary. That distinction can keep an obsolete system alive for years. Loss of understanding can preserve obsolete realizations

    This exposes an interesting inversion. Normally, understanding is associated with an organization’s ability to maintain and develop something. But understanding is equally important when deciding to stop maintaining it.

    As organizational understanding disappears, the realization can become increasingly difficult to change or remove. Its known value may decrease while uncertainty about its unknown value increases.

    Eventually the organization may preserve the realization not because it believes the realization is valuable, but because it cannot establish that removing it is safe.

    Loss of understanding can increase the persistence of something whose value has already disappeared.

    The resulting portfolio contains systems that survive through uncertainty.

    They consume infrastructure, licenses, operational effort and scarce expertise. They may constrain architectural change and introduce security or operational risks. Yet attempts to remove them encounter the same question:

    Are we absolutely sure nothing important still depends on this?

    Without sufficient understanding, the organization cannot answer.

    Retirement is an assessment problem

    Retiring a system is therefore not merely a technical activity. It requires an assessment. The organization needs sufficient understanding of the system’s purpose, current contribution, dependencies, users, data, business processes and outcomes to form a justified judgment about what will happen when it disappears.

    Evidence may need to be collected: usage information, interface traffic, batch execution, dependency analysis, business-process mapping, stakeholder knowledge or controlled interruption.

    The question is not simply whether the system appears obsolete.

    The question is whether there is sufficient evidence and understanding to justify the judgment that its removal is safe.

    This connects retirement directly to Continuity.

    Continuity does not mean preservation of the object

    Continuity can easily be misunderstood as an argument for keeping things alive. It is not.

    The continuity that matters is continuity of what remains significant: intent, outcomes, responsibilities, knowledge and necessary relationships. A particular realization may cease to be the appropriate way of providing them.

    Sometimes maintaining Continuity therefore requires replacing a system. Sometimes it requires transferring responsibilities elsewhere. Sometimes the purpose itself has disappeared and nothing needs to replace it. And sometimes the correct decision is simply to switch the system off.

    The ability to make that decision confidently depends on understanding.

    Poor Continuity may not cause an old system to disappear. It may be precisely why nobody dares to switch it off.

    The portfolio implication

    This has consequences for portfolio management. Portfolio development is often associated with investment: selecting new products, approving initiatives and allocating resources to new opportunities.

    But a portfolio also develops through subtraction. Removing redundant elements releases resources, reduces complexity and risk, and allows investment to concentrate on elements that continue to contribute to portfolio intent.

    A mature portfolio-management capability therefore needs to understand its existing portfolio well enough to answer not only:

    What should we add?

    but also:

    What can we safely stop?

    This makes retirement capability an interesting indicator of portfolio understanding. An organization that continually adds new systems but cannot confidently retire old ones may not have a technology problem at all.

    It may have accumulated understanding debt at portfolio scale.

    And I think this one is particularly valuable because it produced a candidate generic insight for A:

    Sufficient understanding is required not only to develop and assess a subject, but also to determine when it can safely cease to exist.