先日、コードレビューで不思議なコードを見ました。再現してみるとこんな感じです。
if(! running) { start(); // (A) } if(running) { // (B) }
最初に見たとき、本当になにが起こっているのかわかりませんでした。コードを見れば明らかに(A)と(B)は排他になっているわけでして、if(running){ (B) }else{ (A) }で済むわけで。
実は。このコードはメンバ関数の一部で、running
はデータメンバ、start
はメンバ関数。そうrunning
はstart
の中で書き換えられているわけです。つまり上のコードは、実行されていなかった(if(!running)
)ら、実行開始する(start()
)。で、実際に実行できたら(if(running)
)(B)を実行というものでした。
実質、running
はグローバル変数であり、メンバ関数をまたがってコンテクストを引きずってしまったのが混乱の原因。
よくないコードと切り捨てるのは簡単なんですが、なぜよくないかを説明するのは以外と厄介というのを実感してしまった次第(「カプセル化!」で説明できればいいんですが、それも同じぐらい厄介そうです)。