コーディング規約はskillよりrulesに書いた方が効いた
tags: claude
AIの精度が上がってきて、仕事で3年以上動いているサービスのずっとやりたいと思っていたリファクタリングを並行して裏で動作させていた。 claude codeでリファクタリングというと、それをうまくやるskillsやmcp、エージェントチームを用いて⋯という話をよく聞くが、rulesを使ってリファクタリングをした所うまく機能してそうという話
先に結論
コーディングルールなどskillにするよりrulesに定義した方がうまく機能している気がするし、継続してコードの追加・変更をしていく際もskillより精度が高く感じている。
たぶんrulesは明確に対象のファイルパスを書くが、skillだと呼び出されたり、呼ばれなかったりの発火依存だったり、広く覚えておくことになるので作業を進めるうちに忘れられてしまうのかもしれないと考えている。
行ったリファクタリングの手順
1. どうあって欲しいのか、理想をrulesとして定義する
例えばreactのコンポーネントの書き方が最近はコーディングルールの定義などで統一されてきたものの、過去作った所は人によってマチマチだったりした所に以下のようなルールを置いた(実際に書いているものの抜粋)
---
paths:
- '/src/**/*.{tsx,jsx}'
---
# Reactコーディングルール
## コンポーネント定義
- **Props命名**: 単一のコンポーネントしか定義していない時はPropsは`XxxProps`ではなく`Props`として定義する
- **コンポーネント定義**: functionを使用する
- memo化する時は`const Xxx = memo(function Xxx() {})`の形式にする
- **Props型**: コンポーネントで利用する時は`Readonly<Props>`とする
- **返り値型**: コンポーネント関数の返り値型は適切に定義する(`JSX.Element`等)
- `JSX`は`react`パッケージからimportすること
## コメント記法(React固有)
- **reactコンポーネントのprops**: Propsの型定義部分に記述する
- **JSDocの役割分担**:
- コンポーネント関数: 概要説明のみ(例: `/** ユーザー情報を表示するコンポーネント */`)
- Props型定義: 各プロパティの詳細説明(例: `/** ユーザー名(例: "田中太郎") */`)
## React実装時チェックリスト
- [ ] exportするコンポーネントにJSDocコメント追加(概要のみ)
- [ ] Props型定義に各プロパティのJSDocコメント追加(詳細説明)
- [ ] アクセシビリティ対応(accessibilityRole, accessibilityLabel)
2. 実際に一部のリファクタリングを指示してみる
あまり具体的にどう直して欲しいかを伝えず「@src/components/xxx をルールに沿ってリファクタリングして」というようなふわっとした指示をする
3. 結果をレビューする
意図した結果になっているのかなどを見て、意図した通りにならなければ修正指示を投げるのではなくルールを修正し、再度結果を見て〜というのを数回繰り返した
ルール定義後の変化
skillでやっていた時はレビュー的に確認してもらっていていたが、ちょこちょこ指摘漏れや考慮漏れなどがあり人間のレビュワーにレビュー指摘をもらっていたが、rulesに定義してからは指摘が減ったというか、そもそも生成されるものがルールに沿った内容が出力されるようになった。
なので仕事のリポジトリではreactのルールだけでなく
- apiディレクトリ専用のルール
- components集があるディレクトリ専用のルール
- uiデザイン用のルール(単位や利用uiフレームワークの話などが書いている)
- swrの定義ルール
- typescriptのコーディングルール
など管理しやすいように分けている。
やってみた成果
今回この形式でやってみて一番成果があったのは、ずっとやりたいと話していたがなかなか時間を確保して手が出せないでいた部分のリファクタリングが大幅に進んだこと。 具体的には歴史的経緯でfetchラッパーの実装(初期版・初期で対応できない機能サポート版・openapiからのコード生成版)とAPIクライアント実装が複数あった所、api用のルールを作ることで一気にopenapiの自動生成版で統合1本化できたことだった。
書いたルール例
ルールの内容としては
- 呼び出しは
ApiClient経由に揃える(fetch 直接はレガシー扱い) - 関数名の形式ルール(
<Name><Version>Apiのように揃える) - 引数は明確にして暗黙の外部依存を作らない(apiClient, parameterなど明確に引数に取るように)
- APIレスポンス → ドメイン型の変換は SWR hooks 側の責務 に寄せる(api層は型変換しない)
- 1ファイル = 1ドメイン(
auth_user.ts,post.tsなど)
まとめ
そんな成果もあり最近はskillを頑張って作る事よりも、rulesを定義しrulesが苦手な処理手順的な所をskillとして定義することによってskillからの変更精度を上げる事ができるようになった。
最終的にはmonorepo化までAIがやってくれないかな〜〜