――聞こえるでしょうか。
KORG Gadget+GUMIの新曲、"呼応"を公開しました。お聴きいただければ幸いです。
諸事情あってITエンジニア本大賞2023技術書部門大賞受賞作の『良いコード/悪いコードで学ぶ設計入門』(仙塲大也、技術評論社)にいまごろになって目を通しました。「設計」にかぎらない幅広いトピックをあつかう点で看板に偽りありですが、その手広さが支持された一因なのでしょう。ステップアップを図りたい初級者にとって有用なアドバイスが得られる本であることは確かだと思います。一方で個人的には見過ごせない記述もまま見られ、手放しでお勧めできる本でもないというのが率直な評価です。いくつかメモします。
(用語は同書を踏襲します)
同書の強い主張の一つに「クラスは原則として不変にすること」があります。基本的には同意しますが、その主張のしかたには疑問があります。
まず本書のJavaによるサンプルコードで不変と主張されるクラスの定義は、クラスの宣言でfinal修飾子を指定せず継承を許している点で不完全です。
このあたりは言語の仕様にもよりますが、Javaは継承すれば派生クラスは基本クラスのメソッドのオーバーライドが可能になります(ただしprivateメソッドやfinal修飾子が指定されたメソッドは除く。オーバーライドの例は同書でもリスト8.16で例示があります)。オーバーライドで基本クラスのメソッドやインスタンス変数を参照しないようにすれば、基本クラスの機能をまったく使わずかつ基本クラスのインスタンスと置き換えられる派生クラスが定義でき、その派生クラスのインスタンスは基本クラスのインスタンスの代わりに使えます。つまり不変のクラスを引数とするメソッドに可変のクラスのインスタンスを引き渡せます。
(そんなことをする人はいない、と思われた方には、人間の思考の柔軟性を低く見積もりすぎと申し上げます)
全体を通して堅牢性を主張しながら堅牢にし切れていないクラス定義が呈示されていて不思議に思えます。
(なおJavaでクラスを不変にするには継承を禁止する必要ありという指摘はBloch『Effective Java』が初版の段階で行っています)
「第4章 不変の活用」の「4.2.3 副作用のデメリット」の説明も十分とは言えません。
第5章ではインスタンス変数を使えないので低凝集にならざるを得ないとの理由でstaticメソッドを非推奨としていますが、この主張はずいぶん雑に思えます。
わかりやすいスローガンであるがゆえに、型とメソッドの関係を考える機会を奪うという意味でデメリットのほうがおおきいと考えます。
(本件にかぎらず、思考停止を惹起するようなわかりやすいフレーズが多用されているのは気になる点です)
条件分岐は整理されるに越したことはありませんが、同書のswitchに関する整理は筋が悪いと思います。
「「分岐を書きそうになったら、まずinterface設計!」」(p.123)とありますが、型が適切に定義されていれば型にまつわる判定は自然に減るものです(その意味でswitchの多さが適切でない設計を示すことはあります)。分岐を減らすためにinterface定義を検討するのは本末転倒です。
著者はinterfaceを推奨する一方、先に触れたとおり継承を前提としたクラスについては「継承はよっぽど注意して扱わないと危険、継承は推奨しません」(p.155) と否定的です。
たしかに現状のプログラミング言語のオブジェクト指向サポート機能はおおむね乱用を防ぎづらい仕様になっており、その観点から基本的には首肯できる意見です(クラス定義の構文は継承は原則禁止、オプトインで継承可とするほうが望ましいと個人的には考えます)。しかし継承のほうが自然に表現できる型や処理はたしかに存在します。「すぐに密結合に陥」(p.154)るから推奨しない、というのは短絡的でしょう(基本クラスのカプセル化が不十分なときの派生クラスとの密結合は継承固有と言えるでしょうが、それ以外は継承関係でなくとも生じるように思えます)。継承が有用なケースや継承する際の注意点に言及がないのは不親切と言わざるをえません。
またここまで言いながら「第13章 モデリング」の「13.4.2 機能性をイノベートする「深いモデル」」は継承関係の解説が主でinterfaceは登場しません(記述から言って呈示されているクラス図の汎化関係がinterfaceを想定したものとは読みづらい。図6.2では記述されているステレオタイプもここでは記述されていない)。型について=クラスやinterfaceについてどのように考えるのか、設計でどのようにモデリングしてどのように実装に落とし込むのか、説明不足は否めないと思います。
同書は数多くの原則や法則に触れていて後学に資すると思いますが、中にはそのまま受け止めないほうがよいものもあります。
なおマジカルナンバーについては私も誤解していたので人のことは言えません。俗説に向き合うのはむずかしいですね。
同書では触れられていないトピックで、私見では次の2点の欠落が特に気になります。
前者は高品質な設計・実装に有用ですし、後者は複雑なコレクション操作をスマートに解決します(「第7章 コレクション」のサンプルコードの多くはJava Stream APIで別解を出せます)。
同書の記述から察するにどちらも著者の立場とは相容れないものと推察され、そのために触れられなかったのではないかとと思いますが、どちらも優れたソフトウェア開発に資する有用な考えかた・機能ですので、触れられていないのは個人的にはたいへん残念です。
他にも著者と見解の異なる点はままあるのですが、長くなったのでここまでにします。参考までに他の方の評のリンクを挙げておきます。
最後にひとつ、著者や読者に問いかけておきます。「クソコード」なる言葉を使い動画を公開してアクセス数を誇るような人が用いる「心理的安全性」(p.334の「16.1.3 心理的安全性」で触れられています)という言葉にどれだけ信頼がおけるものとお考えでしょうか?
ライブコーディングの情報をすこし収集してみようかとふと思い、『演奏するプログラミング、ライブコーディングの思想と実践』に目を通したりして、これはいまならブラウザでも実現できるのではないかという気がしたのでちょっとプロジェクトを作ってみました。ウェブオーディオAPIのラッパーであるTone.jsを呼び出すコードをブラウザ上で入力・実行できます。
https://github.com/DBC-Works/live-tone
……しかし自分で作っておいてなんですが、Tone.jsのAPIがおよそライブコーディングに向かないため、実用性にははなはだ疑問が残ります。Tone.jsの挙動も個人的にはいまいちよくわかりません(ドキュメントにも誤りがあったりして)。まあProof of Concept、概念実装ということで大目に見ていただければ。