リファクタリングとヒステリシス

リファクタリングとはソースコードエントロピーを小さく抑えることであり、これを言い換えれば「設計のヒステリシスを小さく抑えること」なんじゃないかと思う。

例として、機能A と 機能B の2つの機能を備えたソフトウェアの開発を考えてみる。

最初から 機能A と 機能B の2つの機能が必要であることを知っていれば、全体を見渡した奇麗な設計は比較的容易である。最初から 機能A と 機能B に共通の構造を抽出することも出来るだろうし、抽象化されたインターフェイスを用いたオブジェクト指向設計も出来るだろう。

しかし、現実には最初から全体像を知ることは難しい。まず 機能A の機能を要求され、次に 機能B の機能が要求される。あるいは逆の順序で、最初に 機能B が要求されて次に 機能A が要求される。最初の機能に着手している時点では、そのあとに要求される機能のことは全く知らされていない状態だ。

次の3つのパターンで、最終製品の設計に違いは現れるだろうか。

  • 最初から 機能A と 機能B を把握していた場合
  • まず 機能A が要求され、次に 機能B が要求された場合
  • まず 機能B が要求され、次に 機能A が要求された場合

下手な人が作ると、設計にヒステリシスが現れてしまう。つまり、ソースコードを読むだけでどの機能の順に開発したのかが見当がついてしまう。最初に開発した機能はシンプルに実現できているのに、あとから付け足した機能はいかにも付け足しの無理のある構造になってしまう。

目指すべき理想は、3つのパターンですべて同じ設計になることだ。A → B の順序だろうと B → A の順序だろうと、最終的には「あたかも最初から A と B が必要であることを知っていたかのような」設計に収束させていくのが理想なのだ。この理想を目指してコードを修正していく行為こそがリファクタリングである。つまり、リファクタリングとは設計からヒステリシスを除去すること、と言えるんじゃないだろうか。

だから、何か機能追加や仕様変更があるたびに「もし最初からこの機能/仕様を知っていたらどう設計しただろうか」と自問自答するのが、うまいリファクタリングのコツになるんじゃないかと思う。

追記:「ヒステリシス」とは

ブクマのコメントに「ヒステリシスって何?」とあったので。

ヒステリシス (Hysteresis) とは、ある系(主に物理系)の状態が、現在加えられている力だけでなく、過去に加わった力に依存して変化すること。

ヒステリシス - Wikipedia

以上から分かるように、本来は物理系の用語。この用語から連想して、ここでは次のような意味で使っている。

ソフトウェア設計におけるヒステリシスとは、ソースコードの状態が、現在与えられている仕様だけでなく、過去に与えられた仕様に依存して変化すること。

僕は大学で機械工学をやっていたので、なんでも力学系からの連想で理解するのが好きだ。ここでは、「ソフトウェア構造」という閉じた系(構造物)に、外部から「仕様」という荷重が加えられている様子をイメージして欲しい。このときソフトウェア構造は、まるで生き物のように自らの組織を変化させて、外部からの荷重に耐えようとするとしよう。これは例えば骨の組織を連想すればよい。骨は荷重がかかると骨密度が上がるし、寝たきりだと荷重がかからないので骨粗鬆症になってしまう。

この荷重に応じて再構成されるソフトウェア構造が、過去の経緯に関わらず常に最適な構造に収束するのであれば、ヒステリシスはないといえる。逆に、過去の経緯を引きずってしまい最適な構造まで到達できないのであれば、ヒステリシスがあるといえる。

とはいえ、このヒステリスという用語の用法は、僕が勝手に連想したオレオレ用法なので、一般に通じるかどうかは分からない。