牛乳を3つ買ってくるプログラマーはどうすれば牛乳と卵3つを買ってきてくれるのか

## はじめに
お久しぶりです、Nemesisです。
以前は[Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)の記事を書いていましたが、これがかなりの高評価を頂き、「新しいHello World」なんて言われながら、[タグ](https://qiita.com/tags/%e6%b9%af%e5%a9%86%e5%a9%86)に[動画](https://www.youtube.com/watch?v=pGJ8fK5sraQ)に[アドベントカレンダー](https://qiita.com/advent-calendar/2020/yubaba)となかなか楽しんでいただけたようで、ただの思いつきで書いたもんだからそこまで話題になるとは思わず、かなり嬉しかったです。

さて、今回の記事もまたネタなんですが、この記事を御覧の皆様には、以下のようなネタをご存じの方がおられるかと思います。

**「プログラマーに『牛乳を買ってきて。卵があったら、3つ買ってきて』と頼んだら、牛乳を3つ買ってきた」**

今回は、このプログラマーにしか伝わらないネタについての記事を書いていこうと思います。

#### 注意
* 本記事での使用言語はJavaです。
* 特に真面目な内容でもないので、技術の参考とかにはならないかも...

## ネタの解説
他人のネタをわざわざ解説するのはいささか無粋のような気もしますが、分からない人がいるとそもそもこの記事のネタが成り立たなくなるので、まずはこのネタのポイントを解説します。

**「プログラマーに『牛乳を買ってきて。卵があったら、3つ買ってきて』と頼んだら、牛乳を3つ買ってきた」**

普通の人であれば、上記の文章を見れば、注文されているのは**牛乳１つ、卵があったら卵を3つ**であることは理解できると思います。

しかし、プログラマーという種族の生物は文字を見たとおりにしか解釈しないため、**牛乳を1つ、卵がある場合は牛乳を3つ**という風に受け取ってしまい、結果として牛乳を3つ買ってきてしまう、というネタです。

## なぜそのようなことになるのか
結論から言うと、**そもそもの指示**に原因があります。
「牛乳を1つ買ってきて」「卵があったら、卵を3つ買ってきて」というそれぞれ独立した指示が件の文章に含まれているのですが、「**牛乳を買ってきて**」で牛乳を最低1つは買ってきてくれますが、**卵がある場合に、何を3つ買ってくるのか**が明言されていないため、卵の有無は単に条件として認識されてしまい、独立したタスクが同一のタスクとしてみなされ、牛乳を3つ買ってくるという望まない結果を招いてしまうのです。

```java
if(卵があるかどうかを調べる){
    //卵があった時
    for(int i = 0; i < 3; i++){
        牛乳を買う;
    }
}else{
    //卵がなかった時
    牛乳を買う
}
```
牛乳を3つも買ってきて、お酒のかわりに牛乳で飲み会でもするのでしょうか？普通に消費するのでは、飲みきる頃には消費期限を過ぎているでしょうし、巨大なケーキを作るにしても、牛乳3つ消費するレベルとなれば、尋常じゃない大きさになることが予想されます。いずれにしても正気の沙汰ではありません。

## どうすれば牛乳と卵3つを買ってきてくれるのか
まずは、何がほしいのかを具体的に示す必要があります。今回欲しい物は、以下の通りになると考えられます。

* 牛乳
* 卵

これで、「牛乳と卵が必要である」という意図が伝わり、種族プログラマーは牛乳を買うタスクと卵を買うタスクをそれぞれ認識します。
```java
//牛乳を買うタスク
private void BuyMilk(){
    牛乳を買う();
}

//卵を買うタスク
private void BuyEgg(){
    卵を買う();
}
```

そして、「牛乳は1つ」「卵は3つ」と、ほしい数も具体的に示す必要があります。これで、牛乳を3つ買うという気が狂ったような結果は回避することができます。

```java
private void BuyMilk(){
    牛乳を買う();
}

private void BuyEgg(){
    //ホントだったらこのような書き方をすべきではないのですが、
    //今回は必要なタスクごとでのメソッドの切り出し、ということでお目溢しを...
    for(int i = 0; i < 3; i++){
        卵を買う();
    }
} 
```

最後に、卵を買うタスクは「卵がある場合に」行うタスクなので、条件も指定します。

```java
private void BuyMilk(){
    牛乳を買う();
}

private void BuyEgg(){
    if(卵があるか調べる)
        for(int i = 0; i < 3; i++){
            卵を買う();
        }
    }
} 
```

これで、望んだ通りの結果になると思います。

## おまけ
件の指示には、「**卵はあるけれど、3つ未満しかない場合**」の状況は想定されていないように思います。

普通の人であれば、「ごめんなさい。卵はあったけど、これだけしか買えなかったよ」と、とりあえず卵を買ってくることができますが、最初に説明したとおり、イカれたプログラマーは文字を見たとおりにしか解釈しないので、3つ目の卵を買おうとした時点で**リストの外を参照してエラーを吐いてしまう**か、もしくは**異空間から存在しないはずの3つ目の卵を購入する**ため、その場でエラーを吐いて卵売り場の戸棚の前に立ち尽くしたまま置物と化す、もしくは軽率に卵売り場の空間を歪めて他の利用者を困らせるといったあまりにも迷惑すぎるモンスタープログラマーが爆誕してしまいます。普通に警察案件です。

この問題を回避しようと思うと、「3つ未満しかない場合はあるだけ買ってくる」のように指示するなど、条件周りの指示をもっと具体的に行わなければなりません。しかし、そこまで具体的に指示をしないとしてほしいことをしてくれなかったり、エラーを吐いて置物化したり軽率に空間を歪めるような奴に牛乳3つも買わせるお金と時間があるなら、自分で買いに行ったほうが、臨機応変に対応でき、望み通りの結果を得られると思います。

## 最後に
というわけで、以上が僕の3年ぶりぐらいのクソ記事になります。

「自分で買いに行ったほうが早い」とか言うよくわからない結論で終わらせるわけにはいかないので全体の総括を書きますが、僕がこの記事で伝えたいこととしては、「**仕様書・指示の類は具体的に**」「**何を求められているのかを考えて実装する**」です。

「仕様書・指示の類は具体的に」については、チーム開発などでは、実装する時に齟齬が生じないように、全員で同じ想定になるようにしなければならないので言うまでもありませんが、これは個人開発においても重要で、他人からのフィードバックを得るときに、自分がしたいことを理解して貰う必要がありますし、昨日の自分が書いた仕様書や、コードに書いたコメントアウトなどを次の日以降に見た時、その時の意図を忘れてしまって思い出せず、また考え直さなくてはならない、といったような状況は避ける必要があります。なので、**第三者が見てもなるべく同じ想定になるように書く**のがベストだと思います。

「何を求められているのかを考えて実装する」についても、今回の問題はそもそも「卵があったら3つ買ってきて」という文章を見て、「卵が3つほしいんだ」と理解できれば未然に防げる問題です。「指示が悪い」と思考放棄をするのではなく、**相手が求めるものはなにかを考えて指示を解釈する**必要があり、分からなければ質問をして後々齟齬が生じないようにできれば良いと思います。

これだったら自分でやったほうが早い、という風になってしまってはチーム開発の意味がなくなってしまうので、互いに相手のことを考えて動くことができれば、効率よく作業を進められると思います。

Ja婆婆を書いた当時から3年、インターンに行くようになって、他人と作業をする機会が増えたので、自分のための備忘録として今回の記事を書きました。
終始クソ記事でしたが、最後まで読んでくださって、ありがとうございました。