オブジェクト指向
プログラミング教育
アスペクト指向
プログラミング作法

オブジェクト指向、アスペクト指向は用法・用量を守ってご使用ください

はじめに

このドキュメントは、オブジェクト指向、アスペクト指向において、濫用すべきでない概念について自分の考えをまとめたものです。

なお、タイトルは「オブジェクト指向、アスペクト指向」としていますが、今回取り上げるのはその中の極一部の概念です。

ソフトウェアの品質

ソフトウェアの品質についてはいろいろな指標があると思いますが、バグがないのは大前提として、保守性がその中でも重要なものだと考えています。

その理由は、「プログラムの寿命が長い」ことが挙げられます。

作成したモジュールは、そのモジュールを搭載した製品が無くなるまで生き続けます。最初に搭載した製品が無くなっても、全く異なる製品に搭載されて生き続けることもあります。そういったモジュールは、場合によっては十年以上生き続けます。

そのように「プログラムの寿命が長い」ことによって、当初の作成者がいなくなってしまい、そのモジュールがブラックボックス化することがあります。十年以上ではないにしろ、数年で担当者が入れ替るのは良くあることです。

そして、担当者が入れ替わったタイミングに限って、そのモジュール部分の不具合が見付かったり、機能追加が必要になってモジュールを変更することになります。

こうした場合、もっとも重要になるのは保守性です。もちろん、そのモジュールに対する設計ドキュメントやテストは重要ですが、新しく見付かった不具合や機能追加に対する設計ドキュメントやテストなんてものは存在するはずがありません。モジュールのコードを読み解いて、不具合の原因を特定・修正したり、機能追加する必要があります。

この作業のしやすさが、保守性そのものです。

オブジェクト指向、アスペクト指向には、この保守性を下げてしまう概念を含みます。

使用に対して注意が必要な概念

オブジェクト指向

オブジェクト指向の概念で注意が必要なモノというと、「継承」を挙げる人は多いと思います。よって、ここでは「継承」はあえて挙げません。

では何を挙げるかというと、「演算子オーバーロード」を挙げます。

ただ、こう書くと「演算子オーバーロード」==「オブジェクト指向」じゃないだろ。というツッコミが来ると思いますが、演算子オーバーロードもポリモーフィズムの一部なのでその辺りは大目に見てください。

アスペクト指向

保守性におけるアスペクト指向の問題は、「アドバイス」です。

アスペクト指向におけるアドバイスを否定するとアスペクト指向そのものを否定することに繋がりますが、保守性を考えると悪い面が見えます。

注意が必要な理由

ここでは、「保守性」において上記の概念が何故問題になるか説明します。

まず前提として、保守するエンジニアは対象のモジュールを開発したエンジニアではないとします。

このとき、保守を行なうエンジニアはモジュールのコードを読み解きますが、上記の演算子オーバーロードや、アドバイスが利用されている箇所などは見逃されがちです。

なぜならば、どちらも使用しているコード上は関数呼び出しをしているとは見えないからです。関数呼び出しが明示的に行なわれない演算子オーバーロードや、アドバイスでは、保守を行なうエンジニアの注意が向き難くなります。

この「見え難い」状態を強引に例えると、関数型プログラミングにおける副作用として例えることができます。

関数型プログラミングでは、コード上に現われる明確な入力と出力以外の隠れた処理を副作用としています。一方、演算子オーバーロードやアドバイスでは、コード上には直接的には現われない関数呼び出しが行なわれています。これは関数型プログラミングの副作用と似ていると思いませんか?

ここまでくれば、なぜ私が演算子オーバーロードや、アドバイスが保守性を下げる要因に成り得ると考えているか理解していただけたと思います。

関数型プログラミングは、出来るだけ副作用を排除することで処理の複雑化を防ぐアプローチです。

演算子オーバーロードや、アドバイスは、前述している通り副作用そのものになる可能性があります。これにより処理が複雑化され、保守性の低下につながる可能性があります。

演算子オーバーロードについては、関数呼び出しのシンタックスシュガーなんだから気を付けてしかるべき、という意見もあるかと思います。しかし、 C++ の STL のような誰でも知っているクラスの演算子オーバーロードならともかく、独自に定義してあるようなマイナーなものだと、見逃されがちです。

また、次の記事にあるようなことが技術的には出来てしまいます。

https://developers.srad.jp/story/18/01/18/0648254/

こんなことを敢てやる人はいないでしょうが、演算子オーバーロードを使うと見た目とは異なる副作用が起きてしまう可能性が出てしまいます。

保守するエンジニアが、モジュールを開発したエンジニアと同一であれば上記の概念を利用しても保守性低下にはならないかもしれません。しかし、往々にして保守は別のエンジニアが行なうことになります。そうした時に、コード上に見え難い処理があるのは、保守性に問題があると言わざるを得ないと思います。このような処理は、まるで「見えないトラップ」のように感じてしまいます。

「見えるトラップ」と「見えないトラップ」を比べれば、「見えないトラップ」が圧倒的に厄介であることは理解していただけるでしょう。

保守性を下げないようにするには

保守性を下げないようにするための一番簡単な方法は、「保守性を下げる可能性のあるものの利用を禁止すること」です。

しかし、無闇に禁止すると今度は生産性が低下する可能性があります。

「生産性」と「保守性」どちらの低下も防ぐには、演算子オーバーロードや、アドバイスの利用を必要最低限にし、その仕様についてプロジェクト全体の知識として共有するべきです。

プロジェクト全体の知識とすることで、「見えないトラップ」が「見え見えの落とし穴」くらいになります。

まぁ、「見え見えの落とし穴」にあえてハマる「お約束」もあるかもしれませんが。。