back to main blog page

An Approach to Self-Writing Software

Self-Generating AI There is a widely-held belief in the software community that self-generating code is bad. The main reasons often brought up are confusion, increased likelihood of bugs - mostly due to confusion, and potential for the code to break itself - also due to programmer confusion. In other words, if we were to eliminate the confusion, self-generating code might be ok. But that is easier said than done. Our current approach to coding is not designed for self-generation. Each line of code increases the surface area for errors. Errors stack with each other, and often go undetected for months. Tests are an afterthought, often forgotten entirely in a rush to meet the deadline. But what if there was a better way?

Imperative vs Declarative Approach

The typical approach to coding is imperative, which basically means you give exact instructions to the machine on what to do. Any curveball that causes an instruction to fail will also cause all instructions coming after to fail. The system is unable to backtrack to repeat the failed action like a human would, it simply falls on its face.

There is an alternative approach, called declarative programming. Instead of describing what to do step by step, declarative programming describes the state you want to end up in and lets the system figure out the steps to get there by itself. In order to achieve this, the system would need to have some sort of internal heuristic (an "intuition" about the general direction to go in to achieve the desired state), and understanding of basic building blocks it can put together ("valid moves" it's allowed to make).

The simplest example of a heuristic is Dijkstra's algorithm, which basically picks the shortest path (smallest building block) that gets it towards the desired direction. Here is an animation showing how it would solve a maze:

Dijkstra's algorithm

This is exactly how my Drone project works, that I have written a few years back. It's a declarative testing/web-crawler framework that can navigate itself out of any error pages. Its building blocks (valid moves) are page links and it uses Dijkstra's algorithm to build an internal navigation tree of the web site it crawls. It beats existing testing frameworks like Selenium by a mile because it can traverse the website in any order it chooses, finding issues imperative frameworks wont catch because humans can't hardcode every possible test combination. It can backtrack out of a bad state by reloading the home page and navigating a different route, something even Cypress won't do (don't mean to speak ill of it, it's a great project and Gleb, their VP of Engineering, is a good friend of mine). My point is that declarative frameworks have this "magical" self-assembling tendency that imperative ones do not.

React is another (admittedly more popular) example of a declarative framework. Developer defines the app in terms of states rather than in terms of instructions to update those states. This simplifies the UI development, letting internal algorithm settle the moving parts, even if they're updated out of order. In fact, many compilers/parsers are written the same way, I've written a few of my own back in the day. Declarative coding is not new, it just requires a different way of thinking.

Leveraging Generative AI

This is where my idea of self-building software comes in. To give a full disclaimer, I don't believe this is possible yet with the current state of generative AI, but it may be possible within a couple years, as AI gets better at writing non-hallucinogenic code. The idea is to define the interfaces (the scaffold) for each module, as well as tests this module should pass. These can be unit tests for exposed functions as well as system level tests. You then would ask the AI to generate internal logic for these modules that satisfy all tests, a test-driven development where you outsource the development to AI.

This would require you to be a lot more meticulous with your tests, and for AI to honor them all, something the current generation of generative AI is not great at. The larger the context gets, the harder it is for AI to keep track of the details. But let's imagine an ideal world, with GPT5+ and infinite context size.

You could have the AI regenerate the module internals until they pass the spec you defined via tests and interfaces. In a way, developer's job would now be defining the spec, with AI replacing interns who'd write this code otherwise. Naturally, the quality of such code would probably be on par with code written by interns, at least initially. This is where the developer would come back, add more tests, redefine interfaces after seeing the edge cases AI ran into, and let the generation rerun. The more descriptive the spec, the faster the internals would be generated (assuming no contradicting specifications). Developer would continously break down the problem into smaller modules/chunks, until the AI can fill in the blanks. This would be a form of top-down design.

We could take this concept a step further, and have the tests be generated by AI as well, a GAN (Generative Adversarial Network) approach. This would allow a single developer to control huge portions of code by abstracting the complexity away.

Since large corporations already have the budget for human labor, this would mainly benefit smaller teams that move quickly, allowing solopreneurs to compete with larger players. If you'd be interested in tackling such project together and have something to contribute, hit me up. Given my other commitments, I probably won't be able to work on this full-time, but maybe I can have generative AI do so on my behalf ;).

Be the first to comment...