RAIIとconstオブジェクト

C++の世界では、オブジェクトというのは生まれた時から完成していて、未初期化の赤ちゃん状態をなるべくなくそうという思想がある。RAIIというやつだけれども、一方でconst教というのもある。途中で値を変える必要のないオブジェクトは、値を変えようとする不貞の輩を見つけるために、constで宣言しようという思想もある。が、RAIIとconst教が同居すると、ちょっと難しい局面もある。

    Feeling feeling;
    if (today->isFineDay())
    {
        feeling = GOOD;
    }
    else
    {
        feeling = SO_SO;
    }

こういうことをやりたいとする。ここにconst教とRAIIの教条を持ち込むと、こうなる。

    const Feeling feeling = (today->isFineDay() ? GOOD : SO_SO);

天気が変わらないうちは俺の気分も変わりゃしねーぜ、と。こういう書き方ができると、グッと3項演算子のファンになったりするのだけれど、コーディング規約で3項演算子が禁止だったり、Allmanスタイルで統一されていたりすると、単なる値のスイッチングが上のような9行の大作になる。1行だと凝集度高杉だけど9行もちょっと極端だなぁ、となる。

まあ、boolからFeeling値を取得する手続きを無名のままにしないで名前の付いた小さな関数を書け、ってのがリーダブルコードの思想なんですが。でも英語ネイティブじゃないと、無数にある小さな関数の機能を簡潔な名前で書き分けるだけの文芸的センスがなかったりして、なかなか苦労するわけです。読むにしても定義を検索して骨が折れるし、調べてみてなんだよこれだけかよ、みたいな気分になったり、英語名が動詞も名詞も形容詞も無視してて変なことになってたりして、そのまま書いてくれよ、ということが少なくない。

/// getting one's feeling by weather of the day.
Feeling MyAwesomeClass::Impl::getFeeling(const DayInfo& theDay) const
{
    Feeling feeling;

    if (theDay->isFineDay())
    {
        feeling = Feeling::GOOD;
    }
    else
    {
        feeling = Feeling::SO_SO;
    }

    return feeling;
}

とかやってから

    const Feeling feeling = getFeeling(today);

となる、と。C++はメンバじゃない無名名前空間の関数を認めるので、ここではMyAwesomeClass::Implのメンバにしたりとかconst関数宣言とかは不要だけれども、なんとなく最悪ケースを想像させるような書き方にしてみた。詳細が隠蔽されて美しくはあるんだが、主要処理を書いている段階でここまでディテールに凝るのはなかなか難しいんだよな。リファクタリングマターだな、この水準は。