|
| 1 | +# Gemini Code-Gen Best Practices for This Project |
| 2 | + |
| 3 | +This document outlines the best practices and coding standards to be followed |
| 4 | +during the development of this Flutter project. Adhering to these guidelines |
| 5 | +will ensure the codebase is clean, maintainable, and scalable. |
| 6 | + |
| 7 | +## Architectural Principles |
| 8 | + |
| 9 | +- **DRY (Don’t Repeat Yourself)** – eliminate duplicated logic by extracting |
| 10 | + shared utilities and modules. |
| 11 | +- **Separation of Concerns** – each module should handle one distinct |
| 12 | + responsibility. |
| 13 | +- **Single Responsibility Principle (SRP)** – every class/module/function/file |
| 14 | + should have exactly one reason to change. |
| 15 | +- **Clear Abstractions & Contracts** – expose intent through small, stable |
| 16 | + interfaces and hide implementation details. |
| 17 | +- **Low Coupling, High Cohesion** – keep modules self-contained, minimize |
| 18 | + cross-dependencies. |
| 19 | +- **Scalability & Statelessness** – design components to scale horizontally and |
| 20 | + prefer stateless services when possible. |
| 21 | +- **Observability & Testability** – build in logging, metrics, tracing, and |
| 22 | + ensure components can be unit/integration tested. |
| 23 | +- **KISS (Keep It Simple, Sir)** - keep solutions as simple as possible. |
| 24 | +- **YAGNI (You're Not Gonna Need It)** – avoid speculative complexity or |
| 25 | + over-engineering. |
| 26 | + |
| 27 | +## Coding Standards |
| 28 | + |
| 29 | +### Linting |
| 30 | +This project uses the standard set of lints provided by the `flutter_lints` |
| 31 | +package. Ensure that all code adheres to these rules to maintain code quality |
| 32 | +and consistency. Run `flutter analyze` frequently to check for linting issues. |
| 33 | + |
| 34 | +### Naming Conventions |
| 35 | +- **Files:** Use `snake_case` for file names (e.g., `user_profile.dart`). |
| 36 | +- **Classes:** Use `PascalCase` for classes (e.g., `UserProfile`). |
| 37 | +- **Methods and Variables:** Use `camelCase` for methods and variables (e.g., |
| 38 | + `getUserProfile`). |
| 39 | +- **Constants:** Use `camelCase` for constants (e.g., `defaultTimeout`). |
| 40 | + |
| 41 | +### Cross-Platform Compatibility |
| 42 | +This application targets Android, iOS, web, and macOS. All code must be written |
| 43 | +to be platform-agnostic. |
| 44 | + |
| 45 | +- **Avoid Platform-Specific APIs:** Do not use platform-specific libraries or |
| 46 | + APIs directly (e.g., `dart:io`'s `File` class for UI rendering). When |
| 47 | + platform-specific code is unavoidable, it is abstracted away behind a common |
| 48 | + interface using an adapter pattern, as seen in the `lib/platform` directory. |
| 49 | +- **Use Flutter-Native Solutions:** Prefer Flutter's built-in, cross-platform |
| 50 | + widgets and utilities (e.g., `Image.memory` with byte data for displaying |
| 51 | + images from `image_picker`, which works on all platforms). |
| 52 | +- **Verify Plugin Compatibility:** Before using a new package, ensure it |
| 53 | + supports all target platforms (Android, iOS, web). |
| 54 | + |
| 55 | +### Don't Swallow Errors |
| 56 | +- **Don't Swallow Errors** by catching expections, silently filling in required |
| 57 | + but missing values or adding timeouts when something hangs unexpectedly. All |
| 58 | + of those are exceptions that should be thrown so that the errors can be seen, |
| 59 | + root causes can be found and fixes can be applied. |
| 60 | +- **Use Assertions for Invariants:** Use `assert` statements to validate |
| 61 | + assumptions and logical invariants in your code. For example, if a function |
| 62 | + requires a list to be non-empty before proceeding, assert that condition at |
| 63 | + the beginning of the function. This practice turns potential silent failures |
| 64 | + into loud, immediate errors during development, making complex bugs |
| 65 | + significantly easier to track down. |
| 66 | + |
| 67 | +### Null Value Handling |
| 68 | +- Prefer using required parameters in constructors and methods when a value is |
| 69 | + not expected to be null. |
| 70 | +- When the compiler requires a non-null value and you are certain a value is not |
| 71 | + null at that point, use the `!` (bang) operator. This turns invalid null |
| 72 | + assumptions into runtime exceptions, making them easier to find and fix. |
| 73 | +- Avoid providing default values for nullable types simply to satisfy the |
| 74 | + compiler, as this can hide underlying data issues. |
| 75 | + |
| 76 | +### Widget Development |
| 77 | +- **`const` Constructors:** Use `const` constructors for widgets whenever |
| 78 | + possible to improve performance by allowing Flutter to cache and reuse widget |
| 79 | + instances. |
| 80 | +- **Break Down Large Widgets:** Decompose large widget build methods into |
| 81 | + smaller, more manageable widgets. This improves readability, reusability, and |
| 82 | + performance. |
| 83 | + |
| 84 | +### No Placeholder Code |
| 85 | +- We're building production code here, not toys. Avoid placeholder code. |
| 86 | + |
| 87 | +### No Comments for Removed Functionality |
| 88 | +- The source is not the place to keep a history of what's changed; it's the |
| 89 | + place to implement the current requirements only. Use version control for |
| 90 | + history. |
| 91 | + |
| 92 | +## Styling and Theming |
| 93 | + |
| 94 | +### Avoid Hardcoded Values |
| 95 | +- **Do not** hardcode colors, dimensions, text styles, or other style values |
| 96 | + directly in widgets. |
| 97 | +- All centralized style-related code should be consolidated into |
| 98 | + `lib/styles.dart`. |
| 99 | +- Create descriptive, `camelCase` constants in a dedicated `lib/styles.dart` |
| 100 | + file for any reusable style values that are not part of the main theme. |
| 101 | + |
| 102 | +### Theme Architecture |
| 103 | +- The app uses Material Design 3 with a centralized theme defined in |
| 104 | + `main.dart`. |
| 105 | +- All UI components should inherit styles from this central theme. Avoid custom, |
| 106 | + one-off styling for individual widgets. |
| 107 | +- Only use per-widget theme or style overrides when a particular widget requires |
| 108 | + a value that is explicitly different from the application-wide theme (e.g., a |
| 109 | + special-purpose button with a unique color). |
| 110 | + |
| 111 | +#### Prioritize Blame Correctly |
| 112 | +When debugging, assume the bug is in the local, new, application-specific code |
| 113 | +before assuming a bug in a mature framework. |
| 114 | + |
| 115 | +## State Management |
| 116 | +- **Provider:** use the provider package for state management |
| 117 | + |
| 118 | +## Testing |
| 119 | +- Write unit tests for business logic (e.g., services, state management |
| 120 | + controllers). |
| 121 | +- Write widget tests to verify the UI and interactions of your widgets. |
| 122 | +- Aim for a reasonable level of test coverage to ensure application stability |
| 123 | + and prevent regressions. |
| 124 | + |
| 125 | +## Project Structure |
| 126 | +- **`lib/`**: Contains all Dart code. |
| 127 | + - **`main.dart`**: The application entry point and theme definition. |
| 128 | + - **`styles.dart`**: Centralized file for style constants. |
| 129 | + - **`models/`**: Directory for data model classes. |
| 130 | + - `clue_answer.dart`: Model for a clue and its answer. |
| 131 | + - `clue.dart`: Model for a single clue. |
| 132 | + - `crossword_data.dart`: Model for the entire crossword puzzle data. |
| 133 | + - `crossword_grid.dart`: Model for the crossword grid. |
| 134 | + - `crossword_state.dart`: State management for the crossword puzzle. |
| 135 | + - `grid_cell.dart`: Model for a single cell in the grid. |
| 136 | + - `todo_item.dart`: (likely unused example code) |
| 137 | + - **`platform/`**: Platform-specific implementations. |
| 138 | + - `platform_io.dart`: IO-specific implementation. |
| 139 | + - `platform_web.dart`: Web-specific implementation. |
| 140 | + - `platform.dart`: Common platform interface. |
| 141 | + - **`screens/`**: Top-level screen widgets. |
| 142 | + - `crossword_screen.dart`: The main screen of the application. |
| 143 | + - **`services/`**: Business logic services. |
| 144 | + - `gemini_service.dart`: Service for interacting with the Gemini API. |
| 145 | + - `image_picker_service.dart`: Service for picking images. |
| 146 | + - `puzzle_solver.dart`: Service for solving the puzzle. |
| 147 | + - **`widgets/`**: Reusable, shared widgets. |
| 148 | + - `clue_list.dart`: Widget for displaying the list of clues. |
| 149 | + - `grid_view.dart`: Widget for displaying the crossword grid. |
| 150 | + - `step_state_base.dart`: Base class for step state management. |
| 151 | + - `step1_select_image.dart`: Widget for the first step (selecting an image). |
| 152 | + - `step2_verify_grid_size.dart`: Widget for the second step (verifying grid |
| 153 | + size). |
| 154 | + - `step3_verify_grid_contents.dart`: Widget for the third step (verifying |
| 155 | + grid contents). |
| 156 | + - `step4_verify_clue_text.dart`: Widget for the fourth step (verifying clue |
| 157 | + text). |
| 158 | + - `step5_solve_puzzle.dart`: Widget for the fifth step (solving the puzzle). |
| 159 | + - `todo_list_widget.dart`: (likely unused example code) |
| 160 | +- **`assets/`**: Contains static assets like images and fonts. |
| 161 | +- **`test/`**: Contains tests for the application. |
| 162 | +- **`web/`**: Contains web-specific files. |
| 163 | +- **`macos/`**: Contains macOS-specific files. |
| 164 | +- **`specs/`**: Contains project specifications and design documents. |
| 165 | + |
| 166 | +## Technical Accuracy and Verification |
| 167 | + |
| 168 | +To ensure the highest level of accuracy, the following verification steps are |
| 169 | +mandatory when dealing with technical details like API names, library versions, |
| 170 | +or other critical identifiers. |
| 171 | + |
| 172 | +1. **Prioritize Primary Sources:** Official documentation, API references, and |
| 173 | + the project's own source code are the highest authority. Information from |
| 174 | + secondary sources (e.g., blog posts, forum answers) must be cross-verified |
| 175 | + against a primary source before being used. When a user provides a link to |
| 176 | + official documentation, it must be treated as the ground truth. |
| 177 | + |
| 178 | +2. **Mandate Exact Identifier Verification:** When using a specific |
| 179 | + identifier—such as a model name, package version, or function name—you must |
| 180 | + find and use the **exact, literal string** from the primary source. Do not |
| 181 | + shorten, paraphrase, or infer the name from surrounding text or titles. |
| 182 | + |
| 183 | +3. **Quote Before Use:** Before implementing a critical identifier obtained |
| 184 | + from documentation, you must first quote the specific line or code block |
| 185 | + from the source that confirms the identifier. This acts as a final |
| 186 | + verification step to ensure you have found the precise value. |
| 187 | + |
| 188 | +## Project-Specific Implementation |
| 189 | + |
| 190 | +This Crossword Companion project serves as a practical example of the principles |
| 191 | +outlined above: |
| 192 | + |
| 193 | +- **State Management:** The application uses the `provider` package for state |
| 194 | + management, with a central `CrosswordState` class that acts as a |
| 195 | + `ChangeNotifier`. This single source of truth manages the application's |
| 196 | + data, such as the puzzle details and solver status. |
| 197 | + |
| 198 | +- **Event-Driven Navigation:** Step transitions are handled by a robust |
| 199 | + two-phase state machine (`enteringStep`/`enteredStep`) within |
| 200 | + `CrosswordState`. This allows each step widget to listen for when it is |
| 201 | + being entered and run its own initialization logic in a self-contained |
| 202 | + manner. |
| 203 | + |
| 204 | +- **Abstracted State Management:** To adhere to the DRY principle, the common |
| 205 | + state management logic for each stepper page is encapsulated in a |
| 206 | + `StepStateBase` abstract class. This base class handles the listener |
| 207 | + registration and the two-phase state machine logic for entering a step. Each |
| 208 | + step's state class then extends this base class and provides its `stepIndex` |
| 209 | + and the specific logic to execute when the step is entered. |
| 210 | + |
| 211 | +- **Widget Decomposition:** The UI is broken down into small, single-purpose |
| 212 | + widgets. For example, the main `CrosswordScreen` is composed of a `Stepper` |
| 213 | + widget, which in turn uses a series of `Step...Content` widgets for each |
| 214 | + step in the process. This makes the code more readable, reusable, and easier |
| 215 | + to test. |
| 216 | + |
| 217 | +- **Centralized Theme:** The application's theme is defined in `main.dart` and |
| 218 | + applied to the entire `MaterialApp`. This ensures a consistent look and feel |
| 219 | + across all widgets and avoids hardcoded style values. |
| 220 | + |
| 221 | +- **Services:** Business logic is separated into a `GeminiService`. This |
| 222 | + service is configured with a detailed system prompt that instructs the |
| 223 | + `gemini-2.5-flash` model to act as a crossword-solving expert. This |
| 224 | + decouples the UI from the underlying AI logic, making the code more modular |
| 225 | + and easier to maintain. |
| 226 | + |
| 227 | +- **App-Driven Solving:** The puzzle-solving logic is not a simple API call |
| 228 | + but an intelligent, app-driven loop managed by a dedicated `PuzzleSolver` |
| 229 | + service, which is coordinated by `CrosswordState`. For each clue, the app |
| 230 | + calculates the word's length and current letter pattern from the grid. It |
| 231 | + then sends a highly focused prompt to the expert model. The app validates |
| 232 | + the model's response, updates the grid, and automatically retries clues that |
| 233 | + were answered incorrectly, creating a robust and resilient solving process. |
| 234 | + |
| 235 | +## Verification and Maintenance |
| 236 | + |
| 237 | +### Post-Change Verification |
| 238 | +After any significant refactoring or feature addition, the following steps are |
| 239 | +required to maintain code quality: |
| 240 | + |
| 241 | +1. **Run Static Analysis:** Execute `dart analyze` and fix all reported issues. |
| 242 | +2. **Audit Against Best Practices:** Review the changes against the principles |
| 243 | + outlined in the "Architectural Principles" and "Coding Standards" sections |
| 244 | + of this document to ensure the code remains clean, robust, and maintainable. |
| 245 | + |
| 246 | +## Git Workflow |
| 247 | + |
| 248 | +- **Committing Changes:** After the changes are complete and verified, I will not |
| 249 | + commit them to the repository. You, the user, are responsible for all git |
| 250 | + commits. |
0 commit comments