冪等性(べきとうせい)とは、ある操作を1回行っても複数回行っても結果が同じであることをいう概念である。
言葉の響きは難しいが、これはプログラマーなら何度も遭遇するシチュエーションなので、是非とも覚えておきたい。
たとえばExcelマクロにおいて、以下のコードは冪等ではない。
実行するたびに、オートフィルターのON / OFFが切り替わってしまうからだ。
Sub NotIdempotent() Selection.AutoFilter End Sub
先日業務であるツールを使用する様子を見たが、そのツールで使われていたオートフィルターを設定するコードは冪等ではなかった。
すると、加工するブックは予めオートフィルターを外しておかなければならない。
冪等性に注意を払ってこのコードを作り直すと、以下のようになる。
Sub Idempotent() If Not Selection.Parent.AutoFilterMode Then Selection.AutoFilter End If End Sub
選択範囲の親(ワークシート)を確認し、フィルターがかかっていたらそれ以上は実行しないという処理である。
ただこの処理でもまだ詰めが甘い。なぜなら、全く意図しない場所にフィルターが掛かっていたとしても、処理済と見做してしまうからだ。
改良したのがこちらのコード。まず狙った位置にオートフィルターをかけ、もし掛かっていなければ外れたと判断してやり直す。
Sub IdempotentFixed() Do Selection.AutoFilter Loop Until Selection.Parent.AutoFilterMode End Sub
あるいは、最初からフィルターを解除してしまい、それからフィルターを掛ける。
Sub IdempotentFixed2() Selection.Parent.AutoFilterMode = False Selection.AutoFilter End Sub
前者はバグにより無限ループを作らないとも限らないので、最初からフィルターを外す後者の方が良いかもしれない。
いずれのコードも冪等性は確保されている。
この冪等性という概念を知っていると、自分のマクロが冪等性を担保しているかという批判的な眼を養うことができ、より安定したコード作成ができるようになると思う。
注意:今回は簡単に紹介する目的でSelectionを使用していますが、実際に組み込むマクロではRangeやWorksheetを特定して使っています。