mcpField
C
code-refinements

code-refinements

github.com/alexandru開発5127 回インストール今日更新
リポジトリ

code-refinements について

code-refinementsは、動作を保ちながらコード設計を簡潔にする原則とルールを定めています。コードをレビューまたはリファクタリングする開発者向けに、制約、単純性、パラメトリシティ、型、性能を扱います。

主な機能

  1. 01コードレビューの三つの観点
  2. 02部分関数呼び出しを避けるルール
  3. 03明示的な型シグネチャ
  4. 04不正状態を排除する設計
  5. 05ホットパスの性能指針
  6. 06スタイルとドキュメントの指針

活用シーン

  1. 01リファクタリング案の評価
  2. 02強い型で置き換えられる実行時チェックの発見
  3. 03絡み合ったコード上の関心事の整理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/alexandru/skills --skill code-refinements

インストール後、Claude Code で/code-refinementsを入力して読み込まれたか確認します。

同梱ファイルreferences/philosophical-foundations.md

詳細

コードの洗練

洗練されたコードは、より少ない設計で同じ仕事をします。誤りうる状態が少なく、絡み合った関心事が少なく、規律に頼るプロパティが少なくなります。取り除けるものは名前を挙げられます。ランタイムチェック、分岐、部分的な呼び出し、パラメーター、保存されたフィールド、重複した定義、2つのコンポーネント間の依存関係、読み手が覚えておく必要のある規約などです。そして、コードに含まれる各型や抽象化は、不要にするチェックや規約によって、その存在意義を示します。行数は尺度ではありません。洗練に伴って行数が減ることはよくありますが、行数に合わせて縮めたコードは洗練されているとは限りません。

最も深い洗練は、整然さではなくモデルにあります。無効な状態を記述できない中核のデータモデル、より劣った設計なら2回必要な処理を1回で済ませること、仕事に必要な範囲を超えないモジュール、シグネチャが担う契約があり、どちら側にもチェックが不要な状態です。エッジケースは分岐ではなくモデルに含めます。ケースごとのチェック、テーブルエントリー、分岐は複雑さであり、洗練ではありません。

観点

それぞれの観点は1つの問いを投げかけ、異なる種類の複雑さに注目します。

制約(Bjarnason、「制約が自由をもたらし、自由が制約となる」)

誤った実装ができないように、どのような自由を取り除けるでしょうか?

コードができることが多いほど、読み手はその動作を予測しにくくなります。あるレベルでの自由は、次のレベルでの制約になります。空のリストを返せる関数があると、すべての呼び出し元がそのケースを処理しなければなりません。共有状態を変更できる関数があると、すべての読み手がその状態を追跡しなければなりません。仕事を果たせる範囲で最も表現力の低い型、シグネチャ、抽象化を選び、その値を作成する場所に制約を置きます。そうすれば、置き換えられたチェックは後続の処理からなくなります。

洗練されたコードでは、無効な状態はコンパイルされないため、それを防ぐチェックは不要です。洗練されていないコードには、型が許容する無効な状態、ランタイムチェックや規約によって維持される不変条件(空でないことを確認した後に最初の要素を取得することや、他のフィールドと一致させる必要のあるフラグ)、保持する値より広すぎる型、実際には使わない機能まで渡される関数、到達できない防御的な分岐が見られます。到達可能な無効状態はバグです。

シンプルさ(Hickey、「シンプルであること、容易であること」)

どの独立した関心事が絡み合っていますか? それらを個別に理解できるでしょうか?

シンプルとは、他の何かと絡み合っていない、単一のまとまりのことです。これは客観的な性質であり、慣れ親しんでいる、またはすぐ手に取れるという意味にすぎない「容易さ」とは別の軸です。読み手が一方について考えるとき、もう一方のことも考えずにはいられないなら、その2つの関心事は複雑に絡み合っています。ファイルを分けるだけでは解決しません。モジュール同士が共有状態、フラグ、規約を通じて絡み合っていることもあるからです。コードを書きやすかったかではなく、実行される成果物を評価してください。

洗練されたコードでは、ある関心事についての問いに、他の関心事のコードを参照せずに答えられます。洗練されていないコードでは、1つの概念を2か所で定義し、キャッシュやサイドマップを説明対象のデータから分離し、高速パスをロジックに織り込み、導出できるフィールドを保存し、値しか必要としないコードに状態を渡し続け、別の場所ですでに決められた判断を条件分岐に埋め込みます。

パラメトリシティ(Wadler、「Theorems for free!」)

型は実際に何を保証し、何が実装上の規律に依存するのでしょうか?

型を定理として読みます。任意の A について、A のリストを A のリストに変換する関数は、A に対する操作を持たないため、要素を削除、複製、並べ替えすることしかできません。したがって、入力に関数を適用してからその関数を呼び出しても、その関数を呼び出してから入力に関数を適用しても、どのような関数についても結果は同じになります。型がより一般的で正確であるほど、より多くのことを証明します。文字列、整数、ブール値のような具体的な型はほとんど何も証明せず、null、キャスト、実行時の型検査、リフレクション、例外、副作用のような抜け道は、型が証明したことを弱めます。それらが持つ性質は、すべて規律に依存します。

洗練されたコードでは、性質はコメント、慣習、呼び出し側のチェックではなく、シグネチャによって保証されます。洗練されていないコードは、順序が重要な名前のないタプル、閉じた集合の代わりに使われる文字列、キャッシュキーに含まれていない引数に依存するキャッシュ結果、調べることのない具体的な型を受け取る関数、そしてシグネチャで強制できる不変条件をコメントだけで述べるコードに頼ります。

ルール

レンズは複雑さに名前を付けます。これらのルールは、その複雑さのないコードの姿を示します。

部分呼び出しをしない

洗練されたコードには部分呼び出し、つまり型が許す入力の一部で失敗する操作がありません。空の可能性があるリストの先頭要素、キーが存在しないと例外を投げるマップや辞書の検索、オプショナル値のチェックなしのアンラップ(Option.get、unwrap()、! による非 null アサーション)、キャスト、ケースを網羅していない match や switch がこれに当たります。型が証明を担います。リストを構築する段階で空でない型を使う、キーの代わりに検索した値を保持する、すべてのケースを網羅する match を使う、といった方法です。オプショナル値は型であり、コードがチェックを忘れないように覚えておく必要のあるセンチネル値ではありません。例外はホットパスだけです。確立された不変条件によって呼び出しが安全であり、安全な形式にすると意味のあるコストが加わることがパフォーマンスの証拠で示される場合に限ります。

明示的なシグネチャ

ローカルヘルパーやラムダを含め、すべての関数に戻り値の型を付けます。すべてのフィールドに宣言型を付けます。型ヒントを任意に付けられる言語では、型ヒントを有効にしておきます。ラムダに戻り値の型を注釈する構文がない場合は、そのラムダのバインディングか、ラムダを受け取るインターフェースに関数型を記述します。注釈は、読み手とコンパイラーに契約を示します。注釈がないのは簡潔さではなく、契約が欠けているということです。

誤った状態を表現できないようにする

バグは、誤った状態が入り込める設計箇所を示します。洗練されたコードでは、そのような状態を認めません。検証するのではなく、パースします。入力を、単なるチェック結果を捨てるのではなく、不変条件の証明を保持する表現に変換します。誤った入力は表現できないか、その種類をすでに処理している仕組みを通して流れます。原因は一つ、仕組みも一つです。不変条件を支える後段の実行時ガードや、特殊ケースを抱えた if は、設計がまだ誤った状態を許していることを示します。

ホットパスを高速に保つ

リクエストごと、エンティティごと、アイテムごと、フィールドごとに実行されるコードは、その処理に必要な以上の仕事を呼び出しごとに行いません。注意すべき兆候は、処理に不要な割り当て、検索の代わりにスキャンを行うこと、一度で済む処理を二度に分けること、あるべき場所に高速パスがないことです。

スタイル

コードは周囲のコードと同じように読み取れるものにします。プロジェクトのフォーマッター、インポートのスタイル、命名規則、慣用表現に従います。コメントは、コードだけでは誤解を招く場合に限って付けます。名前を言い換えるだけのコメントには何の情報もありません。ドキュメントコメントには、シグネチャだけでは示せない契約を、プロジェクトのドキュメントコメントの慣習に従って記述します。

基礎

原典と、パースによって型の証明がどのように保持されるかについては、哲学的な基礎を参照してください。

コメント