コード構造
なぜこの構造なのか
あえての 8 ファイル構成。
LocalLens は src/ 配下の TypeScript ファイル 8 つで構成されています。
8 は魔法の数字ではありません。各レイヤーに明確な境界を与えつつ、どの
レイヤーも窮屈にしない、最小の分割数がたまたまそれだったというだけです。
このページでは、なぜ1 つのファイルでも、なぜ30のファイルでもないのか を説明します。
1 ファイルではダメな理由
この規模なら 1 ファイル版の LocalLens は誘惑的です。それでも間違いです。 理由が 3 つあります。
- QVAC 連携は UI コードと同じファイルを共有すべきではない。 モデル ライフサイクルには独自の関心事があります。遅延読み込み、フォールバック 選択、ワークスペースの片付け。それらを UI ハンドラに通すと、埋もれるか 重複するかのどちらかになります。
- ファイルアダプタはモデル推論と同じファイルを共有すべきではない。 フォルダ走査やブラウザのファイルピッカー正規化は、embedding ステップとは 独立しています。分けておけば、片方を変えてももう片方に触れずに済みます。
- 境界が見えると読者の助けになる。 コードベースを評価する人や、
拡張を検討する人は、QVAC の表面を知りたければ
src/qvac.tsだけを、 入力を見たければsrc/files.tsだけを、ワークフローを追いたければsrc/locallens.tsだけを読めばよくなります。モノリスは全体を頭に 入れることを強います。
過剰な構造化を避ける理由
LocalLens には意図的に存在しないものがあります。
- 深いフォルダ階層(
src/services/rag/qvac/embeddings/…) - 抽象的なリポジトリインターフェースや「store」インターフェース
- DI フレームワーク
- 早すぎるベクトルデータベース抽象化
- プラグイン機構
bun buildを超えるカスタムビルドパイプライン
大規模アプリならどれも妥当です。しかし、この規模ではいずれもボトルネック ではありません。本物のコードに辿り着く前に読まされる儀式になるだけです。
いま採用している形
| ファイル | 担当 |
|---|---|
domain.ts | 型と AppError。 |
files.ts | ファイル検出と入力の適応。 |
rag.ts | チャンク化と根拠付きプロンプト。 |
qvac.ts | QVAC SDK 連携。 |
store.ts | ローカル JSON 永続化。 |
locallens.ts | プロダクトワークフロー(LocalLensApp)。 |
cli.ts | ターミナルインターフェース。 |
server.ts | HTTP インターフェース。 |
ui/ | ブラウザの操作。 |
次のページでは、各ファイルが持つべきでないものをこの表に追加します。 境界は、その向こう側にあるものが分かるほど守りやすくなります。
ファイルを追加するタイミング
コードの一部に変更理由が 2 つ生まれたら、新しいファイルを追加してください。 モジュールの名前と関係ないことを直すために、そのモジュールに手を入れて いる自分に気づいたら、それがサインです。関係ない方を切り出して、両方に 1 つずつの仕事を持たせてください。