用語解説
第22章 既存プロダクト改善
この章では、すでに動いているプロダクトを壊さずに変える型を学ぶ。題材は学習ログ整理アプリに「支援ステータス機能(status)」を追加する改善である。ここでは、その改善作業で出てくる一般的な専門用語を解説する。
現在の約束
- 読み:げんざいのやくそく
- 一言で言うと:既存プロダクトで、利用者や開発者がすでに頼りにしている動作、データ、手順。
- くわしく:現在の約束は、契約書のように明文化されたものだけではない。README通りに起動できる、ログを作成できる、既存ログが一覧に表示される、既存データが読める、エラー時に画面が壊れない、といったことも約束である。既存改善では、新しい機能だけでなく、この約束を守る必要がある。約束は記憶ではなく、README、画面確認、テスト結果、確認ログなどの証拠で扱う。
- 具体例:status追加前に「ログ作成後に一覧へ表示される」「README手順でlocalhostを開ける」を確認し、変更後も同じ確認を行う。
- つまずきやすい点:自分が作った小さなアプリだから、既存動作を確認せずに変えてよいと考える。
- 関連語:既存振る舞い(第22章)、回帰確認(第22章)、verification log(第21章)
- テキスト本文での登場箇所:第22章「既存プロダクトとは、現在の約束を持つソフトウェアである」
status contract
- 読み:ステータス コントラクト(status contract)
- 一言で言うと:statusの値、意味、表示名、作られるタイミング、既存データの扱いをそろえた小さな仕様契約。
- くわしく:statusのような小さなfieldでも、UI、API、DB、テスト、READMEで表記や意味がずれると不具合になる。status contractでは、
draft、learned、needs-helpのような許可値、利用者向け表示、default、既存ログをどう扱うか、不正値をどう拒否するかを一つの表にする。これは大げさな設計書ではなく、変更中のズレを防ぐための確認表である。 - 具体例:
needs-helpはAPI値、画面表示は「相談したい」、既存ログには明示されず、statusなしはlearnedとして扱う、と書く。 - つまずきやすい点:画面では「help」、DBでは
needs_help、READMEではneeds-helpのように表記が割れる。 - 関連語:validation(第11章・第14章)、互換性(第22章)、acceptance criteria(第9章)
- テキスト本文での登場箇所:第22章「変更要求は、そのまま実装しない」
characterization test
- 読み:キャラクタライゼーション テスト/characterization test(特性化テスト)
- 一言で言うと:今のアプリがどう動いているかを記録して、その動きを固定するテストである。
- くわしく:既存プロダクトを変えるとき、変更前の振る舞いが分からないと、変更後に何が壊れたか判断できない。characterization testは「今こう動いている」という事実をそのままテストにする。正しい仕様かどうかは問わず、現在の動きを証拠として残すことが目的である。Michael Feathersが既存コードを安全に扱う方法として広めた考え方である。既存テストが少ないとき、まず壊したくない動きを一つテストにすると、改善中の事故に早く気づける。
- 具体例:支援ステータス機能を追加する前に、「ログを作成したあと一覧に表示される」という既存の主要動線をテストにする(create log then list logs)。statusを足した後も、この動線が壊れていないことを確認できる。
- つまずきやすい点:正しい仕様を書くテストと混同しやすいが、目的は現在の動きの記録であり、理想の動きを書くものではない。
- 関連語:回帰確認/regression test(第8章・第13章)、リファクタリング(第8章)
- テキスト本文での登場箇所:第22章「回帰確認は、変えていないはずの価値を見る」
backfill
- 読み:バックフィル/backfill
- 一言で言うと:既存データへ、あとから値を埋める作業である。
- くわしく:新しいfield(列)を追加すると、古いデータにはその値がない。backfillは、その空いている部分に後からまとめて値を入れることである。これをしないと、古いデータが新しい仕組みでうまく扱えず、一覧から消えるなどの不具合が起きることがある。backfillは必須ではなく、nullableやdefault、読み取り時の補完など他の選び方もあるので、状況に応じて判断する。判断した内容はmigration noteに残す。
- 具体例:学習ログに
status列を追加したとき、既存ログにはstatusがない。既存ログすべてにlearnedを埋めるのがbackfillである。研修の小さなプロジェクトでは、backfillせず「読み取り時にlearned扱いにする」だけで足りる場合もある。 - つまずきやすい点:大量データへのbackfillは時間や負荷がかかるため、本番では実行タイミングや影響範囲に注意がいる。
- 関連語:nullable(第22章)、default(第22章)、migration(第22章)
- テキスト本文での登場箇所:第22章「既存データは、変更後も読めなければならない」「Migration Noteは、データ変更の説明である」
read-time fallback
- 読み:リードタイム フォールバック(read-time fallback/読み取り時補完)
- 一言で言うと:保存済みデータを書き換えず、読み取るときに足りない値を補って扱う方法。
- くわしく:新しいfieldを追加すると、既存データにはその値がない。read-time fallbackでは、DBに値を埋めるのではなく、読み取り処理や表示処理で「値がなければ
learnedとみなす」のように補完する。既存データを書き換えずに互換性を保ちやすいが、UI、API、テストで同じ補完ルールを使わないと解釈がずれる。 - 具体例:statusがない既存ログを、一覧表示と
learned絞り込みではlearnedとして扱う。 - つまずきやすい点:保存値は空のままなので、別の処理が補完を忘れると、画面とAPIで結果が違うことがある。
- 関連語:nullable(第22章)、default(第22章)、backfill(第22章)、互換性(第22章)
- テキスト本文での登場箇所:第22章「既存データは、変更後も読めなければならない」
nullable
- 読み:ナラブル/nullable(NULL可)
- 一言で言うと:その項目に値が入っていなくてもよい、という設定である。
- くわしく:DBの列などで、値が空(NULL)のまま保存できる状態をnullableという。逆に、必ず値が必要な状態は「必須(NOT NULL)」と呼ぶ。新しいfieldを追加するとき、既存データには値がないため、nullableにしておけば古いデータをそのまま保存し続けられる。ただし、値が空のままだと表示や絞り込みの扱いを別途決める必要がある。空のときどうするかを決めずに進むと、画面とAPIで解釈がずれる。
- 具体例:学習ログに
statusを追加するとき、列をnullableにすれば、既存ログはstatusが空のまま残せる。表示や絞り込みでは、空のものをlearnedとして扱うと決めておく。 - つまずきやすい点:nullableにしただけでは「空のとき何として扱うか」は決まらない。表示・絞り込みのルールを別に決める必要がある。
- 関連語:default(第22章)、backfill(第22章)、互換性(第22章)
- テキスト本文での登場箇所:第22章「既存データは、変更後も読めなければならない」
default
- 読み:デフォルト/default(既定値)
- 一言で言うと:値を指定しなかったときに自動で入る、あらかじめ決めた値である。
- くわしく:DBの列や設定では、入力がないときに使う初期値をdefaultとして決められる。defaultがあると、新しく作るデータが必ず何らかの値を持つので、空のままになるのを防げる。新しいfieldを足すときは、新規作成時のdefaultを決めておくと扱いがそろう。ただし、defaultは新しく作るデータに効くもので、すでに保存済みの古いデータには自動では入らない点に注意がいる。古いデータはbackfillや読み取り時の補完で別に扱う。
- 具体例:新しい学習ログを作るとき、
statusを指定しなければdraftをdefaultにする、と決められる。これで新規ログは必ずstatusを持つ。 - つまずきやすい点:defaultは新規データにだけ効き、既存データには適用されないことを忘れやすい。
- 関連語:nullable(第22章)、backfill(第22章)、migration(第22章)
- テキスト本文での登場箇所:第22章「既存データは、変更後も読めなければならない」「Migration Noteは、データ変更の説明である」
migration
- 読み:マイグレーション/migration(データ移行)
- 一言で言うと:データの形や内容を、新しいやり方に合わせて移し替えることである。
- くわしく:第10章ではDBの構造(スキーマ)を変えるmigrationを扱った。既存プロダクト改善では、構造の変更に加えて、すでに保存されている既存データをどう扱うかというデータ移行の観点が重要になる。古いデータが変更後も読めるか、新しいデータが正しい値を持つか、戻すときどのデータに影響するかを考える。これを整理した説明メモがmigration noteである。実装より先に、何を変え、既存データをどう扱い、どう確認し、どう戻すかを言葉にする。
- 具体例:学習ログに
statusを追加する改善では、列の追加(スキーマ変更)と、既存ログをlearned扱いにする(既存データの扱い)の両方を決める。これがstatus機能のmigrationである。 - つまずきやすい点:構造を変えることばかりに気を取られ、すでにある既存データの扱いを決め忘れると、古いデータが読めなくなる。
- 関連語:backfill(第22章)、default(第22章)、nullable(第22章)、マイグレーション(第10章)
- テキスト本文での登場箇所:第22章「Migration Noteは、データ変更の説明である」「既存データは、変更後も読めなければならない」
revert
- 読み:リバート/revert
- 一言で言うと:加えた変更を取り消して、前の状態に戻すことである。
- くわしく:revertは、入れた変更が問題を起こしたときに、それを打ち消して安全な状態に戻す操作である。gitでは
git revertで特定のコミットの変更を取り消せる。安全な変更とは、失敗しないことではなく、失敗に早く気づき、必要なら戻せることである。だからこそ、戻すときに何が起きるかを事前に考えておく。コードだけでなく、UI、保存処理、保存済みデータ、READMEの手順までまとめて戻せるかを確認する。 - 具体例:支援ステータス機能を戻す場合、status入力UI、絞り込みUI、保存処理、READMEの確認手順を合わせて戻す。
status列を追加していたなら、戻した後も既存ログが読めるかを確認する。 - つまずきやすい点:コードだけ戻して、DBに追加した列や保存済みデータの扱いを戻し忘れると、データとコードの食い違いが起きる。
- 関連語:互換性/後方互換性(第22章)、migration(第22章)、リファクタリング(第8章)
- テキスト本文での登場箇所:第22章「Safe Change Planは、小さく戻せる順序を作る」
互換性 / 後方互換性
- 読み:ごかんせい/こうほうごかんせい(compatibility/backward compatibility)
- 一言で言うと:これまでの使い方やデータが、変更後も困らずに使えることである。
- くわしく:互換性とは、既存の使い方、既存データ、既存API、既存手順が、変更後もそのまま通用することをいう。特に、古いものが新しいバージョンでもそのまま動くことを後方互換性という。既存プロダクト改善では、新しい機能を足すだけでなく、今まで動いていたものを壊さないことが重要になる。互換性リスクは、変更を禁止するために書くのではなく、壊す可能性があるときに移行方法、告知、戻し方を考えるために書く。前提を決めれば、実装もテストもREADMEもその前提でそろえられる。
- 具体例:学習ログに
statusを追加するとき、既存ログにはstatusがない。statusを必須にして既存ログを読めなくすると後方互換性が崩れる。そこで「既存ログはlearned扱いにする」と決め、古いログも一覧に表示され続けるようにする。 - つまずきやすい点:API responseにfieldを足すだけは安全に見えるが、呼び出し側が厳密な形を期待していると壊れることがある。
- 関連語:migration(第22章)、backfill(第22章)、nullable(第22章)、revert(第22章)
- テキスト本文での登場箇所:第22章「互換性は、既存の使い方を困らせないこと」
release note
- 読み:リリースノート/release note
- 一言で言うと:何が変わったかを、利用者や運用者に向けて短く伝える文書である。
- くわしく:release noteは、リリースで利用者に見える変化を伝えるための文書である。技術的な差分をすべて書く必要はなく、使う人に何が見えるかを優先する。ただし、互換性、データ移行、既知の問題は隠さずに書く。PR Summaryが主にレビュアーや開発の履歴向けなのに対し、release noteは利用者・運用者向けという違いがある。release noteを書くと、「実装した」ではなく「使う人に何が見えるか」という視点が明確になる。
- 具体例:支援ステータス機能のrelease noteには、「ログに
draft、learned、needs-helpのstatusを付けられます」「一覧でstatusを指定して絞り込めます」「既存ログはlearnedとして扱われます」など、利用者目線の変化を書く。 - つまずきやすい点:技術的な差分だけを並べてしまいがちだが、利用者に見える変化を中心に書く。
- 関連語:互換性/後方互換性(第22章)、migration(第22章)、テクニカルライティング(第20章)
- テキスト本文での登場箇所:第22章「Release Noteは、利用者に見える変化を書く」
回帰確認 / regression test
- 読み:かいきかくにん/リグレッション テスト(regression test)
- 一言で言うと:前からできていたことが、変更後も壊れていないかを確認することである(→第8章/第13章)。
- くわしく:詳しい定義は第8章・第13章を参照する。既存プロダクト改善の文脈では、新しい機能が動くかだけでなく、既存の振る舞いが壊れていないかを分けて確認する点が重要になる。status絞り込みが動くかに加えて、ログを作れるか、一覧に既存ログが出るか、README通りに起動できるか、不正なstatusを保存しないかも確認する。
- 関連語:characterization test(第22章)、テスト戦略(第13章)
- テキスト本文での登場箇所:第22章「回帰確認は、変えていないはずの価値を見る」
リファクタリング
- 読み:リファクタリング/refactoring
- 一言で言うと:利用者から見える振る舞いを変えずに、内部構造を整理することである(→第8章)。
- 関連語:characterization test(第22章)
- テキスト本文での登場箇所:第22章「仕様変更とリファクタリングを分ける」