

Aravind Putrevu
October 15, 2024
8 min read
優れたチームはコーディング規約を採用し、さらに優れたチームはそれを習慣にします。厳しい期限や機能を早く出すプレッシャーのため、コーディング規約は後回しになりがちです。しかし、規約を軽視すると保守性が下がり、バグ率が上がるなど、後に多くの問題が生じます。
コーディング規約とは、コードベース内でコードをどう記述・整理するかを定める指針、ベストプラクティス、慣例です。命名規則、フォーマット、アーキテクチャパターンなどを扱い、コードベースの一貫性、可読性、保守性を高めることを主な目的とします。
規約に従うことは、目隠しをして迷路を進むように感じられ、迷ったり苛立ったりしがちです。道筋を明確に案内するガイドがいたらどうでしょうか。
AST Grepと生成AIの組み合わせは、コード品質の維持を自動化・簡素化する強力な道具になります。
本稿では、AST Grepと生成AIを使ってコーディング規約をコード化し、あらゆるプログラミング言語で書かれたコードの品質を効率化する方法を説明します。
Linterはコード品質を陰で支える存在です。静的コード解析ツールは数十年にわたり、品質問題への最初の防衛線として、コードベースを走査し、潜在的な問題を指摘し、セキュリティへの影響からスタイルや慣例までの規約を適用してきました。
Linterには、細かな問題やスタイルの不統一を容赦なく指摘する、うるさいツールという評判があります。開発者は解析結果を評価しながら、絶え間なく届く警告やエラーを疎ましく思うという、愛憎入り混じった関係になりがちです。

そのノイズの下で、Linterはクリーンで一貫性があり、保守しやすいコードを書くよう絶えず促します。ベストプラクティスへ導き、技術的負債の蓄積を防ぎます。
各プログラミング言語で使える強力なLinterの例を紹介します。
biome.config.jsまたはbiome.config.tsを使います。pyproject.tomlまたは.ruff.tomlを使います。phpstan.neonまたはphpstan.neon.distで設定できます。Linterごとに個別設定が必要で、複雑さ、一貫性、組織の規約との競合、粒度、保守方法も異なります。
現在は画像、文章、音声、さらにはコードまで生成できる時代です。コードを神聖視する開発者にとっても、ボタン一つでコードが生成されるようになりました。深い推論能力を持つ強力な大規模言語モデル(LLM)は、要件に合う文脈的なコードを生成します。

LLMはコードだけでなく、YAMLやDockerfile、lint設定などのツール仕様も生成できます。
AIコーディングアシスタントの普及により、開発者はかつてないほど多くの機能を書いています。ただし、生成コードにはバグが残り、組織固有の要件や規約に完全には合わない場合があります。生成されたLinter設定も、組織の指針に合わせたルールほど効果的でないことがあります。
そのため、Linterとコードレビューの役割は依然として重要です。この両面の課題も、生成AIを使って解決できます。
AST Grepは、正規表現に似た簡潔なクエリ言語で独自ルールを書き、コードパターンを照合できる強力なツールです。次のPythonコードを例に、パターン検出を見てみましょう。
def authenticate(username, password):
if username == "admin" and password == "supersecret":
return True
return False
// secret_detector.yml
id: detect-hardcoded-credentials
language: python
rule:
pattern: |-
def $FUNC_NAME($USERNAME, $PASSWORD):
if $USERNAME == "$USER_VALUE" and $PASSWORD == "$PASS_VALUE":
return True
return False
message: "Hardcoded credentials detected in authentication function"
severity: warning
sg --rule-file secret_detector.yml /path/to/your/python/files
sample_code.py: Potential hardcoded secret detected
if username == "admin" and password == "supersecret":
^^^^^^^^^^^^^^^^^^^^^^^^
注:このルールはAST Grep playgroundで実行できます。
より複雑なAST Grepパターンを書き、リポジトリや組織固有のコーディング規約とベストプラクティスを適用できます。
AST Grepは規約の適用だけでなく、コードフローの背景にある洞察や論理を得るためにも使えます。組織では、過去のインシデントを踏まえた重要な事業判断がコードへ反映されます。対象を絞ったパターンにより、アーキテクチャ上の判断や潜在的な性能ボトルネックをコード化できます。
例えば、関数がネットワーク呼び出しを行うか検出するとします。
id: detect-requests-get
language: Python
rule:
pattern: |-
(call
function: (attribute
object: (identifier) @MODULE
attribute: (identifier) @FUNCTION))
constraints:
MODULE:
regex: ^requests$
FUNCTION:
regex: ^get$
message: "HTTP GET request detected. Ensure proper error handling and consider security implications."
severity: warning
このルールは、requestsモジュールでGETリクエストを行う関数呼び出し、つまりネットワーク呼び出しを探します。複雑または文書化の不十分なコードでも、コードベース全体から検出できます。
同様に、AST Grepルールで次を検出できます。
async/awaitの使用など)コード断片の意図を理解すれば、リファクタリング、最適化、アーキテクチャ変更について、より適切に判断できます。
AST Grepでコードの意図を発見する方法を見たので、次に生成AIと組み合わせ、通常のlintルールより良い結果を得る方法を説明します。
一般的な検索拡張生成(RAG)では、検索した情報をLLMへ追加し、文脈に基づく回答を生成させます。検索した文脈(ベクトル化データ)は事実情報でLLMを接地し、ハルシネーションを減らします。人間とは異なり、LLMが誤った、または一貫しない情報を出す確率は、問題が複雑になるほど上がるためです。
AST GrepとRAGを組み合わせると、解析対象コードについて関連性が高く、焦点の合った文脈をLLMへ渡せます。AST Grepが特定のパターン、アーキテクチャ上の判断、潜在的な問題を抽出し、追加文脈として渡すことで、問題へのワンクリック修正も提案できます。
lintルールを一つも書かずに、複雑なコード問題の理解、発見、修正提案が可能になります。
コードベース内のデータベースクエリを見つける次のルールを例にします。
id: parameterised-db-query
language: python
rule:
pattern: $RESULTS = $DB.query($QUERY, $PARAM)
message: "Consider using parameterized queries for better security"
severity: WARNING
fix: |-
$RESULTS = $DB.execute($QUERY, ($PARAM,))
AST Grepは次のようなコードを見つけます。
results = db.query("SELECT * FROM users WHERE id = ?", user_id)
周辺の文脈とともにRAGの一部としてLLMへ渡すと、コードと意図を解析し、ベストプラクティスや規約に基づいて提案や問題の特定を行います。この例では、保守性を高め、SQLインジェクション攻撃を受けにくくするため、SQLAlchemyのようなORMライブラリを提案するかもしれません。
user = User.query.filter_by(id=user_id).first()
この方法は、従来のLinterルールよりノイズを減らし、繊細で知的なフィードバックを可能にします。LLMは提案の説明や根拠も示せます。
CodeRabbitでは、RAGとAST Grepの組み合わせが規約適用の強力な方法になると考えています。生成AIモデルの主な課題は、整合性があり文脈に合う出力でも、コードベース固有の要件には必ずしも一致しないことです。そこで決定論的な接地が役立ちます。

AST Grepでパターンだけでなく、変数名、関数シグネチャ、依存関係など、コードに関する具体的で決定論的な情報を抽出し、LLMへ現実に即した文脈を渡します。提案のノイズとばらつきが抑えられ、既存の設定内で構文的・意味的に有効な提案を生成するよう導けます。
データベースクエリの例では、ORMライブラリを使うLLMの提案は文脈に合っています。開発者は提案を確認し、コードを書き直さずワンクリックで適用できます。
「自分のプロジェクトでどう使えばよいのか」と思うかもしれません。CodeRabbitは、GitHub、GitLab、Azure DevOpsなど既存のコードホスティングプラットフォームで動くAIコードレビューです。
CodeRabbitはこの概念を、コードとともに開発者の生産性を高める強力なツールへ変えました。AIネイティブなコードレビューがLLMとAST Grepの可能性を活用します。
開発者コミュニティ向けに、独自のAST Grepルールをast-grep-essentials GitHubリポジトリで公開・保守しています。ぜひスターを付けてください。CodeRabbitへ登録し、AIによるコード品質向上を始めましょう。