Persistence

続けることに意味がある。

オブジェクト指向設計やプログラミング言語の歴史とこれからについて

はじめに

クソコードを生成して迷惑をかけた気がするので、オブジェクト指向設計について学び直すことにした。今振り返ると、当時の自分はオブジェクト指向設計を全く理解せずにコードを書いていた。極端に言ってしまうと、構造化プログラミングにクラスと継承を付け足したもの、といえば伝わるだろうか。

それでもなぜか自分はプログラミングちょっとデキると思っていた。なぜか。まず第一に、コードの綺麗さにはそれなりに自身があった。「リーダブルコード」などを読んで自分なりにきれいに書くように努めていたからだ。第二に、いくつかのWebApplicationフレームワークを使ってプロダクションコードを書いた経験があったからだ。第三に、ドメイン駆動開発(DDD)やソフトウェアアーキテクチャについても学んできたからだ。(ただ今思うと、概念的にわからないことが多くて上滑りしていた気がする)

しかし今回のクソコードはWebApplicationフレームワークRuby on Rails)の土台の上に、かなりの業務ロジックを追加したもので、それらは全くオブジェクト指向設計の要素や原則を無視したもので、残念ながら変更に脆くとても保守性の悪いものだった。(以前、こんな記事を書いているのにもかかわらず、使わずに時間が立ってしまうと全く忘れてしまうという、悲しいことだ)

更に悪いことに、メタプログラミングを多用し、設計ではなく力技で実装を進めてしまった。弱い人間が強い力を手にすると自滅するというセオリーをここまで身をもって体験するとは、自分でも苦笑してしまう。なお、この記事ではメタプログラミングの失敗についてはこれ以上は触れないことにする。

動的型付け言語は保守性が悪い?

少し本題とは逸れるが、はじめにこの疑問についてケリを付けたかった。職場には比較的、静的型付け言語の支持者が多く、動的型付け言語はプロダクションコードとしても使われて入るものの市民権を得られていない雰囲気があった。そんな中でも自分は割と動的型付け言語肯定派(というか適材適所派)で、よほど特殊な要件がない限りはどちらのタイプの言語でも置き換え可能と思っていた。

でも実際のところ、クソコードを書いてしまったわけだし、動的型付け言語でどうやって保守性の高いコードを書くことができるのかを知りたくなった。そこでまず読んだのが「オブジェクト指向設計実践ガイド」だ。オブジェクト指向設計の本の中では比較的新しいし(それでもオリジナルが発行されたのは2012年)、サンプルはすべてRubyで書かれているのでここに求めている答えがある気がした。

とても良本だった。オブジェクト指向設計の本質や、SOLIDの原則(なんとなく知っていたけどオブジェクト指向設計の話だと思っていなかった。)などが詳しく解説されていて、自分の無知を思い知った。オブジェクト指向設計の本質は「要求の変更」に対して「依存関係」を管理することで変更可能なアプリケーションを構築するということだ。そのために、オブジェクト同士がメッセージを通じて協調し合うことで動作する。これがオブジェクト指向プログラミングだ。また変更可能性を高めるために、カプセル化・継承・委譲・ポリモーフィズムなどの機能が提供され、SOLIDの原則やデザインパターンといった設計原則を用いることでさらにそれを高めていくことができる。

しかし、ダックタイピングの章を読んだところで、どうしても動的型付け言語の怖さを克服することができなかった。結局、動的型付け言語で型(やインターフェイス)が動的に決まることについては、「テストで文書化して保証する」「型宣言がなくてもコンテキストがわかるように設計する」のだが、これらをプロジェクトのメンバー全員が達成することはコスト的にもスキル的にもハードルが高いと感じたからだ。静的型付け言語の本質は「設計が型で表されているから保守性が高い」なんだと思う。(まだうまく言語化できない)

静的 vs 動的 vs ???

では2000年台に入り、その当時、Javaや.Netなどの静的型付け言語があったにもかかわらず、動的型付け言語が流行したのはなぜか。一つは、それらの静的型付け言語がまだ発展途上であったこと。もう一つは、動的型付け言語のフレームワークが台頭し生産性が向上したから。それらが重なってPHPRubyなどの動的型付け言語が使われるようになった。しかし、2010年台は静的型付け言語が進化し生産性が向上し、また保守性を取り戻すべく静的型付け言語が再び流行りだすことになる。また、2018年現在は、静的と動的の両方を併せ持つ言語)が開発されていたり、動的型付け言語であるPythonに型アノテーションを導入する動きなども見られるが、どこまで実用的かはまだわからない。

UMLはなぜ廃れたのか

また脇道に逸れるが、「オブジェクト指向設計実践ガイド」の中でオブジェクト同士のメッセージのやり取りを表すためにシーケンス図が用いられていた。シーケンス図といえばシステム同士のAPIコールを表すことにしか使ったことがなかったので、そもそもUMLオブジェクト指向設計を図示するためのツールだということを知らなかった。そこで、UMLを学べばオブジェクト指向設計をもっと知ることができるのではと思い、マーチン・ファウラー先生の著書「UMLモデリングのエッセンス第3版」を読んだ。

UML モデリングのエッセンス 第3版 (Object Oriented SELECTION)

UML モデリングのエッセンス 第3版 (Object Oriented SELECTION)

この本では最初の2つの章で、UMLの使い方と、UML開発プロセスに適応する方法について書かれている。というのも、UMLの標準化団体は、UMLを厳密化しUMLからプログラムを生成できるようにするために、UMLをどんどん複雑な仕様にしていった。しかし設計からコードを生成するということは、コードと同じレベルの設計書を書くということなので、コードを書いたほうが遥かに楽ということは想像できるだろう。また、開発プロセスについてもウォーターフォール開発ではなくアジャイル開発が主流になり、設計書を書くという行為自体が無駄という風潮が高まり、UMLは姿を消していった。

しかし、本書はそういった厳密なUMLの使い方ではなく、スケッチとして、コミュニケーションツールとしての使い方を推奨している。特に知っておいたほうがいいと思ったのは3章から5章までに書かれているクラス図とシーケンス図だ。クラス図を知っておけばオブジェクト指向設計をする上で必要な継承・集約・コンポジット・依存関係などをすばやく組み立てることができる。また、シーケンス図を知っておけば「オブジェクト指向設計実践ガイド」でも使われているようにカプセル化やSOLIDの原則に違反している箇所に気づきやすくなるため有効だと思う。その他、有用そうなものは、上流工程としてユースケース、詳細設計として状態マシン図くらいだ。

プログラミング言語パラダイム

最後にパラダイムについて少しだけ触れて終わりにする。様々なパラダイムがこれまでの歴史上発明されたにもかかわらず、オブジェクト指向設計は20年以上に渡り第一線のプログラミングパラダイムとして使用されている。しかしここ数年の動きとしては、リアクティブプログラミングや関数型プログラミングにも注目が集まっており、それぞれの特性を理解した上で次に乗る船を決めたい。手始めに「関数型リアクティブプログラミング」などを読んでみたいと思っている。

まとめ

オブジェクト指向言語を使うのなら、オブジェクト指向設計はちゃんと学んだほうがいい。オブジェクト指向設計に関する定番的な本は2000年代前半までに書かれたものが多く、いまさら結構な金額の本を読むのは抵抗があると思うが、逆に考えると定番さえ読めば特に重要な先人の知恵をストレートに得ることができるので楽なのかもしれない。