-
Notifications
You must be signed in to change notification settings - Fork 8
AI coding architectures comparison #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| <!-- Enlighter Metainfo | ||
| { | ||
| "id": 501, | ||
| "title": "Introduction to AI-Optimized Architectures", | ||
| "next_button_title": "Next" | ||
| } | ||
| --> | ||
| <h5>Introduction to AI-Optimized Architectures</h5> | ||
| <p> | ||
| Welcome to this course on designing software architectures that work effectively with AI coding assistants. As AI tools become more integrated into our development workflows, it's crucial to understand how to structure our codebases to maximize their potential. This tutorial, based on the research from the <a href="https://github.com/ipospelov/vibe-coding-architectures">vibe-coding-architectures</a> repository, will guide you through different architectural patterns and their impact on AI-assisted development. | ||
| </p> | ||
|
|
||
| <h5>The Question: Does Architecture Matter for AI?</h5> | ||
| <p> | ||
| With the rise of powerful AI coding tools, a key question emerges: "How can we design codebases to be optimal for AI?" Traditional architectural patterns were designed for human developers, but AI assistants have different requirements for understanding code and navigating context. The primary goal of this course is to determine if and how software architecture affects the performance of AI code generation. | ||
| </p> | ||
|
|
||
| <h5>Key Components of AI Code Generation</h5> | ||
| <p> | ||
| The success of AI in coding tasks depends on four main components: | ||
| </p> | ||
| <ul> | ||
| <li><b>Prompt:</b> The instruction given to the AI. The model generates the most probable continuation of a text based on the prompt.</li> | ||
| <li><b>Model:</b> The underlying Large Language Model (LLM) that determines the quality and probability of the generated code.</li> | ||
| <li><b>Context:</b> All the information available to the model beyond the prompt, which is primarily the existing codebase.</li> | ||
| <li><b>Tools:</b> Functions and capabilities that allow the AI to expand its context, such as file readers, search tools, and terminal access.</li> | ||
| </ul> | ||
| <p> | ||
| This course will focus on optimizing the <b>context</b> through thoughtful codebase architecture. | ||
| </p> | ||
|
|
||
| <h5>Why is Architecture Important for AI?</h5> | ||
| <p> | ||
| A well-designed architecture significantly impacts the effectiveness of AI coding tools. Here's why: | ||
| </p> | ||
| <ul> | ||
| <li><b>Context Management:</b> Good architecture simplifies context management for both developers and AI, ensuring the AI has the right information without being overwhelmed.</li> | ||
| <li><b>Token Efficiency:</b> AI models have a limited context window (measured in tokens). A token-efficient codebase requires less context to be provided to the AI, leading to faster and more accurate results.</li> | ||
| <li><b>Resource Efficiency:</b> A well-structured codebase is more cost-effective. It saves developer time, reduces the computational resources (tokens) needed by the AI, and ultimately saves money.</li> | ||
| <li><b>Clarity and Predictability:</b> Familiar and clear architectural patterns are easier for AI to understand and follow, leading to better adherence to the existing design during code generation and modification.</li> | ||
| </ul> | ||
| <p> | ||
| In the following stages, we will explore four different architectural patterns, build a small application with each, and analyze their performance with AI assistants. | ||
| </p> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| <!-- Enlighter Metainfo | ||
| { | ||
| "id": 502, | ||
| "title": "Experimental Setup", | ||
| "next_button_title": "Let's test!" | ||
| } | ||
| --> | ||
| <h5>Experimental Setup</h5> | ||
|
|
||
| <p> | ||
| To provide a clear and transparent foundation for the findings in this project, this section details the experimental setup used in the original research. Understanding the methodology will help you interpret the results and replicate the experiments with your own tools and models. | ||
| </p> | ||
|
|
||
| <h5>3.1 Experimental Setup</h5> | ||
| <ul> | ||
| <li><b>Test Application:</b> Snake game implementation</li> | ||
| <li><b>Test Modification:</b> Addition of randomly generated maze functionality</li> | ||
| <li><b>LLM:</b> Claude Sonnet 3.7</li> | ||
| <li><b>Isolation:</b> New functionality added from new chat (no context sharing between chats)</li> | ||
| <li><b>Sample Size:</b> 5 runs for each architecture</li> | ||
| </ul> | ||
|
|
||
| <h5>3.2 Evaluation Metrics</h5> | ||
| <p>The performance of each architecture was measured against the following metrics:</p> | ||
| <h6>Initial Generation Metrics:</h6> | ||
| <ul> | ||
| <li><b>One-shot generation success:</b> Application works correctly on the first attempt (binary).</li> | ||
| <li><b>Architecture adherence:</b> Generated app follows the specified architecture (binary).</li> | ||
| <li><b>Token consumption:</b> Cached and non-cached tokens for the initial generation.</li> | ||
| <li><b>Context window size:</b> Final context length after generation.</li> | ||
| </ul> | ||
| <h6>Modification Metrics:</h6> | ||
| <ul> | ||
| <li><b>One-shot modification success:</b> New feature works on the first attempt (binary).</li> | ||
| <li><b>Architecture preservation:</b> Architecture is maintained after modification (binary).</li> | ||
| <li><b>Modification token consumption:</b> Tokens used for the feature addition.</li> | ||
| <li><b>Final context window size:</b> Context length after modification.</li> | ||
| </ul> | ||
|
|
||
|
|
||
| <h5>How to Monitor Token Usage in Cursor</h5> | ||
| <p> | ||
| As you work with an AI assistant, keeping an eye on token consumption can be insightful. In Cursor, you can typically see the token count for your prompt and the AI's response in the Cursor dashboard. This can help you understand how different instructions and context affect the AI's workload. | ||
| </p> | ||
| <callout label="Find the token count"> | ||
| Where can I see the token count for my interactions with the AI? | ||
| </callout> | ||
|
|
||
| <h5>3.3 Project Setup</h5> | ||
| <p> | ||
| Now, let's set up the necessary files and folders for our experiment. First, create a directory for each architectural pattern we will test. | ||
| </p> | ||
|
|
||
| <callout label="Create architecture directories"> | ||
| Create four new directories: `layered_architecture`, `atomic_composable_architecture`, `vertical_slice_architecture`, and `pipeline_architecture`. | ||
| </callout> | ||
|
|
||
| <p> | ||
| Next, we'll create a single, detailed specification file for the Snake game. This ensures the AI assistant has consistent requirements for each architecture. | ||
| </p> | ||
|
|
||
| <callout label="Create the Snake game specification file"> | ||
| Create a new file named `snake_game.md` with the following content: | ||
|
|
||
| ```markdown | ||
| # Project: Browser-based Snake Game (MVP) | ||
|
|
||
| ## 1. Purpose & Scope | ||
| **Purpose:** To deliver a minimal, fully playable Snake game in a modern browser. | ||
| **Scope:** This MVP includes only the essential features needed for a functional Snake game; it excludes all optional enhancements. | ||
|
|
||
| ## 2. MVP Features | ||
| - **Game Initialization:** A snake of length 3 appears centered on a 20×20 grid. One food item spawns at a random empty cell. | ||
| - **Core Game Loop:** The game updates every 150 ms by default. Each tick involves moving the snake, detecting collisions, and rendering the state. | ||
| - **Controls & Direction Handling:** Use Arrow keys (and/or WASD) to change direction. 180° reversals (e.g., from left to right) are disallowed. | ||
| - **Collision Detection & Game Over:** Hitting a wall or the snake's own body triggers "Game Over." The game loop pauses, an overlay with the final score is shown, and input is disabled until restart. | ||
| - **Scoring Display:** The current score (number of food eaten) is updated in real time above or beside the canvas. | ||
| - **Restart Functionality:** A "Restart" button resets the game to its initial state without reloading the page. | ||
| - **Browser Compatibility:** Supports the latest two major versions of Chrome, Firefox, Edge, and Safari. | ||
|
|
||
| ## 3. Functional Requirements | ||
| - **FR-1:** Initialize the game state with a snake of length 3 at the grid center and one food item. | ||
| - **FR-2:** Implement a game loop that runs at a configurable interval (default: 150 ms). | ||
| - **FR-3:** Capture and queue keyboard events for direction changes; prevent direct reversals. | ||
| - **FR-4:** On each tick: | ||
| 1. Move the snake head one cell in the current direction. | ||
| 2. Check for wall or self-collision; if one occurs, trigger the game-over flow. | ||
| 3. If the head lands on food: increment the score, grow the snake by one segment, and spawn new food. | ||
| 4. Render the updated snake, food, and score. | ||
| - **FR-5:** Display a "Game Over" overlay with the final score and a clickable "Restart" button. | ||
| - **FR-6:** Reset all state (snake position/length, score, food) when the "Restart" button is clicked. | ||
|
|
||
| ## 8. Non-Functional Requirements | ||
| - The canvas should scale to fit the viewport while preserving the cell aspect ratio. | ||
| - Use ES6+ modules to separate game logic from rendering. | ||
| - All interactive elements should be reachable via the keyboard; provide minimal ARIA labels on buttons. | ||
|
|
||
| ## 9. Acceptance Criteria | ||
| - The player can move the snake using the keyboard; the snake cannot reverse direction by 180°. | ||
| - The snake grows when eating food, and the score increments accordingly. | ||
| - Colliding with a wall or itself immediately stops the game and displays the final score. | ||
| - Clicking "Restart" immediately resets and restarts the gameplay. | ||
| - The game works smoothly in Chrome, Firefox, Edge, and Safari without console errors. | ||
| ``` | ||
| </callout> | ||
|
|
||
| <p> Now, let's test each code architecture design in practice. </p> | ||
|
|
||
| <alert> | ||
| The results presented in this course are based on a specific set of tools and models. Your results may differ depending on the IDE, AI assistant, and underlying language model you use. Feel free to experiment with your own settings to see how the architectures perform! | ||
| </alert> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| <!-- Enlighter Metainfo | ||
| { | ||
| "id": 503, | ||
| "title": "Layered Architecture", | ||
| "next_button_title": "Next" | ||
| } | ||
| --> | ||
| <h5>2. Layered Architecture</h5> | ||
| <p> | ||
| The Layered Architecture is a classic and widely-used design pattern. It organizes an application into horizontal layers, each with a specific responsibility. This separation of concerns makes the codebase easier to understand, maintain, and test. | ||
| </p> | ||
| <img style="margin: auto; display: block;" src="https://ucarecdn.com/7c892123-fc13-41e6-a5b1-d67aed2b910f/" alt="Layered Architecture" title="Layered Architecture"> | ||
| <p> | ||
| A typical web application might have three layers: | ||
| </p> | ||
| <ul> | ||
| <li><b>Presentation Layer (UI):</b> Handles all user interface logic.</li> | ||
| <li><b>Business Logic Layer (Domain):</b> Contains the core application logic and business rules.</li> | ||
| <li><b>Data Access Layer:</b> Manages data persistence and retrieval.</li> | ||
| </ul> | ||
| <p> | ||
| Dependencies in this architecture are strict and typically flow in one direction: Presentation → Business Logic → Data Access. | ||
| </p> | ||
|
|
||
| <h5>Advantages</h5> | ||
| <ul> | ||
| <li>High cohesion and low coupling between layers.</li> | ||
| <li>Promotes separation of concerns.</li> | ||
| <li>Well-understood and familiar to many developers (and AIs).</li> | ||
| </ul> | ||
|
|
||
| <h5>Disadvantages</h5> | ||
| <ul> | ||
| <li>Can be rigid; changes may require modifications across multiple layers.</li> | ||
| <li>Can lead to unnecessary complexity for simple applications.</li> | ||
| </ul> | ||
|
|
||
| <h5>Let's Build a Snake Game</h5> | ||
| <p> | ||
| Now, let's use an AI assistant to generate a Snake game using the Layered Architecture. First, we need to provide the AI with the game's specification and the architectural guidelines. The following blocks will create the necessary files. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Скорее, AI agent, а не AI assistant |
||
| </p> | ||
|
|
||
|
|
||
| <callout type="chat"> | ||
|
|
||
| Create a file /layered_architecture/architecture.md. Add the following content: | ||
|
|
||
| You are working in a codebase that MUST follow **Pipeline Architecture (PA)**. | ||
|
|
||
| ───────────────────────────────── | ||
| 🔹 1. Core Idea | ||
| ───────────────────────────────── | ||
| Process data as a linear (or branched) **flow of stages**: | ||
|
|
||
| Source ➜ Stage 1 ➜ Stage 2 ➜ … ➜ Sink | ||
|
|
||
| • Each stage performs ONE atomic transformation, then immediately forwards the record. | ||
| • Stages run concurrently; different records may sit on different stages at the same time. | ||
| • Contracts (schema or typed DTO) between stages are explicit and version-controlled. | ||
|
|
||
| “**Do one thing, pass it on.**” | ||
|
|
||
| ───────────────────────────────── | ||
| 🔹 2. Folder & Naming Rules | ||
| ───────────────────────────────── | ||
| src/ | ||
| ├── pipeline/ | ||
| │ ├── stages/ | ||
| │ │ ├── 00_source.py # emits records | ||
| │ │ ├── 01_validate.py # Stage 1 | ||
| │ │ ├── 02_enrich.py # Stage 2 | ||
| │ │ ├── 03_predict.py # Stage 3 | ||
| │ │ ├── 04_sink.py # final drop-off | ||
| │ │ └── __tests__/ | ||
| │ ├── runner.py # wires queues, sets back-pressure, starts tasks | ||
| │ ├── contracts/ # Avro/Proto/JSON-Schema files | ||
| │ ├── shared/ # generic utils (logging, metrics) | ||
| │ └── config.yaml | ||
| └── README.md | ||
|
|
||
| Convention notes | ||
| • Prefix stage files with a sequence number (**00**, **10**, **20**…) so order is obvious. | ||
|
|
||
| ───────────────────────────────── | ||
| 🔹 3. Dependency Rules | ||
| ───────────────────────────────── | ||
| ✔ Stage → contracts/, shared/, std-lib, third-party libs | ||
| ✘ Stage → another stage’s **implementation** (no “reach-inside”) | ||
| ✘ Cyclic imports among stages or shared code | ||
|
|
||
| ───────────────────────────────── | ||
| 🔹 4. Code Generation & Refactoring | ||
| ───────────────────────────────── | ||
|
|
||
| Create a new stage file or modify exactly ONE stage. | ||
|
|
||
| ───────────────────────────────── | ||
| 🔹 5. Best Practices | ||
| ───────────────────────────────── | ||
| • **Single-Responsibility Stage** – validation ≠ enrichment ≠ ML inference. | ||
| • **Idempotent processing** – a stage can safely re-run on the same record. | ||
| • **Explicit schemas** – Avro/Proto/JSON-Schema stored under contracts/. | ||
| • **Dead-letter queue** – send irrecoverable records to DLQ, don’t stop the flow. | ||
|
|
||
| ───────────────────────────────── | ||
| 🔹 6. Your Role | ||
| ───────────────────────────────── | ||
| Whenever you create or modify code: | ||
|
|
||
| 1. **Identify the affected stage** (or insert a new one). | ||
| 2. **Respect folder structure and dependency rules.** | ||
|
|
||
| </callout> | ||
|
|
||
| <p> | ||
| Now that the files are created, use the following prompt to ask the AI to generate the game. | ||
| </p> | ||
|
|
||
| <callout label="Generate the Snake game"> | ||
| Generate an application based on the description from @/snake_game.md, designed as described in @/layered_architecture/architecture.md. Run the app when you have completed the implementation. | ||
| </callout> | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Возможно, тут стоит предложить пользователю проверить работоспособность самостоятельно, чтобы как-то разбавить теорию - описать, как открыть приложение, какие тест кейсы можно использовать. А уже после описывать результаты моего исследования. |
||
| <p> | ||
| Test the game in your browser to ensure whether all the features are working as expected. | ||
| </p> | ||
|
|
||
| <h5>Results from the Study</h5> | ||
| <p> | ||
| The Layered Architecture achieved a 100% success rate for both initial generation and subsequent modifications. | ||
| </p> | ||
| <table> | ||
| <thead> | ||
| <tr> | ||
| <th>Metric</th> | ||
| <th>Average Result</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <td>One-shot generation success</td> | ||
| <td>5/5 (100%)</td> | ||
| </tr> | ||
| <tr> | ||
| <td>One-shot modification success</td> | ||
| <td>5/5 (100%)</td> | ||
| </tr> | ||
| <tr> | ||
| <td>Architecture adherence (modification)</td> | ||
| <td>5/5 (100%)</td> | ||
| </tr> | ||
| <tr> | ||
| <td>Initial token consumption</td> | ||
| <td>16.22k ↑ / 248k ↓</td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
Uh oh!
There was an error while loading. Please reload this page.