先日、コードレビューで不思議なコードを見ました。再現してみるとこんな感じです。
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はグローバル変数であり、メンバ関数をまたがってコンテクストを引きずってしまったのが混乱の原因。
よくないコードと切り捨てるのは簡単なんですが、なぜよくないかを説明するのは以外と厄介というのを実感してしまった次第(「カプセル化!」で説明できればいいんですが、それも同じぐらい厄介そうです)。