エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

分断されるコンテクスト

先日、コードレビューで不思議なコードを見ました。再現してみるとこんな感じです。

    if(! running)
    {
        start(); // (A)
    }

    if(running)
    {
        // (B)
    }

最初に見たとき、本当になにが起こっているのかわかりませんでした。コードを見れば明らかに(A)と(B)は排他になっているわけでして、if(running){ (B) }else{ (A) }で済むわけで。

実は。このコードはメンバ関数の一部で、runningはデータメンバ、startメンバ関数。そうrunningstartの中で書き換えられているわけです。つまり上のコードは、実行されていなかった(if(!running))ら、実行開始する(start())。で、実際に実行できたら(if(running))(B)を実行というものでした。
実質、runningグローバル変数であり、メンバ関数をまたがってコンテクストを引きずってしまったのが混乱の原因。
よくないコードと切り捨てるのは簡単なんですが、なぜよくないかを説明するのは以外と厄介というのを実感してしまった次第(「カプセル化!」で説明できればいいんですが、それも同じぐらい厄介そうです)。