「わからない」を「わかる」にする方法の話

エンジニアになる時、参考書などで勉強した後でいざ実践しようとしたら、あまりにもわからないことだらけで途方に暮れたことはないでしょうか？
または、新しいプロジェクトに参画してコードを読んだ時に、前任者のコードがわからなすぎて逃げ出したくなったことはないでしょうか？
バグがなぜ起きているかわからずに数日費やしたことは？ 

エンジニアリングでは、どうも勉強だけで得られる理想と現実に大きなギャップがあるようです。
そこら辺を解決するための泥臭い話をします。

## 何の話をするか

非常にざっくり言えばここらへんの話をします。

- わからないを解決する方法
- デバッグ方法（コードのわからないを解決する方法）
- 科学的手法（デバッグ方法の一種）

参考　[Wikipedia「デバッグ」](https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%90%E3%83%83%E3%82%B0)
参考　[O'Reilly『デバッグの理論と実践』](https://www.oreilly.co.jp/books/9784873115931/)
参考　[Wikipedia「科学的方法」](https://ja.wikipedia.org/wiki/%E7%A7%91%E5%AD%A6%E7%9A%84%E6%96%B9%E6%B3%95)

これらの話は大抵「誰も教えてくれないのに、無いと詰む」というタイプの知識であり、エンジニア挫折原因の一つだと思います。
オライリーの本にも「あまり本が出てない」と書いていました。

## 注意事項

この話は非常に重要なのに、あまりにも語られません。
わかった風に書きますが、私もこれについては何となくやってるので自信がありません。

また、これらの手法を使えないシーンというのも数多く存在します。
最も使えるシーンは皆がよく知るサービス系のシステムを開発するシーンです。

# 先に結論！！

知的活動というのは非常に複雑です。
俯瞰しやすくするため先に結論を書きます。目次みたいなものです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/df346d63-d333-73a0-4e9f-6b2e20a79792.png" width=70%>

# 「わかる」をわかる

たぶんこの章が一番難しいです。
「わかる」の構造がわかるとだいぶ楽になりますが、読み飛ばしても構いません。

## 「わかる」をClassで考える

「◯◯についてわかる」という状態を理解するのも説明するのもとても難しいのですが、これは**Classで考えると分かりやすい**です。

あるClassについて**わかる**、というのは

- Classのメンバーについてわかる
- Classのメンバー内の他のClassについてわかる
- Classの外からみた位置づけについてわかる

これらが全てわかるという状態が近いでしょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/bdfd4a34-286d-91fd-8723-094e7439b209.png" width=70%>

もっと単純化すると、対象の**外と内**に分けられます。
[内包と外延](https://ja.wikipedia.org/wiki/%E5%86%85%E5%8C%85%E3%81%A8%E5%A4%96%E5%BB%B6)なんて言ったりします。

「HogeClassがわかる」がそれに関連した**いくつかのサブ要素のわかるによって成り立っている**というのが重要です。
入れ子になっています。

## 「わからない」をClassで考える

「HogeClassがわからない」というのは、いくつかのサブ要素の中の1つ以上がわからないという状態です。
例えば「HogeClassのメンバー変数の◯◯がわからない」でもよいです。
こう考えると、「HogeClassがわからない」は**より具体的にいくつかのサブ要素がわからない**と言い換えられます。
これは非常に重要で、そのいくつかのサブ要素がわかれば、HogeClassがわかるということにもなります。

## 「何がわからないか、わかる」「何がわからないか、わからない」はどういう状態か？

例えば、算数の教科書があったとします。教科書は10章で構成されています。
これら10章についてわかったなら、その教科書についてわかったと言えるでしょう。
例えば5章だけわからないなら、「5章だけわからないとわかる」です。
なら、その教科書を読んでいなく、10章で構成されることすら知らなければ、「何がわからないかわからない」となるでしょう。

つまり、「何がわからないかわる」「何がわからないかわからない」は構成要素そのものを話題にしています。

## 「わからない」は2種類ある

- ◯◯がわからない
- 何がわからないかがわからない（◯◯自体がわからない）

この2つのどちらかによって、対策は変わってきます。
前者なら、上で書いたようにサブ要素に分解して、より具体的なわからないことを導きます。**わからないことの具体化**とでも呼んでおきます（上に挙げたオライリーの本では別の呼び方してたと思います）
後者なら、◯◯自体を知らなければ話が始まりません。
これは知識に依るところが大きいです。

## 目的が生じると「わからない」が増える

目的達成のための流れというのは以下のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/660a4fa6-d0b3-c52f-c9a3-d36abb74bbe8.png" width=70%>

これはデバッグ作業が分かりやすいです。

目的：バグを修正する
理想状態：正常動作
現在の状態：再現した動作

この1個1個の構成要素について「わからない」は発生します。

- 目的がわからない（どうすればいいのかわからない）
- 理想状態がわからない（どうなればいいのかわからない）
- 現在の状態がわからない（今どうなのかわからない）
- 差分がわからない（求められない）
- 差を埋める行動がわからない（対策がわからない）

「あーこのタスクわからない！」となったときに、まず上の構成要素を見れば**「何がわからないのかはわかる」**とおもいます。
上で説明したとおり、わからないの対策は2パターンです。具体化か、知識を得るか。

## 補足：「わかるのサブ要素」が複雑なものと、シンプルにできるものがある

例えば「Web開発についてわかるようになりたい」と言ったときに、サブ要素がなにか＝どこからどこまでわかればOKなのかは非常に難しいです。
**サブ要素を見つけるのがまず大変、体系立てるのも非常に大変**というジャンルは星の数ほどあります。
参考書が存在していても、大体それは網羅されていないことが多いです。よくわかってないけど必要なこと・経験則・統計的に決まるものなどは言語化しづらいのです（この記事のように）

対して、上の「目的を達成するためのサブ要素」のようなシンプルな形にできるものも少ないですが存在します。
そういったミニマムな行動ルールを一つずつ身に着けていくことは、他の未知のものをわかるようにするために有効に働きます。
仕事界隈全体において、これらを発見しモノにするのが一つの目的になっていると思います（対象的に、体系付けられないのを経験則で解決するアプローチもあります、これらは現在のAIに近いですね）

## 「わからない」を「わかる」ようにするのは目的となる

例えば、「Viewの色が違う」というチケットが振られたとします。
困りました、色の理想状態が書いていません。
これは「理想状態がわからない」です。
なら、「理想状態をわかるようにする」は目的にできます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/15378f63-8459-5004-ffe9-db86307c6029.png" width=70%>

仕様を訊く、なんていう単純な行動でもこのように型にはめられます。

## 目的が生じる→わからないが生まれる→小目的になる

目的はわからないことを通じて小目的に分解されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/fb56fa3b-3176-748b-bae8-725d1632eae0.png" width=70%>

実際のデバッグ作業などでは、これが何段にも分解されていくはずです。
もちろん小さいタスクなら脳内でどうにかなりますが、ある一定ラインからこういうのを意識しないとわけがわからなくなります。
日常茶飯事です、あれをするために、これをするために、あれをするために、これをするために、それをする。みたいな。

## わかるを分解したときのサブ要素でよくあるもの

「◯◯がわかる」を分解しようとすると

- 外から見た◯◯がわかる（外）
- メンバー（変数や機能）がわかる（内）
- メンバーの型がわかる（内）

となるとClassの例で書きましたが、これをより詳細に書けばいくらでもでてきます。

- 分類がわかる（外）
- 他人からの認識がわかる（外）
- 使い方がわかる（外、内）
- 関係や位置づけがわかる（外）
- 内部の仕組みがわかる（内）
- 変更した際の挙動がわかる（内・外）

これらをまとめるのに非常に苦心したのですが、どうやら該当する問題で絞ったほうが分かりやすいようなので、ソースコードだけに絞りましょう。

そしたらだいたいこのくらいわかればまずはいいですよね。

- それが言語の何なのかわかる（外）
- 何をするものなのかがわかる（外）
- それの型がわかる（外）
- 何のデータの流れがわかる（内？）
- どういう意図で使われてるかがわかる（外）
- 依存関係がわかる（外・内）
- 依存する物が何であるかわかる（外・内）
- 機能がわかる（外・内）
- 変更した際の挙動がわかる（外・内）

こういうのは環境差があります。
目的を満たすためにどのような要素があるかは、調べたり発見する必要があります。

## 目的を満たすためには、全部わかる必要はない

きちんと抽象化された構造内においては、目的達成のために全部がわかる必要はありません。
というか全部わかろうとすると時間がいくらあっても足りません。

例えば、家電を使用するのに内部の機構を意識する必要はないはずです。
ただ必要なのは、目的を達成するために「わからなくて良い」ということがわかる必要があります。「内」についてわからなくても良いためには、ブラックボックステストをすればいいです。

# 休憩

疲れました。
疲れますよね。
こういうメタの話は頭が疲れます。

ところでこれを書いていて気づいたんですが、「完全に理解した」状態っていうのが説明できるようになったと思います。
[エンジニアの言う「完全に理解した」「なにもわからない」「チョットデキル」って本当はこういう意味？「わかる」の声多数](https://togetter.com/li/1268851)

例えば「Linux完全に理解した」というのは、自分が認識しているLinuxのサブ要素について全て理解したという意味で、「なにもわからない」は、サブ要素を新たに大量に発見した状態、「チョットデキル」はおそらくサブ要素を大体発見し尽くした状態なのではないかと思います。
参考書などで勉強すると、参考書に出てくることを全て理解するのは無理ではないんですが、参考書に書いていないことを発見するのが大変なんですよね。
わかりますか？

そういえば、「わかった？」って酷い言葉ですよね。サブ要素のどれのことを指してるのかさっぱりわかりません。「わかった？」って、「『わかった？』がわからないよ」ですよね。
わかった？

# エンジニアリングに必要な「わかる」ための行動

プログラミング初心者が参考書を何度か読んで、ついでに基本情報処理技術者くらい取って、さて実務やるぞとなってからあまりにもわからないことだらけで詰むというのはよくある話だと思います。
私ももうプログラマーやめようと絶望した時期がありました。

原因はいくつかあります。

- 参考書に書いていないことが多すぎる（知識不足）
- 一般知識でどうにもならないことがあることを受け入れられない（アプローチが学校と違う）

## 一般知識でどうにかなることと、ならないことがある

エンジニアリングである小さなタスクを実行しようとした時、おそらくソレは「知ってること」「一般知識でどうにかなること」「一般知識でどうにもならないこと」のどれかです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/9222b038-84e8-1332-70f4-a9fe8146ae10.png" width=70%>

このタスクは目的と捉えても大丈夫です。
もう一度貼ります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/660a4fa6-d0b3-c52f-c9a3-d36abb74bbe8.png" width=70%>

つまり「わからないこと」の中で一般知識でどうにもならないことがたくさんあって早々に詰むんですが、「勉強」が基本の学校教育に慣れすぎた私達はそのことを受け入れられなくて「もっと勉強しなきゃ」となってその量に押しつぶされるんですね。
でもじゃあ「一般知識でどうにもならないものはどうすればいいの？」というのは誰も押してくれないのでそこからサバイバルゲームが始まるわけです。

## 一般知識でどうにもならないもの

そこら中にありますが、わかりやすいもの

- 前任者が書いたソースコード
- 今取り組んでいるシステムの仕様
- 誰もソレについてまとめていない事柄

これらはググっても出てこない情報です。
勉強しても覚えてなくて当たり前です。

## 業務では何故か「勉強してもわからないこと」が沢山出てくる

これは単純に**わからないことの方が多くの時間がかかるから**です。

たとえ話ですが、部屋の片付けをイメージしてください。
どこにしまえば良いかわかるものはすぐ片付けられてしまいます。
最後に残るのは「よくわからないもの」です。

実際に業務のタスクを個数で数えてみたら、多分「既に知ってるもの」「知識があればわかるもの」の方が多いはずです。でも「わからないもの」に時間がかかるため、いっつもわからないものと戦ってる気がしてきます。
**そして「わからないもの」を「わかるようにする」ができないと、業務ができず辛くなってしまいます。**

## 「一般知識でどうにもならないもの」に対するアプローチをする前に

このエントリーの主題はこれなんですが、もちろん先に「一般知識でどうにかなるもの」でアプローチすべきです。
上で書いたように、わからないことをわかるようにするには非常に時間と手間と汗と涙が必要になります。
**本に書いてれば最良ですし、ググって解決できるならそれが良いです。**

## わかってることを増やす方法

わからないものと戦うのは高コスト、だからわかってることを増やすのは非常に大事です。
なので、参考書を読んだ後に何をすべきかについても触れたいと思います。

まずは「何がわからないかがわからない」状態からの脱却です。
言い換えれば**「あと残り何を勉強すれば開発がスムーズになるのか」**という、サブ要素を集めます。
iOSなら、Swiftを覚えただけでは開発業務は難しいです。iOSについて深く知らなきゃいけないし、Xcode、git、cocoapods、Carthage、人気のLibrary、ターミナルやツールやMac、基礎的な情報工学、他DBとか通信とか諸々をある程度覚えておくのと覚えないのとでは大きな差が出ます。
もちろん一気に勉強しろと言われると死んでしまいます。「あと残り何を勉強すれば開発がスムーズになるのか」を覚えて、「何がわからないかわかっている」状態になるのが先決です。安心もできます。

ただこれがどこにも書いてないから困ったもので、実際の開発業務から学ばなきゃいけないかもしれません。頑張って情報収集すればある程度は集まるかもしれませんが。精度が悪いとあれもこれもと許容量を超えるかもしれません。
（よく人気の記事で「新卒が読んでおきたい本」みたいに大量の本が挙げられますが、あれが精度悪かった場合です。頭がすごく良いとそれでも乗り越えられるのですが、私みたいな凡人は普通に詰みます）

上記のような必要なサブ要素を全部「わかった」にしても、実務にはまだ不足感が出ます。
そのほとんどは**質の良い完成形**を見ることで解決できると思います。丁度いいお手本があるかどうかでかなり差があります。ただこれは運要素が強いのが困ったところです。
ネット上で素晴らしいコードは発見できるのですが、そういうのは大体熟練者が書いていて初学者には読みづらいです。
とりあえず、もし他人のコードを見る機会があればよく観察してみることをおすすめします。


# 「一般知識でどうにもならないもの」に対するアプローチ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/660a4fa6-d0b3-c52f-c9a3-d36abb74bbe8.png" width=70%>

これは図の差を埋める行動にあたってきます。
目的や理想状態、現在の状態を調べるのにこの方法は使わないです（あくまでエンジニアリングではです。もっと広く考えると市場調査など色々あります。）

本当は科学的手法！と書きたかったのですが、まるで自信がないです。
[オライリーの本](https://www.oreilly.co.jp/books/9784873115931/)の方で結構ちゃんと書いていたので読んでみてください。

あと方法論についてカテゴライズが上手くできていないのですいませんが思いつきベースで書きます。話が行ったり来たりになります。

## 基本の考え方

わかるようにしたい対象だけが観察できるように色々するのが基本的な考え方です。
対象だけが存在してれば分かりやすいですが、対象というのは大抵の場合色んな相互関係の中で存在しているので、観察が難しいのです。

また、上で話したようにわからないことはサブのわからないことに分解できます。
なのでメインのわからないことを解決するために、サブのわからないことを解いて品をと集めていくイメージに近いです。推理ゲームとかクロスワードにも似ているかもしれませんね。

## 何が知りたいかによって対応方法が変わる

わからないにも色々要素があったと書きましたが、それによって対応方法が変わってきます。
（どれがどれに対応するかはちょっと手間なので今は書きません）

## 実践１．比較する

比較は非常に有効な方法です。

### 比較するためには、知りたいモノ以外の条件を揃える必要がある

これは絶対おさえて置かなければならないことで、わからないものをわかるようにする（＝検査）対象は１つとか、狭くしておいて、その他の条件をきちんと合わせておかなければなりません。
ちなみにこれは現実空間だと結構しんどいことです。薬の試験とか大変そう。

参考　[対照実験](https://ja.wikipedia.org/wiki/%E5%AF%BE%E7%85%A7%E5%AE%9F%E9%A8%93)

### 比較の実践１−１．破壊する

例えばあるコード１行がわからない時、簡単なのは**その１行をコメントアウト**することです。
もしそれでプログラムが動いてくれたらラッキーです。
破壊（コメントアウト）前の挙動と、破壊後の挙動を見比べて、変化があればその１行をコメントアウトしたからかもしれません（もちろん、たまたまそうなっただけかもしれません！）

この１つを破壊するというのは非常に強力です。
世の中には「非破壊検査」という考えがあるくらいに、モノを壊さずに調べなければならない状況が多々存在します。例えば人体や橋なんかもそうです。
これは破壊すると不都合が生じるとか、破壊すると性質が変わってしまうものに使います。

それに比べてプログラムは簡単に破壊できます（というかそう作られている）し、運が良ければ性質も変わりません。
もちろん**性質が変わるモノには使えないので、全ての状況で破壊検査が使えるわけでは有りません。**
どういう場合に破壊検査できて、どういう場合にできないかを考えておく必要があります（私は何も考えずに一回ぶっ壊しますが）

### 比較の実践１−２．一部を変えてみる

これは分かりやすいです。
わからない１つの要素を別のものに変更してみましょう。

あるViewのパーツがどこにあたるかを調べるために背景を赤にするなどは頻繁にやります。

### 比較の実践１−３．差分を戻してみる

わからない対象がコードではなくコミット単位であれば、もちろんそれを戻して動かしてみたり、変更差分を見てみることというのは当然できますよね。
そのためにも、プログラムの変更履歴管理ツール（gitとか）は重要になります。

### 比較の実践１−４．他の類似コードと比較する

あるクラスがきちんと動いているけど、同じ使い方をしているはずの別のクラスは動いていない。
となれば、もちろんその二つを比較できますよね。
ここでも**とにかく条件を揃えること**が大事です。適当にやるとなにも得られません。

### 比較の実践１−５．条件や環境を比較する（条件の切り分け）

ある条件・環境ではこう動いてるのに、別の条件・環境では別の動きをしている。
その時に、少しずつ条件を変えていって、どこを変更すればどう動作が変更するかを調べていけばヒントが得られます。
これは二つの対象を比較しているようでいて、実際に比較しているのは条件の方です。
同じソースコードでも、条件や環境で別の動きをするというのがポイントです。

例
アプリバージョン1.1　iPhoneX　iOS12.3　ステージング環境で正常動作
アプリバージョン1.2　iPhone8　iOS11.0　本番環境で異常動作

この場合、まずは「アプリバージョン1.2、iPhoneX、iOS12.3、ステージング環境」で正常動作するかを確認して、その後に条件を一つずつ変えていきます。

### 比較の実践１−６．破壊した上で１個ずつ戻していく

１個だけ破壊する方法は「完全なもの」と「完全なものから検査対象を除いたもの」の比較によって「検査対象」を検査しました。

これを「完全なものから10個要素を取り除いたもの」と「完全なものから10個要素を取り除いて、**1個だけ元に戻したもの**」を比較すれば、その差分の1個について検査ができます。

これはまず「10個の要素を取り除く」のが大変なので積極的にはやりませんが、例えば検査対象が多すぎて困る時は有効です。

### 比較の実践１−７．最小構成まで壊し切る

例えばあまりにもバグが多いとか、どこが問題なのかわからない時、一旦サンプルコードレベルに機能を削る方法があります。
その最小構成まで落としたコードで問題が生じるかどうかで、「最小構成の方に問題がある」か「削った部分に問題があるか」の**問題の切り分け**ができます。

これまでは１個ずつ要素を見ていく方法ばかりでしたが、このようにアグレッシブに破壊して問題の箇所の切り分けをする方法もあります。

### 比較の実践１−８．対象要素以外全部壊す

１個だけ削る、１個だけ増やす、最小構成にする、ときて、今度は知りたい１個以外全部削る方法です。
例えばあるクラスにオプションが20個設定されていて、そのうちの1個について知りたいのであれば、その1個を削るか、もしくはその1個以外全部削るかのどっちかですよね。

ちなみにこれは「全要素削除した状態」と「検査対象1個だけ戻した状態」の比較なので実は「比較の実践６．破壊した上で１個ずつ戻していく」と同じです。

### 比較の実践１−９．同じものを一から作ってみる

割と最終手段というくらいに手間がかかりますが、コードの切り分けができないときはよくやる方法です。
ある機能や、あるパーツの挙動などについて確認したい時はサンプルコードを作って上手く動くか見たほうが早いときがあります。

または、１個ずつコードを移植していってどこで何が起きるか見ていく方法もあります。
ほんと最終手段ですね。

### 実践２．観察する

単に破壊したり比較したりだけでは意味がありません。
**何が変わったか**をきちんと把握しなければなりません。
観察する方法は色々あります。
最も有名なのはprintデバッグです。もっとかっこよくデバッガーツール郡でもよいです。
フロント寄りでないコードやモジュールであればテストコードがそれに当たるでしょう。

その環境や状況に即したありとあらゆる手段を用いて正しく観察します。
（ちなみに私は初心者の頃に「printデバッグって初心者がやるものでしょ」とか思ってましたが未だにprintデバッグを一番使っています。結局一番信頼できるんですよね）

ですが上手く観察できないとか、何を観察すれば良いのかわからないとか、観察結果が何か怪しいとか、いろんな不都合は生じます。
基本ではありますが、これで全ては解決しません。

### 実践２−１．わからないコードの前後で同じように観察する

>print()
>わからないコード
>print()

のようにわからないコードをサンドイッチすることで、何に変化が及んだのかを調べる方法です。
デバッガでも問題有りません。どの場所で情報を観察するかはよくよく考えてください。処理の流れをちゃんと把握できていないと間違ったタイミングで観察してしまいます。

ちなみにこれは、「検査対象のコードを実行する前」と「検査対象のコードを実行した後」の比較でもあります。

### 実践３．分類から調べる

それが何か、カテゴリと属性からわかろうとする試みです。
お手軽なので、順番的には比較や破壊の前に来ます。

具体的に言えば、その変数が何の型だとか、そのクラスが何のサブクラスかをまず調べます。おそらくこれについては多くの人ができていると思います。

### 実践４．分解する

これは比較の前段階にあたるものです。
比較や破壊をするときには、できるだけ疎結合なモノを作ってやらなきゃなりません。
実験空間を作るのです。
外部からコントロールできない影響が及ぼされると、その検査対象を増やしたり減らしたりしたおかげで変化が生じたのか、それとも外部要因で変化が生じたのかが判別つかなくなるのです。

しか実験空間を用意できないコードというのは大量にあります。密結合すぎて分解できないコードです。

### 実践５．関連を見つける

例えば分解できないとか、変更できない検査対象があったとします。
そのままではどうしようもないですが、その検査対象が依存している何かを見つければ、その何かが代替検査対象にすることができます。

### 実践５−１．わかるの連鎖を見つける

AがわかればBがわかる、BがわかればCがわかる
といった関連を見つけます。
AとBがわかればCがわかる、といった構造や
AがわかればBとCがわかる、といった構造もあります。

これらはきちんと論理構造にするために結構頭を使うので慎重に行ってください。
しかしこの発想は必ず必要になってきます。
実際に動いているシステムを触れないとか、仕組み上内部がいじれないようになっているというのはよくあります。

### 実践6.期待動作と実際の動作の差分を見つける

わからない対象が処理の流れである話。
コードリーディングから「ここでこうなる」が想像できるかもしれません。
しかし実際の動作がそうなっていない場合は、**処理を一個ずつ遡る**ことでどこで予想と違う結果が得られたかの場所を特定できます。

### 実践7.モジュール化、Unitテスト

特にモジュールに対する調査なら、テストコードは非常に手っ取り早いです。
または、モジュール化することで、わかるの構造が変化しよりわかりやすくなるということもあります。
リファクタリングにより理解が進むようなイメージです。

### 実践8.範囲以外をコントロール下に置く

対象と他の結合度が高くて、しかも深いところにある場合など、モジュール化が厳しい場合などは、例えばそれに接続されているものをダミーにしてしまうという方法があります。


### 実践9.データを追う

わからない対象がデータである時。
breakポイントを貼れるのであれば、逐一処理を止めてデータを確認していきます。
breakポイントが使えない場合は、printデバッグがlogデバッグになるでしょう。
正しくわかるためには、複数の網羅された条件で、観察しなければなりません。

### 実践10.わからないことを一般化してググる

特にバグ対応のとき。
実際のところ、**似たデバッグはネット上の誰かがしている可能性が高い**です。
わからないこと、バグ、悩みが一般化できるのであれば積極的にググりましょう。
先人達が既に検証済みなら自分がするメリットはかなり少なくなります。
（実際そのためにネットに情報が集まっていると思います。皆こういう検証作業は大変なのです）

どのようにすれば一般化できるかという話はちょっと難しいのですが、エラーメッセージは非常にお手軽です。同じエラーメッセージに遭遇した人がたくさん見つかるはずです。

### 実践11．質問する

もちろん質問も一つの適切な手段です。
ただこの業界、案外質問数が少ないのは、上記のような色んな調査を口頭で伝えるのが大変だからだと思います。

これまでの流れから、正しく質問するのは非常に難しいように感じるかもしれません。
実際自分の現状の理解を正しく質問して期待の回答を得るのは中々訓練が必要な気がします。
一旦、メイン目標とサブ目標、理想状態と現在の状態があれば十分だと思います。

例：このバグチケットについて、理想はこうだけど現状はこうで、こうすると直ると思ったが、その方法がわからない

でもこれは相手によるかもしれません。
どこまで上流の目的までトレースするかは個人差がありますね。

### 実践12．仮説を立てて、調査して、推理する

さあヒントは集まりました。答えは出そうでしょうか。

実際これらは壮大な推理ゲームじみています。
私達は仕事の大半を推理ゲームしています。
上で書いた様々な実践は、直接的な答えをくれず、ヒントしかくれません。だから推理の繰り返しになります。

推理するにしても、当てずっぽうで上に書いたようなことをしまくるとおそらく１ヶ月が終わってしまいますから、「何となくここが怪しい」という検査範囲を絞り込んで、仮説を立てて検査しなければなりません。この「何となく」は残念ながら経験量が必要です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/64be0757-9b86-2aff-1e44-9f0891f451bd.png" width=70%>

## 追加テクニック

- 完全にわかるクリーン空間を作る
- わかんないものを全部消し去っていちから作り直す
- コメントを書く
- 論理的に考える（静的解析）

# その他留意することなど

## 詰み

実は結構詰みます。

- 観察できない
- 実験できない
- 時間が足りない
- 毎回別の観測結果が出る（再現性がない）
- わからないことが多すぎる（全部わからない）
- 知識を得られない（例：ググれない）
- 「わからない」を「わかる」にする方法を知らない
- 「そんなの気付けるわけ無いだろ！」みたいな超高難度の問題
- 知識が必要なのに記録がない（例：仕様書がない）
- 設計関係
- 密結合・ジェンガコード
- 複数のわからないことが複雑に絡んでいる

## 設計の引き継ぎ、仕様の引き継ぎは詰みます

例えば「あるクラスの１メンバー変数がわからない」とかならどうとでも調査できますが、「クラスをどのように配置させて関連させるか」のような思想はコードから読み取るのが難しいのでわかりようがありません。
（喩えるなら、連立方程式で変数に対して式が足りずに「それじゃ答えでないよー」という状態です）

また、仕様も「現状そうなってる」以上のことがわかりません。「現状そうなってるけど正しいのかわからない」になります。
注意しましょう。

## わからないことが多いほど詰みます

理想を言えば、ほとんどわかっていて一部がわかっていない状態です。
わからないものが増えるほどに、とんでもなく時間が増えていきます。
わからないモノ同士が依存していたらなおさらです。

そのベースアップをするためには勉強や経験が必要ですが、勉強したところで他人のコードや設計が理解できることはないので、特にプロジェクト引き継ぎ直後の詰み率が高いですね。

## 調査結果というのは貴重です

同じ調査をすると何時間も削れてしまいます。
わかったことは記録を残して共有しましょう。

## 保守性・可用性が高く、持続開発可能なコードはどういうコードか

**「わかりにくくないコード」**です。
あるいはわかろうとした時にすぐわかるコードです。

この話は別途まとめたいです。

# おわりに

この話、言語化しようとすると吐くほど難しいですね。圧倒的に地頭の限界を感じます。
もっといい方法があるなら知りたいです。別解があればぜひ教えて下さい。

おそらく疫学とか薬学、実験工学あたりがここらへん強いんですかね？

今生き残ってるベテランエンジニアってこういうのを誰から教わるでもなく体得してると思うんですが、意味わからないですね。
私の次の疑問はこういうのを教えてたとして定着するのかどうかです。どうなんですか？そもそも理解してもらえるのか疑問が残ります。自分で書いててわけわかんないし、なぜ自分は働けているのだろうか。
オライリー本も良かったんですが、あれは５年目くらいじゃないと理解できない気もします。

## おまけ：以前、わからないことについて考えてみた例

[UXという理解し難いモノと向き合う　forエンジニア](https://qiita.com/netetahito/items/88a61128d26ff17bd418)
[設計とは何か](https://qiita.com/netetahito/items/85a022e77cc48e7c3d35)