やることが多くて面倒なときは呼び出し元駆動開発を使え！

# 注意
結構テキトー書いてるので話半分でお願いします

# こんなときありますよね
- やるべきことはわかるし列挙もできるが、とにかく手を付けるのが億劫
- 作業量が多いので対応漏れが頻発する
- 作業中に自分なにやってたんだっけ？　となる

例えば、特定のインスタンスについて都度生成削除を繰り返していると重いのでこれをプールするように書き換えるとき。
さらに状況を絞って、音ゲーでノーツを大量に作るので、ノーツインスタンスを使いまわしたい場合を考えます。
(私の趣味でUnity+C#想定です)

```c#
// 元々の処理（プールを使わず都度生成のとき）
void Update()
{
    List<CreateInfo> requestList = GetCreateInfo();
    foreach(var request in requestList)
    {
        var createdObj = Instantiate(request.prefab); // ここでインスタンス化している
        var createdNote = createdObj.GetComponent<Note>();
        createdNote.transform.position = request.initPos;
        createdNote.status = request.status;
        // このあともいろいろな初期化が続く...
        TimingWatcher.Regist(createdNote);
    }
}
```
まずはInstantiateを置き換えて、プールから……
じゃあプール用のクラスも作らないといけないな……
あれ？　プール用のクラスって内部はQueueでいいかな？
ノーツの仕様ってどうだっけ……
あっ！　これプールに戻す条件も考えなきゃじゃん！
めんどくさ……
………………
…………
……
Twitterを見てたらふつうに一日終わってたりします。

- やるべきことはわかるし列挙もできるが、とにかく手を付けるのが億劫
- 作業量が多いので対応漏れが頻発する
- 作業中に自分なにやってたんだっけ？　となる

そんなあなたに呼び出し元駆動開発！

# 呼び出し元駆動開発とは？
呼び出し元のほうから存在しないシンボルを使って書く、型を書き換える、などして意図的に発生させたエラーを解消するようにコーディングしていく手法のことをこう呼んでいます。つまり私の造語です。残念だったな！

先程の例を使いましょう。
まずプールにしたい！　という目的があるわけなので、このように書き換えます。
```diff_c_sharp
// foreach内
- var createdObj = Instantiate(request.prefab);
- var createdNote = createdObj.GetComponent<Note>();
+ var createdNote = NotesPool.GetInstance(request.prefabNameEnum);
createdNote.transform.position = request.initPos;
createdNote.status = request.status;
// このあともいろいろな初期化が続く...
TimingWatcher.Regist(createdNote);
```
いいですか？
まだNotesPoolというクラスは作っていないですし、request(CreateInfo型)にもprefabNameEnumなんていうメンバはいません。なので、順次そういうシンボルをつくっていきます。

```diff_c_sharp
class CreateInfo
{
    // いろいろなメンバ略
+   PrefabNameEnum prefabNameEnum;
}
```
さて、これで問題が一つ解消しましたね！
それはそれとしてPrefabNameEnumがないと言われました！
じゃあこれを解消……おっと、そういえばプールには戻す作業も必要でした！
こんな末端のCreateInfoよりも呼び出し元に近いので、プールに戻す作業を先に書きましょう！
```diff_c_sharp
// 元々の処理（プールを使わず都度生成のとき）
void Update()
{
    List<CreateInfo> requestList = GetCreateInfo();
    foreach(var request in requestList)
    {
        // ...
+       _createdNotes.Add(createdNote);
    }
+   foreach(var note in _createdNotes)
+   {
+       if(note.IsResetable())
+       {
+           NotesPool.Return(note);
+           // foreach内で要素変更しちゃだめなので……
+           _deleteReserveNotes = note;
+       }
+   }
}
```
ここでまだ宣言していない変数を大量に書きました。ついでにNotesPoolも存在しませんがReturnという関数を勝手に考えて使うことにしました。さらにnoteのIsResetableとかいう関数を仮定しています。そんな都合の良い関数があるんでしょうか？　でもこんな感じで使いたいのでとにかく書いておきましょう。
さっき中断したなんたらEunmを宣言してもいいですが、呼び出し元に近いので今書いた変数たちを宣言するところから始めていきましょう。
（以降、同じ要領で続けていく）

もし、呼び出し先の記述で呼び出し元を書き換えないといけない場合、印だけつけて呼び出し元に戻ってきます。
NoteクラスのIsResetableは画面サイズを用いないと画面外に出たかどうか判定できない……としましょう。
シングルトンを利用してデータを拾ってきてもいいですが関数の引数に画面サイズを渡してほしいと思ったので関数の宣言に変数を書き加えます。そして呼び出し元に戻ります。呼び出し元を解消してやれば引数の不一致は解消されるはずです。

# こういうときどうする？
リファクタリングとしてメンバ変数の型を変えたいときは、そのまま型を変えます。
エラーが出たところを呼び出し元から直していきます。
命名は呼び出し先クラスの様子をみてから決めたいときは、いかにもテキトーな名前にします。
Reset_AtodeMeimeiKakunin();
とかどうでしょうか？
作業を中断したいときは無効なシンボルを残しておきましょう。
コメントなしでKokokaraSaikaiとか書いておけばいいです。
呼び出し元、の意味がゆらぎそうな場合は実現したい機能の実現に近いところからと位置づけましょう。
呼出履歴の順序を参考にしてもよいです。
（これでいくと変数の宣言なんて呼出履歴に出ないので優先度がかなり低いことがわかると思います）
コンパイルエラーが出ないような実装漏れは利用されていない変数などから検知します。なのでコンパイルエラーのほか警告も見てください。
呼び出し元にいちいち戻るのが面倒だったらそのまま作業を続けても大丈夫です。あくまでこれは作業をスムーズに進めるための手法で、遵守しないことで不整合が起きるわけではないです。

# 利点の紹介
### ・作業の進め方が決まっている
何から始めるかという計画が決まっていない限りどこから始めるかという選択肢がたくさんあり、そして人は多すぎる選択肢から選びづらいです。（決定回避の法則とか呼ばれるやつです、しらんけど）
どんな作業でも"呼び出し元から書いていく"という規則があればとりあえず作業が始められます。
作業を進めるのに一番いいのは作業を始めてしまうことです。

### ・作業の再開継続がしやすい
タスクの残りがコンパイルエラーという形で表示されているのでこれに手をつけていくだけです。
再開しても上記の通り順番が決まっているのでどこから再開すればいいか自明です。

### ・本質を見失いにくい
プログラミングの事情でさせられる変数宣言、クラス設計は必要なものの問題解決に対しては本質的でありません。どういったメンバが、どういった型かというのを考えるのは、どういった挙動をするのかわかっていないと難しい、のにそれを先にすると望ましい挙動を歪めることがあります。
どう使うかを先に書き始めたほうが要件がコードという形で具体的に決まっていき、それをもとに書いていったほうがよいでしょう。

### ・メモを手動でとらなくてよい
TODOアノテーションは比較的長期的なメモを残すのによいですが、一日程度で完結するような作業でいちいちメモを取るのは面倒です。（本当はあったほうがいいですが……）
作業を進めているだけでIDEが勝手にここがおかしい、作業をしないといけないというマーカをつけていくのは素晴らしいことです。それを解消していくだけでいいのですから。

# こんな人には向いてない
- 仕様を実現する際のアルゴリズムがそもそも思い浮かんでない人（初心者や、手探り期にいるひと）
大量に書いて一発で通そうとする手法なので、ある程度の経験がないと大事故になります。
- バージョン管理ツールを使っていない人
もともとの処理を破壊することもあるので、バックアップもないとこわい。
- タスクの切り分けができない人
さらにこの編集は大量にかくといってもある程度定期的に挙動確認はしたいので、それなりの粒度でタスクが切り分けられているべきです。
- いろんな事情で優れたIDEが使えない
そもそもですがコンパイルエラーとか警告がリアルタイムで検知できないとこの手法は使いづらいです。
警告が握りつぶされてるとか出すぎている場合も使いづらいですね。

# いかがでしたか？