본문으로 건너뛰기
cccskills
무료GitHub에 공개

writing-code

コードを書く時の実装原則(既存パターンの踏襲・deep module 設計・seam・テスタビリティ・シーム限定 TDD・コメント規約・リーダブルコード)。プロダクションコードの差分を作る時に、規模を問わず使用(数行の修正も含む)。

新しい module・関数・エンドポイント・画面の追加、DB への書き込み、認可・入力検証の追加、既存構造を変えるリファクタでは特に。CSS・HTML・テンプレート等のフロントエンド資産も対象。lint・CI 等の設定ファイルだけの変更では使わない。

TypeScript/Python/Go の言語別ガイドを同梱。境界: バグ・エラーの原因調査は systematic-debugging が先、提出前の diff 確認は self-review。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(5)

  • SKILL.md22.4 KB
  • references/comments.md2.4 KB
  • references/go.md2.2 KB
  • references/python.md2.1 KB
  • references/typescript.md4.8 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Writing Code

人間に読みやすいコードは、生成AIにとっても読み・変更しやすい。本スキルは、コードを書く時の設計判断を毎回同じプロセスに固定する。

バグ・エラーの修正では、先に /systematic-debugging スキルで根本原因を特定し、修正の実装段階で本スキルの原則に従う。

実装前ゲート: 既存パターンの確認と踏襲

コードを書き始める前に実行する:

  1. 触るものが同じ既存実装を洗い出して読む — 「同類」は機能の類似ではなく、触るものの同一性で選ぶ。変更が読み書きするもの(テーブル・レコード・セッションキー・URL空間・外部API・共有状態)と、担うUIの役割(フォームの結果表示 / トグル / モーダル / エラー・完了通知)を列挙し、それぞれについて既存の触っている箇所を検索ですべて挙げる。UIも機能も全く違っても、同じレコードを書くなら同類。UI役割が同じものからは、アクセシビリティ属性(role / aria-*)と状態表示の作りを引き継ぐ
  2. 各既存経路が持つガードを列挙して突き合わせる — 洗い出した各経路について、そこにあるガード(認可チェック / ロック / 入力検証 / 履歴記録 / 冪等性 / 削除ガード)を列挙し、自分の経路に要るか要らないかを1つずつ判断する
  3. 新たに依存する共通ラッパーは実装を読む — 自分が新しく呼ぶ共通ラッパー・ミドルウェア・フレームワークAPI(監査ログの計装、トランザクション境界、認可ガード、状態フック等)は、失敗時の挙動・副作用の実行順序・状態が反映されるタイミングを実装で確認する。「型が通る」「登録要件を満たした」は確認したことにならない
  4. 適切な理由がない限り踏襲する — 「シンプルだから」「今回は例外」は理由にならない。本スキルの設計原則と既存パターンが食い違う場合も、既存パターンを優先する
  5. 逸脱はユーザー確認を経てのみ — 既存パターンが明らかな技術的負債になると判断した場合に限り、負債と考える根拠を添えてユーザーに確認を取った上で(Claude Code: AskUserQuestion)逸脱してよい。無断の逸脱は禁止

なぜ「機能の類似」で選んではいけないか: 新機能は見た目が似た画面・似た名前のmoduleに引きずられて選ばれるが、データ整合性を守るガードは同じレコードを書く別機能の側にある。似た画面を1つ読んで「踏襲した」と判断すると、読んだファイルの中で印象に残った部分だけがコピーされ、そのファイルにある他のガードはコピーから漏れる。

このゲートの成果物は「触るもの × 既存経路」の対応表(各経路のガードと、自分の経路での要否・不要な場合の理由)。「既存実装を読んだ」は成果物にしない(1件読めば満たせてしまい、漏れが表に現れないため)。同類が存在しない場合はその旨を記録する。数行の修正では、触るものが1つなら表は1行で足りる。

制約を追加するときの経路網羅

認可チェック・関門・レート制限・redirectガード・バリデーションを新しく置くときは、その制約が守る対象への到達経路を列挙してから実装する。最低限:

  • URL直打ち — 途中の画面を飛ばして到達できるか。フレームワークの評価順(layoutとpage、middlewareとhandler)で制約が先に走るか
  • クライアント側遷移 — soft navigationで制約が再評価されるか、初回描画時にしか評価されないか
  • API直接呼び出し — 画面に置いた制約ではAPIの直接呼び出しを防げない。同じ判定がサーバー側にあるか

1経路にだけ置いた制約は未完成とみなす。 守らない経路があるなら、なぜ守らなくてよいかを書く。

実装前ゲートの2と対になる。ゲート2が「既存の制約 → 新しい経路」への転記漏れを防ぎ、本節が「新しい制約 → 既存の経路」への展開漏れを防ぐ。どちらも「制約 × 経路」の直積が埋まっていないことが原因で、ゲート2と本節のどちらか一方だけでは埋まらない。

検証境界の確定(過剰防御の抑制)

防御的コード(nullチェック・再バリデーション・フォールバック)は局所的には常に正当化できる(「nullかもしれない」)ため、迷い自体を追加の根拠にしない。書く前に保証元を確認する:

  1. 入力ごとに保証元を確認する — 変更が受け取る各入力について「どこで検証済みか」(型・上流のスキーマバリデーション・DB制約・フレームワーク保証)を特定する。保証済みの値には再ガードを書かない(parse, don't validate: 境界で検証して型に落とし、内部は型を信頼する)
  2. 保証が確認できないときは、足すのではなく前提を確認する — 確認せずにガードを足すと検証境界の位置が実装のたびに変わり、防御コードが増え続ける。境界をどこに置くかは既存方針・ユーザーへの確認事項として扱う
  3. 前節との関係 — 経路網羅は「制約を置くべき経路の漏れ」を防ぎ、本節は「保証済み領域への重複配置」を防ぐ。制約は境界に1箇所、内部はゼロが目標

レビュー指摘で防御追加を求められた場合も同じ基準で判断する(保証済みなら却下候補。類型は ~/.claude/context/code-review-checklist.md §16)。

設計語彙(Glossary)

設計判断の記述・議論では以下の用語を正確に使う。コード上の既存命名・フレームワーク公式用語(React component等)はそのまま尊重する(既存パターン踏襲と両立させる)。

  • Module — interfaceとimplementationを持つすべて。スケール非依存: 関数・クラス・パッケージのどれでもよい。設計議論でunit / component / serviceと言い換えない
  • Interface — 呼び出し側がmoduleを正しく使うために知るべき全て。型シグネチャに加え、不変条件・呼び出し順序の制約・エラーモード・必要な設定・性能特性を含む
  • Seam(Feathers) — その場所を編集せずに振る舞いを差し替えられる場所。interfaceを置く位置。boundaryと言わない(DDDのbounded contextと衝突するため)
  • Depth — interfaceにおけるleverage。呼び出し側が学ぶinterface量あたりに引き出せる振る舞いの量。実装行数とinterface行数の比ではない(水増しを誘発するため)
  • Adapter — seamでinterfaceを満たす具体物。役割の名前であり、中身の大小は問わない

設計原則

  1. Deep moduleを設計する — 小さいinterfaceの背後に多くの振る舞いを置く。interfaceを設計する時に自問する: メソッド数を減らせるか / パラメータを単純化できるか / より多くの複雑さを内側に隠せるか
  2. The deletion test — そのmoduleを削除したと想像する。複雑さが消えるなら通過型(pass-through)であり不要。複雑さがN箇所の呼び出し側に再出現するなら、moduleは価値を生んでいる
  3. The interface is the test surface — 呼び出し側とテストは同じseamを通る。interfaceの内側をテストしたくなったら、moduleの形が間違っているサイン
  4. One adapter = hypothetical seam. Two adapters = real seam. — 実際に差し替わらないものにseam(port・抽象層)を作らない。adapterが1つしかないseamはただの間接参照であり、Speculative Generality(投機的一般化)
  5. 依存は生成せず受け取る(DI) — module内部で依存をnew・生成せず、引数で受け取る。時刻・乱数も依存として扱う
  6. 副作用より戻り値 — 引数を変異させたり外部状態を書き換えるより、結果を値として返す。テスト容易性と参照透過性が上がる
  7. 数行のために依存を足さない — 探す順序は AGENTS.md「新しく作る前に」に従う(既存の helper → 標準ライブラリ → 導入済みの依存)。新しい依存は、数行で書ける処理のためには入れない(依存は更新・脆弱性対応・ライセンス確認をずっと払い続ける)
  8. 内部 API を置き換えるときは、同じ変更で呼び出し元を移して旧 API を消す — 外部の利用者がいない限り、互換層を残さない(旧 API が残ると、それを写した新しい呼び出しが増え続ける)。旧 API の振る舞いだけを守っていたテストも消す

リーダブルコード原則

  • 命名: 名前だけで役割が分かること。プロジェクトの用語集(CONTEXT.md等があれば)と一致させ、同じ概念には全体で同じ語を使う
  • 命名は「それが何か」で付け、「どこから来たか・なぜ入ったか」で付けない: 識別子(モジュール・パッケージ・テーブル・変数・設定名)は現在のシステム内での役割・ドメイン概念から命名する。由来・経緯(移行元/連携先のシステム名・案件名・依頼者・新旧や暫定を示す相対語)はWhyであり、コミットログ・ADR・仕様書に置く。識別子に固定化すると、由来を知らない読み手への説明コストと、改名されないまま残る負債になる。公開契約のリソース名は「システムが外に見せている名前」なので機能名として使ってよい。迷ったら命名表を作りユーザー確認(Claude Code: AskUserQuestion)

コメント

How はコード、What はテスト、Why(変更した理由・経緯)はコミットログに置く。コードコメントに残すのは、コードとテストとログのどれにも置けないものだけにする(コメントはコードの変更時に更新されず、古くなってもレビューで気づかれないため)。

  • 既定はコメントを書かない。書くのは Why not(自明な代替案を採らない理由)・隠れた不変条件・外部要因の workaround・lint 抑制の理由・消せる条件つきの TODO・限界を承知で取った近道だけで、1〜2行にする
  • 近道は shortcut: <限界>, <見直す条件> の形で書く。限界と見直す条件の無い近道は、条件に達しても誰も気づかないまま残る
  • 関数名や型の言い換えになる docstring、PR 番号・依頼者・経緯のコメントは書かない(経緯はコミットログ)
  • 他のコードは file:line でなくシンボル名で指す。リポジトリ外の文書や外部ツールの内部記号(画面番号・チケット内の連番)だけを根拠にしない(そのコードだけを読む人が辿れない)
  • 3行以上になりそうなら、先に関数の抽出と命名で表せないか考える
  • 書いたコメントは1つずつ「消すとレビュアーが誤読するか」を問い、誤読しないものは消す
  • 既存ファイルに確立したコメント密度・docstring の形式があればそれに従う

書く例・書かない例は references/comments.md。迷ったときに読む。

テスト規律(シーム限定TDD)

テスト基盤が存在するPJでプロダクションコードを書く時に適用する。適用外: テスト基盤が存在しないPJ / 設定・ドキュメントのみの変更 / UIの微調整。適用外で進めた場合は完了報告にその旨を明示する。

ループの規則

  1. Test at pre-agreed seams — テストを書く前に、テスト対象のseamを列挙する。実装計画(30_plan.md等)にseamが列挙済みならそれを合意とみなし自律実行してよい。計画外の公開interface新設・変更が必要になった時のみユーザーに確認する(Claude Code: AskUserQuestion)
  2. Red before green — 失敗するテストを先に書き、それを通す最小限のコードだけを書く。将来のテストを先取りした投機的実装をしない
  3. Vertical slices — 1テスト→1実装→繰り返し。各テストは前のサイクルの学びに応答するtracer bullet。全テストの先書き(horizontal slicing)は想像上の振る舞いを固定するため行わない
  4. リファクタはループの外 — red→greenのサイクル内でリファクタしない。green後・レビュー段階の責務として分離する

テストの質

  • テストはpublic interfaceを通して振る舞いを検証する。内部実装が全て変わってもテストは変わらないのが良いテスト。良いテストは仕様書のように読める(「user can checkout with valid cart」)
  • トートロジー禁止 — 期待値をコードと同じ方法で再計算しない(expect(add(a, b)).toBe(a + b) は構造的に必ず通る)。期待値は独立した真実源から取る: 既知の正しいリテラル・手計算した例・仕様書
  • 2つの想像上の変更で判定する — 振る舞いを壊す変更(誤った値を返す・副作用を飛ばす・2回実行する)をしても通るテストは何も守っていない。観測できる結果を変えずに内部だけ組み替えると落ちるテストは、実装に縛られている。どちらかに当たるテストは書き直すか消す
  • Mockは外部境界のみ — 外部API・DB(テストDBを優先)・時刻/乱数・ファイルシステム。自分のmodule・内部コラボレータ・自分が制御するものはmockしない。内部をmockしたテストは、振る舞いが変わっていないリファクタで失敗する

Pure関数の回帰テスト固定

Parser / diff / tokenizer / formatter / 日付境界ヘルパー等、入力から出力が決定論的に定まるpure関数を新設・変更する時は、以下を必ず整備する:

  1. 境界値の網羅 — 0 / 空文字 / 空配列 / null / undefined / MAX_SAFE_INTEGER / 極端に長い文字列。日付はtimezone境界 / DST / 閏年。数値はinteger overflow / floating point誤差
  2. CJKとASCIIの両方 — Tokenize / diff / word-wrap等は必ず両方をテスト(片方だけだと日本語圏で失敗するバグを見逃す)
  3. バグ修正時の回帰固定 — 修正したバグの bug-triggering inputを回帰テストとして残す(後日同じロジック変更で再発した時に検出する)
  4. Property-based testingの判断 — Invariantを明示できるロジック(mapToDsl(dslToMap(x)) === x のround-trip、sort(sort(arr)) === sort(arr) のidempotency、可換性、逆演算成立)は fast-check 等を優先。個別ケース列挙より状態空間の網羅性が上がる

Falsy check(言語横断のよくある罠)

  • ID / count / revision番号は 0 を有効値として持ちうる。!!id / if (id) は 0 を無効値として扱う
  • != null(null と undefined のみfalse) をdefaultにする
  • 「truthyチェックかnullチェックか」を意識しない実装が本番バグの典型的な原因。lint rule化を検討する

部分更新の undefined

optionalフィールドを更新処理に渡すとき、undefined が「変更しない」なのか「削除する」なのかを、呼び出し側と保存側の両方で確認する。保存側が全列を書く実装(渡されなかった列を null で埋める)なら、optionalをそのまま渡すと意図しない削除になる。

型は両者を区別しない(どちらも T | undefined)ため、シグネチャを見ても判別できない。保存側の実装を読むまで結論を出さない。

不可逆な状態遷移とコミット後の副作用

一度実行するとユーザーが自力で戻せない状態遷移(確定・昇格・削除・フラグの片道更新)を書くときは、コミットの後ろに並ぶ副作用(外部API呼び出し・通知・キュー投入・別テーブルへの追記)を列挙し、それぞれが失敗したときにユーザーが次に何をできるかを決めてから実装する。

  • コミット済みの遷移に対して「失敗を投げて終わる」は選べない。呼び出し側には失敗に見えるのに状態は進んでおり、再試行は「もう遷移済み」ガードで拒否される。想定内の失敗(期限切れ・既存行との衝突)は救済経路を用意し、想定外はログに記録して完了として扱う
  • 同じ行を触る他経路がロックを取っているかを先に確認する。取っているなら自分も取る(一方の経路だけがロックを取ると、他経路のロックも防御として機能しない)。ロック取得後は、判定に使う前提を読み直してから進める

再実行に耐える操作

状態を変えるスクリプト・ジョブ・移行・起動や停止の処理は、前回の実行が意図したことではなく今ある状態を読み、目標との差分だけを当てる形にする。2回続けて走っても、前回がどこで落ちていても、同じ結果に収束させる(リトライ・再起動・クラッシュが普通に起きる場所で動くため)。

  • 前回が残すもの(ロック・一時ファイル・書きかけのレコード・取りかけのジョブ)は、どこで止まっても次の実行が「古い」と判定できる形にする。一時パスに書いてから rename で置き換える、作成順でなく中身で比べる、など
  • 「残った状態しだい」としか答えられない操作には、状態を突き合わせて直す手順を足す

破壊的操作の参照者

delete / disable / revoke / 無効化 / 全件上書き を書くときは、その対象を今参照している他者を列挙する: 別セッション・別ユーザー・共有済みのURLやトークン・キャッシュ・外部システム。

「今の画面から見て不要」は削除の理由にならない。発行済みのものを無効化する処理は、発行先が自分とは限らない。

アンチパターン(実装中の自己検知)

書いている最中に以下の兆候を検知したら手を止めて設計を見直す。いずれも判断材料でありハード違反ではない。PJの明文規約を常に優先する。

Smell兆候対処
Duplicated Code同じロジックが2箇所以上共通化を検討(3箇所目で必須検討)
Duplicated Stateサーバ/永続層が持つ状態を、クライアントのstateや操作の戻り値にも保持して表示に使う真実源を一方に決める。複製するなら、サーバ側だけが変わる経路(他ユーザーの更新・別タブ・再検証・複合操作の部分的失敗)を列挙し、追従を設計する
Scattered State同期させる boolean が2つ目になる、if/else に分岐を1つ足すだけで機能を追加する、同じ形の前提を複数ファイルで繰り返す状態機械・判別共用体・表(registry)で状態と分岐を1か所に表す。形が今のままで十分小さく、増える見込みが無いなら作らない
Feature Envy他moduleのデータばかり触るメソッドロジックをデータ側へ移す
Primitive Obsessionドメイン概念を裸のstring/intで表現専用型・値オブジェクトへ
Data Clumps同じ引数群がいつも一緒に移動まとめて型にする
Shotgun Surgery1つの変更が多数ファイルに飛散変更が集まるようmoduleを再配置(localityの欠如)
Speculative Generality「いつか使うかも」の抽象層・引数削除(two adapters ruleで判定)
Redundant Guard型・上流・DB制約で保証済みの値への再チェック保証元を確認し、あるなら書かない。無いなら境界(入口)に1箇所置く
Message Chainsa.b().c().d() の連鎖深いinterfaceで隠蔽

言語別ガイド(Read when)

新規module作成・公開interface変更・テスト設計を伴う実装の開始時に、対象言語のガイドをReadする。既存コードの数行修正では読まない。

完了基準

  • 実装前ゲートの対応表が埋まっている(既存パターンから逸脱した箇所はユーザー確認済み)
  • PJ 規定の品質チェック(lint / format / typecheck / test)が通っている
  • 追加したコメント行を1つずつ取捨した(「コメント」節の基準で、残したものは誤読を防ぐものだけ)

出典: obra/superpowers、mattpocock/skills、DietrichGebert/ponytail、cursor/plugins の pstack(いずれもMIT License)を翻案。詳細はリポジトリルートのNOTICE.mdを参照。

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

コードベース全体のレビュー・監査。perf/sec/test/arch/cq/docs の6観点を並列委譲し、優先度付き issue ファイルと観点サマリをメモリディレクトリに生成する。コードベース全体の監査・定期レビュー・リリース前品質確認の依頼時、/codebase-review 実行時に使用。境界: PR 単位は pr-review、自ブランチの提出前確認は self-review。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ukwhatn/.claude42026년 10월 19일 업데이트

commit

무료

変更を git-cz 形式でコミットする。リポジトリの直コミット可否の判定手順と、push 後の CI・conflict の確認を含む。/commit 実行時、「コミットして」「pushして」等の依頼時に使用。--push 引数または「pushして」の依頼で push も行う。境界: PR 作成は create-draft-pr、PR コメントへの対応コミットは pr-comment から呼ばれる。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ukwhatn/.claude42026년 10월 19일 업데이트

PR を Draft で作成する。変更をローカルで動かして確かめ、画面が変わるならスクリーンショットを gh の --attach で貼り、PR テンプレートを全セクション埋めて対象 repo の既存 PR の分量に揃え、出した後は CI・レビュー・マージを Monitor で見張る。PR 作成の依頼時、実装が一段落して PR 化する時、/create-draft-pr 実行時に使用(gh pr create を直接実行しない)。引数でベースブランチを指定できる。境界: 個別レビューコメントへの対応は pr-comment、PR 全体のレビューは pr-review、複数 PR 規模の計画は plan-feature-prs。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ukwhatn/.claude42026년 10월 19일 업데이트

スキルを新規作成する。「スキルを作って」「この手順をスキル化して」等の依頼時、/create-skill 実行時に使用。AGENTS.md・context・既存スキルと整合させ、重複・競合を避ける。境界: 既存スキル・指示ファイルの修正は update-inst、指示ファイル全体の監査は instructions-audit。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ukwhatn/.claude42026년 10월 19일 업데이트

抽象的な要件・事業側の要求を深掘りし、既存実装との整合を確認して実装マスタとシステム要件書を作成する。「こういう機能を作りたい」「この要求を満たす機能を設計して」等の抽象要件の提示時、既存機能の拡張や Phase 分割の要件定義開始時、/design-feature 実行時に使用。境界: 要件確定後の実装計画書・PR 分割と実装進行は plan-feature-prs。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ukwhatn/.claude42026년 10월 19일 업데이트

画面の設計判断(ナビゲーション・重ね方・通知と空状態と読み込み・外枠とトークンと状態表現)の型を決定表で選び、アプリ内の全画面で揃える。画面・ページ・レイアウト・ナビゲーション・ダイアログ・コンポーネントを新しく作る・作り直す時、モックやダッシュボードを作る時、サイドバー・タブ・モーダル・シート・toast・バナー・空状態のどれを使うか決める時に使用。PJ に components.json があれば shadcn の部品とトークンへの対応も扱う。主要なデザインシステム(Material・HIG・Carbon・Primer・Atlassian・Fluent・GOV.UK・NN/g・WAI-ARIA APG・WCAG)の一致点を規則にし、食い違いの採否を定めてある。境界: 画面の文言は writing-ui-text、画面に何を出すかと提示前の完了基準は context/ui-artifact-standards.md、コードの実装原則は writing-code、shadcn 部品の API と組み立ては shadcn。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

ukwhatn/.claude42026년 10월 19일 업데이트

ukwhatn의 스킬 모두 보기

이 스킬의 문제 신고