
Architecture Tests: How to Enforce Architectural Rules Directly in Code
Architectural rules that exist only in documentation will sooner or later be broken. It's not a question of if, but when.
Go to content|Go to the main menu|Go to search
A year ago, I wrote on this blog about how AI is changing software development. Back then, I was asking colleagues and community members how much time chatbots and copilots were saving them. At that time, we were mainly discussing whether AI helps in development. Today, that question sounds almost naive, because we see AI multiplying the speed of software development processes all around us. The question that interests me now is: how to develop with AI so that the result is repeatable, auditable, and high-quality?
Part of the answer came from experience on a project where we gradually built this approach, and I’d like to share it with you now. It resulted in a perspective on two paths you can take when developing with AI - and why one of them is significantly more sustainable.
I believe that the use of AI in development can be either guided or unguided. The unguided approach is what is often - and rather pejoratively - called vibe-coding. It’s a state where the developer lets artificial intelligence lead, accepts its suggestions without deeper verification, and essentially just “clicks through” the results. It may work for prototypes or one-off scripts, but it’s not sustainable for production development.
The guided approach - which I call agentic development - is based on a different principle. The developer systematically builds the context in which the solution is created. AI agents are then viewed as functions that produce quality outputs from well-prepared inputs. This creates a repeatable process that can be audited and iterated upon.
To avoid speaking only in abstractions, I’ll describe a concrete case from a project for one of our clients, where we’re developing a system for managing manufacturing processes.
On this project, a requirement emerged for a video archive. The system has N cameras monitoring the manufacturing process. For each camera, there can be M archival tasks. Video is stored in hourly blocks in object storage, to which the client has direct access. The key complexity lay in playback - archive navigation is entirely arbitrary: jumps of any size forward and backward, playback at various speeds forward and in reverse.
Previously, I would have estimated such functionality at half a year of work for a large team. In this case, most of the work was completed in approximately 3 sprints.
The entire process had five phases, in which artificial intelligence played a fundamental role.
At the beginning was a rough specification of approximately 1.5 A4 pages. It wasn’t anything extensive - use cases were listed with short descriptions. What’s important, though, is that the document also captured the basic expectations of the end user.
We took this specification and began brainstorming the architectural design with the help of AI. An ADR (Architecture Decision Record) was created in Markdown, which I worked on for about 4 hours - basic objects, diagrams, and an idea of how the components would communicate. Then I let it “snowball”: AI generated technology proposals that would meet the requirements, compared them against each other, and I validated whether the comparisons matched the facts. During this phase, a draft of the playback logic for the client was also created.
Very quickly after that, a prototype emerged - backend in Python, frontend in Flutter. The prototype served to validate the playback logic, and of course it wasn’t right the first time. We identified incorrect assumptions and iterated between the ADR and the prototype until we eventually arrived at a functional and maintainable design.
Once the technical specification was ready, we supplemented the agent’s context with descriptions of the repositories and already completed parts of the system. Then we tasked it with breaking down the work. It generated features (the first level of the backlog), which it then further attempted to break down into tasks. Not everything worked perfectly - the breakdown into tasks was less reliable than the breakdown into features - but it significantly accelerated backlog preparation compared to classic grooming with the entire team.
The resulting tasks with clearly prepared context could be assigned directly to agents. This phase was still partially manual for the first functionality, but for subsequent ones, it became apparent that agents could handle most of the work based on the prepared specifications.
The process described above multiplied the development speed. I believe that in all phases, it’s possible to leave at least 80% of the work to AI. Activities like planning and design (of a single work package) no longer need to be performed by the entire team. A single responsible person who brainstorms with AI can handle them. The output is then validated with the product and technical leadership of the project.
This transformation has both downsides and upsides. I really enjoy collaborating with people, but let’s be honest: communication between people slows many things down. We humans are smart and motivated, but sometimes we’re tired, having a bad day, and frictions arise that slow the process down. Other obstacles are purely mechanical: I’m sure many developers have experienced those uncomfortable moments during grooming where several people watch one unfortunate soul sweating out words into the Description field of an issue tracker while planning work. We’re limited by meetings, keyboards, or the fact that we simply can’t find the right words at that moment. AI can eliminate these stumbling blocks in existing development processes.
I believe this is not the twilight of human collaboration in software development. I expect that human coordination and collaboration will move up a level - to alignment on product priorities, high-level architecture, and so on.
It’s not surprising that our gradual journey from experiment to a functional process wasn’t without complications. These are the lessons we took away:
If you’ve decided to build your own agentic development process, the most important thing to remember is: context is everything. Our work will increasingly be about gathering a description of the solution and then effectively guiding agents - and ourselves - from that description. Just as we previously extended the resulting solution by various interventions in the code, it’s now necessary to write down all relevant facts and our expectations into the context.
What does this mean in practice? Whenever a customer communicates their requirement, we must immediately take notes in text form.

As soon as we take ownership of the problem and begin thinking about its solution and placing it in the broader context of the system, we must also write down this reasoning. Personally, I’ve found the ADR style and Markdown format work best - simple, versionable, and structurable.

With context prepared this way, we can then try to assign development to artificial intelligence.

Will it work for the first time? Maybe not. The result may not be complete,the volume of changes may be too large to digest, or we simply get something different from what we wanted.
To overcome these problems, two tools can be used - ones we know well from everyday developer work - we just apply them at a different level now.
Iteration is straightforward. We take what doesn’t work, return to the specification, adjust it with the agent’s help based on the experience gained, and have the agent rework the solution, or try to generate it again.

But even iteration has its limits. Requirement descriptions and ADRs start to bloat and grow. Suddenly they’re multi-page unwieldy documents that even an agent can’t handle, because - just like a human - it doesn’t have an infinitely wide context window.
That’s when recursion comes into play - we break down (ideally also with the help of AI) the large feature into several, as much as possible independent slices, each with its own requirements description and ADR. We then focus the agent only on the part that’s currently relevant. This process can be recursively repeated to any depth.

We know this principle well from classic development processes - it’s called backlog refinement or grooming. It’s an activity that has always been extremely important, but nobody really wanted to do it because it cost a lot of effort and time. Today it’s a necessary prerequisite for effective agentic development, and AI can significantly help with it.
Where is all of this heading, in my opinion? I will focus on the development on one out of many potential features of some system, as the scaling of development through the parallel effort of multiple developers can be easily derived from there. When developing one feature, we usually go through the following phases:

When AI enters the picture, this process will change in the following way:

Architectural rules that exist only in documentation will sooner or later be broken. It's not a question of if, but when.

Software development is a dynamic field in which new tools and trends are constantly emerging. However, if we want to develop high-quality software, it is not enough to simply apply these tools and trends; we must truly understand how they work and what risks they may entail.
Thank you for your interest in subscribing to our newsletter! To complete your registration you need to confirm your subscription. We have just sent you a confirmation link to the email address you provided. Please click on this link to complete your registration. If you do not find the email, please check your spam or "Promotions" folder.
