The Design Phase in Three Sessions — Having AI Design the Architecture

This article was originally written in Japanese and translated into English with AI assistance. Please note that some expressions may carry nuances from the original Japanese.

🇯🇵 日本語版はこちら / Japanese version


Series: DataMigrator Development Journal (Part 4)


By the end of last time, I’d finished writing Rev.7 of the requirements document, and I was ready to advance to the design phase. This time is about that design phase.

To get to the point: I split the design phase into three sessions total. Session 1 for the architecture, Session 2 for the database and classes, Session 3 for the GUI and tests. About eight design documents came out of it, and the total volume reached a fair thickness. I wrote all of them together with Claude. Until this period, I’d never imagined that someone with zero programming experience would end up writing an architecture design document.

Starting by Asking the AI What Design Even Is

Honestly, at first I didn’t quite get the difference between requirements and design. Requirements are “what to build,” design is “how to build it” — that’s what the books say, but concretely, what am I supposed to do? “How to build it” shouldn’t mean the code itself, so then this something that sits one step before the code — at what level of granularity are we talking?

When I asked Claude, the explanation that came back was roughly the following. A requirements document is a request form — “please build this” — while a design document is closer to “the blueprints of a building that satisfies that request.” A building’s blueprints have layers — the number of floors, the room layout, the placement of pillars, the plumbing, the wiring — and each is drawn on a separate sheet. Software is the same: you need a separate design document for each layer — the overall structure (architecture), how the data is held (DB), the relationships among the parts (classes), the appearance (GUI), the method of quality verification (tests), and so on. Starting to write code only after all these design documents are in place corresponds, in building terms, to “bringing in the materials only after the foundation and blueprints are done.” That was the explanation.

This explanation made me understand: “Ah, so that’s why you split it into three sessions.” Asking, in a single chat, “please write all the design documents” is like suddenly telling a single architect “gimme all the drawings” — it’s not realistic. Splitting it by layer and working through them one at a time is something I, as a human, can keep up with too.

Session 1: Architecture

In the first session, I decided the skeleton of the whole software. It’s the configuration known as a “three-layer architecture.” You divide it into three: the GUI layer (the part that interacts with the user), the business-logic layer (the part that assembles the processing you actually want to do), and the data-access layer (the part that accesses the database and file system).

Put like that, it just sounds like a classification, but what was interesting in this session was that the idea of a “shared engine” came up.

In the requirements, I’d decided to build three modes for DataMigrator (Exploration mode, Quick mode, Full-inspection mode). Naively, you’d write unique processing logic for each of the three modes. But look closely, and what the three modes do has a lot in common. They all share the same skeleton: first scan the files, then take hashes, and finally group and display the results. What differs is only the parameters — things like the scan scope and the way hashes are taken.

What Claude proposed was the policy: “rather than writing processing logic for each of the three modes, build just one set of shared engines (a scan engine, a hash engine, a grouping engine) and change how they’re called per mode.” Doing this reduces the amount of code, means a fix only needs to happen in one place when a bug appears, makes it easier to carry data over between modes, and makes it easier to merge or add modes in the future — the benefits were laid out one after another.

At this point, I asked one question back: “What’s the benefit of going with this policy? Is it that the implementation cost is low?” From the perspective of someone with no programming experience, I had an intuitive grasp that “gathering similar things in one place seems good,” but I didn’t understand concretely what it led to.

The answer that came back raised, beyond implementation cost, perspectives like “localization of bugs,” “test efficiency,” “carrying data over between modes,” “future flexibility,” and “ensuring consistency” — and I remember it sinking in: “ah, so it has that wide an effect.” For me, this single exchange was the moment that decided the direction of the entire design phase. Had I just thrown it over the wall with a “leave it to the pro,” I think I’d probably have regretted something later.

Session 1 also decided other things: the thread configuration (one main thread and one worker thread), the method for cancellation handling, and the method for detecting when you step into a symbolic-link loop. These were the result of crushing the architecture-related items from among the homework that had been left in Appendix C.

Session 2: Database and Classes

The second session was the design of how to hold the data and of the parts.

I decided to use SQLite for the database. For a personal tool, where the use is no more than storing file metadata and hash values, SQLite is plenty. There’s no need to stand up a separate server, and the fact that it completes in a single file is a welcome thing.

The table structure settled into five tables: a table to store the history of scan runs, a table to store information for each individual file, a table to store groups of duplicate candidates, a table for error logs, and a table for file-move logs. The structure has these five connected to one another by foreign keys.

This gets into the weeds, but what quietly troubled me in this session was the “is it okay to put two different meanings of data in the same table?” problem. Quick mode’s “duplicate-candidate groups” and Full-inspection mode’s “confirmed-duplicate groups” are, strictly speaking, different in meaning. The former is “only the name, size, and partial hash match,” while the latter is “matched completely, all the way to the full hash.” Is it okay to put these in the same table, or should they be in separate tables?

As a result of discussing it with Claude, I went with the policy of using the same table and distinguishing them with a “group type” column. The big benefit was that being able to handle them in the same table makes it easier to carry data over from Quick mode to Full-inspection mode. It’s through an accumulation of small decisions like this that the design document fills up.

On the class-design side, I defined around thirty classes: the engine family, the mode-controller family, the data-access family, the worker-thread family, the utility family, the custom-exception family. For each individual class, the role and the public methods get written out. I don’t write code, but at this stage an image started to come into view: “ah, so this class gets called like this.” I think the sensation of the software starting to move inside my head gradually began to emerge around this time.

Session 3: GUI and Tests

The third session was screen design and test planning.

In the GUI design, I defined nineteen screens: a mode-selection screen, a folder-selection screen, a progress screen during a scan, a results-display screen, a confirmation screen for deletion candidates, a settings screen, error dialogs, and other auxiliary screens. I had Claude write out the role of each screen and the flow of the main operations. I didn’t draw the actual appearance as pictures — it was closer to a bulleted level of “this screen has these items lined up on it” — but even so, I had the sensation of “the tool’s form, as seen by the person using it” gradually rising up.

What was intriguing was that, in the middle of doing the GUI design, an idea for a new feature occurred to me. It was the thought, “rather than only deleting duplicate files, it might be handy to have a mode that gathers the scattered actual data into one place (consolidation into a storage folder)” — a feature that hadn’t been written in the requirements document.

Naively, the proper thing would be to go back to the requirements and add it as Rev.8. But as a result of consulting Claude, we discussed “is this feature high enough priority to include in the MVP,” judged that it was “worth including,” and then took it in by adding it to the design document. Whether to strictly adhere to the requirements, or to flexibly take in improvements you notice along the way — this is a hard line to draw, but this time I chose the latter. Looking back now, I think it’s one of the strengths of solo development. In a large organization, taking in a mid-stream idea like this would require meeting after meeting.

In the test design, I defined just under eighty unit-test cases and a dozen-odd integration-test scenarios. All of these would get written during the implementation phase. At this point, I had the surprise within me of “so that’s how much testing you write.” I came to terms with it: this is probably, in essence, the same as how there are days and days of full run-throughs before a theater performance. Going in cold without rehearsal doesn’t work — on the stage or in software alike.

After Finishing Eight Design Documents

After three sessions, the design documents came to eight in total: software architecture, source-code organization, GitHub repository structure, DB schema, class design, GUI design, test design, and the initial prompt for the implementation phase. On top of these, auxiliary materials such as handoff prompts between sessions and meeting notes also piled up.

Honestly, my impression when the whole thing was finished was “is this really okay?” Even though I wrote it together with AI, I myself have zero programming experience. There’s a limit to how well I can judge whether these design documents are of a quality that can withstand implementation. Gazing at the table of contents, I can tell it somehow looks the part, but I lack the foundational knowledge to scrutinize all the contents myself.

Still, I couldn’t very well stay stopped here, so I confirmed things up to the point of “at least all the Appendix C homework is crushed, consistency with the requirements document holds, and the obvious holes have been plugged through discussion with Claude,” and made the decision to advance to the next phase. If it turns out to be no good, then it’s no good, and I’ll fix it in the implementation phase. That kind of resignation.

Incidentally, the time it took to write the eight design documents was, in total, I think a little over ten hours — about two to three hours per session. For someone with no programming experience to write this volume of documentation from scratch on their own would probably be impossible even with months. It’s because I did it together with AI that it took only this much time. Of that, there’s no doubt.

Next Time

Next time, I finally enter the “have AI write the code” phase. But before that, one more preparation was needed. Separate from the Claude I’d been using so far (the chat version used in a browser), I needed to introduce a type of Claude that runs in the terminal, called “Claude Code.” Starting from installing it on the Mac, having it write “Hello World” in a practice project, understanding the security mechanisms, preparing the directory for the production project — the plain, unglamorous prep work continues. Along the way, there were a few stumbles, too: hitting Python-environment problems when I tried to run PySide6, and strange errors in GitHub authentication. Look forward to the Claude Code introduction installment.


About Soul Resonant Works

Soul Resonant Works is a solo venture developing seven local AI systems. Starting from zero programming experience, the development is progressing through collaboration with AI.

🌐 Soul Resonant Works:
https://sr-works.net/en/index.html

📝 This blog publishes the entire development process as a serialized journal.


If you found this article useful, please share it.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *