あらまし
ド・モルガンの法則。名著『リーダブルコード』にも登場し、コードレビュー等で出会う頻度も少なくない。
¬(P∨Q)=¬P∧¬Q
¬(P∧Q)=¬P∨¬Q
コードレビューをしていると、「これ、ド・モルガンでリファクタリングできそう」と思うこともしばしばある。
ただ、ド・モルガンを使いたくなるような、判定条件に複雑さが兆しているソースコードの大半は、それ以前にやるべきことがあるんじゃないかと思うことが多い、と感じる。
例
function executeParams(array $params): bool
{
// 諸々の処理
$params = execute($params);
// 処理が「成功したかどうか」を返す
if (
!isset($params['hogeColumn'])
|| !($params['fugaFlg'] !== true && $params['piyoCount'] >= 1)
) {
return false;
}
return true;
}
一見すると、「否定が多い」「括弧が深い」→ド・モルガンで整理できそう
と、条件式そのものを直したくなる。実際、ド・モルガンを使った方が整理された形になるのは間違いない。
ただ、こういった関数の条件部分だけを綺麗にしても、そこまで劇的な効果はないように思う。
リファクタリングするなら
ここでは、条件式をいじる前に責務を分けることを優先する。
function executeParams(array $params): bool
{
// 諸々の処理
$params = execute($params);
return isSucceeded($params);
}
成功判定を別関数に切り出す。
function isSucceeded(array $params): bool
{
// 必須カラムが存在しない場合は失敗
if (!isset($params['hogeColumn'])) {
return false;
}
// fugaFlgが true であること
if ($params['fugaFlg'] !== true) {
return false;
}
// 件数が 1 件以上であること
if ($params['piyoCount'] < 1) {
return false;
}
return true;
}
好き嫌いはあるにせよ、少なくとも元の関数よりはずっと見通しが良くなっていると思う。
結局何が言いたいのか
重要なのは、「ド・モルガンを使うこと」よりも「ド・モルガンを使いたくなるほど条件が絡み合っている構造を、そのままにしないこと」にあるように思う。
コードレビューをする際に、「ド・モルガン」のような名前の付いたテクニカルな指摘はやりやすいが、そもそもそんな条件を放置してよいのか、と一段掘って考えられるようにしたい。