マトリョーシカ的日常

ワクワクばらまく明日のブログ。

Claude Codeで向き合う WATASHI.mdという開発理念

最近話題になっているClaude CodeをWEB開発に導入することとした。ClaudeCodeとはターミナル上で動作する、AIコーディング支援ツールである。Cursorとは異なり、CLI上で動くツールだ。対話型でコーディングを進めるため、画面の向こうの別の人物とやりとりしているようだ。

AIの利用についてはいまだに賛否両論があるかもしれない。しかし食わず嫌いになってはいけない。

Claude Codeの導入

さて、まずはinstallしよう。

docs.anthropic.com

✻ Welcome to Claude Code!                         │
│                                                   │
│   /help for help, /status for your current setup  │
│                                                   │
│   cwd: /Users/(name)/lytcycle                  │
╰───────────────────────────────────────────────────╯

 Tips for getting started:

 1. Run /init to create a CLAUDE.md file with instructions for Claude
 2. Use Claude to help with file analysis, editing, bash commands and git
 3. Be as specific as you would with another engineer for the best results
 4. ✔ Run /terminal-setup to set up terminal integration

いったいなにからやればいいんだ。

WATASHI.md をつくる

Claude CodeはCLAUDE.md というファイルを参照し、開発方針や注意事項を確認しているらしい。マークダウンファイルなので日本語で書ける。設計仕様書のようなものか。

彼を参考にして、わたしもWATASHI.mdをつくる(宣言する)ことにしよう。

# 理念
1. 常に考える
2. 考えるとは論じることである
3. 余白は論じることを補完する
4. 良さは結果を超える


# 方針
1. 課題を明らかにする
2. なぜその課題を解決するかを論じる
3. 課題解決の手法として複数の選択肢を挙げ、違いを論じる
4. 手法を選択した理由を論じる
5. 用いた手法によって課題が解決されたかを論じる
6. 第三者が出力したコードを扱うときは十分に理解して使う
7. 「十分に理解」とは、自分の言葉で説明ができるということである
8. 方針はアップデートされる

理念について

理念は私の中の大きな枠組みである。理念に基づき方針が決定された。何事も文章にすることで、理解は進むし、コーディングの腕も上がるはずだ。

思考とは言語。これはウィトゲンシュタインが同様のことを述べている。

matoyomi.hatenablog.com

余白と良さについては私の過去の記事を参考にした。常に考えるには、余白というか休息も必要だ。そして最後に決定を下すのは自分の心であり、良さである。これは道徳的観点や単純な趣味嗜好も含まれる。

matoyomi.hatenablog.com

方針について

実際にコードを書く上での方針である。開発とは課題解決である。そのため課題を明らかにし、ほんとうにその課題は解決される必要があるかも考えないといけない。コーディングはそれからの話だ。

方針に基づいた開発

課題と選択肢の提示

今回はERBファイルのlintツールを導入することとした。今までもlintは行っていたが、erbファイルは対象にしていなかった。コードの保守性を向上させるため、導入する。

手法はいくつかある。無難にerb-lint gemを導入する。他の選択肢を含めた表を以下にまとめた。

ツール名 主な用途 備考
erb-lint ERB用の総合的なLinter 最も一般的
haml-lint + 変換 間接的なチェック Hamlは使っていないので選択肢から除外
rubocop + Ruby抽出 埋め込みRubyコードのLint Ruby部分しか使えない
htmlhint HTML構文のLint HTMLしか使えない
prettier-plugin-erb フォーマッタ 整形に特化/ https://prettier.io/docs/plugins

フォーマッタは使えそうだ。また次回にしよう。

実装

まずは以下のgemをGemfileに記載し、bundle install を行う。

GitHub - Shopify/erb_lint: Lint your ERB or HTML files

Gemfile

group :development do
  gem 'erb_lint', require: false
# 略
end

設定ファイルである.erb_lint.yml を作成する。readmeに記載している better_html_config: .better-html.yml は消す。これは別のgemであるbetter_htmlを用いる設定だ。

.erb_lint.yml

---
EnableDefaultLinters: true
linters:
  ErbSafety:
    enabled: true
   #  better_html_config: .better-html.yml ここは削除
  Rubocop:
    enabled: true
    rubocop_config:
      inherit_from:
        - .rubocop.yml

lintから除外するファイルの設定

$ bundle exec erb_lint --lint-all を実行すると、700件以上の修正箇所が発見された。多すぎると差分がわからなくなるので、いくつかのファイルをerb-lintの対象から除外する。例えば /app/views/simulations/ 以下のerbファイルは数が多いので今日はやめる。 様子を見ながら、除外の対象を減らそう。

---
EnableDefaultLinters: true
exclude:
  - '**/vendor/**/*'
  - '**/node_modules/**/*'
  - '**/app/views/simulations/*'
  - '**/app/views/layouts/*'
  - '**/app/views/devise/*'
  - '**/app/views/terms/show.html.erb'
linters:
  ErbSafety:
    enabled: true

# 略....

erbタグが消える

lintを実行すると、必要なerbタグ自体がなくなっていた。もう一度ドキュメントを読むと、以下の記述があった。

Note: Each ruby statement (between ERB tags <% ... %>) is parsed and analyzed independently of each other. Any rule that requires a broader context can trigger false positives (e.g. Lint/UselessAssignment will complaint for an assignment even if used in a subsequent ERB tag).

https://github.com/Shopify/erb_lint?tab=readme-ov-file#rubocop

<% などは独立したコードとして解析されるようだ。.erb_lint.yml に除外するルールを追加して対処する。

linters:
  ErbSafety:
    enabled: true

  Rubocop:
    enabled: true
    rubocop_config:
      inherit_from:
        - .rubocop.yml
      Layout/InitialIndentation:
        Enabled: false
      Layout/LineLength:
        Enabled: false
      Layout/TrailingEmptyLines:
        Enabled: false
      Layout/TrailingWhitespace:
        Enabled: false

bundle exec erb_lint --lint-allを実行し、指摘事項を確認したら、bundle exec erb_lint --lint-all -a を実施する。

できた。

Github Actionsへ適用

erb-lintをGithub Actionsに適用する。リポジトリにpushすると、他のlintやテストと共に実行されるようになる。

.github/workflows/testandlint.yml

name: "Ruby on Rails CI"
on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]
jobs:
  test:
# 略
      - name: erb lint
        run: bundle exec erb_lint --lint-all

これでできた。

終わりに

導入するだけしたが、結局今回はClaude Codeを使っていなかった。しかしこの記事でもって、私の開発方針というか理念が定まった。これを軸としてAIと共にコードに向き合うこととする。

Unsplash Peter Thomas