読者です 読者をやめる 読者になる 読者になる

JavaScript勉強会

JavaScriptの学習日記

JavaScriptで継承を使わないプログラミングスタイル

JavaScript

JavaScriptでは「継承による差分プログラミング」はモダンではない、という意見がありました。

なるほど、「継承による差分プログラミング」を使わないスタイルもあるんですね?(参考になります)

 

jsstudy.hatenablog.com

 

オブジェクト指向って便利なの? - JavaScript勉強会

うへええええ継承による差分プログラミングとか現代に言わないでくれよ。しかも「JSはプロトタイプベースのOOP」を初めとして間違いが多いぞ

2017/03/27 09:42

b.hatena.ne.jp

 

(1) 継承による差分プログラミングは、現代では廃れた古い手法?

(2) JavaScriptはプロトタイプベースのオブジェクト指向プログラミング言語ではない?

 

実際のところ、どうなんでしょうか?

JSは、関数型プログラミングで書くのがモダンとか?

 

関数型プログラミングの基礎 JavaScriptを使って学ぶ

関数型プログラミングの基礎 JavaScriptを使って学ぶ

 

 

勉強がてら、調べてみましょう。

(以下、「オブジェクト指向プログラミング」を「OOP」と略記)

 

OOPアンチパターン

OOPのノウハウ(良い方法や悪い方法)は、様々なパターン(定石)のカタログとして知られています。

 

アーキテクチャパターンとは - はてなキーワード

ソフトウェアパターンの一種で、特にソフトウェアのアーキテクチャ (構造) に関するもの。

アーキテクチャーパターンとは何か | Think IT(シンクイット)

Patterns of Enterprise Application Architecture

 

デザインパターン (ソフトウェア) - Wikipedia

ソフトウェア開発におけるデザインパターン(型紙(かたがみ)または設計パターン、design pattern)とは、過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。

 

アンチパターン - Wikipedia

アンチパターン (anti-pattern) とは、ある問題に対する、不適切な解決策を分類したものである。
主に失敗した開発プロセスに焦点を当てて失敗に陥るパターンを類型化する。そうすることで、そのような事例の早期発見と対応策に関しての提案を目的とする。 

 

ソフトウェアシステムアーキテクチャ構築の原理 第2版

ソフトウェアシステムアーキテクチャ構築の原理 第2版

 

 

継承による差分プログラミングの注意点は、「レガシーコード改善ガイド」などで紹介されています。

 

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

 

 

OOPには過去の資産として、こういう本がたくさんあるので、ベストセラー本を一通り読めば、先人の工夫を習得できます。(受け売りw)

 

d.hatena.ne.jp

どうやって機能を追加すればよいのでしょうか?

オブジェクト指向言語を使用しています。

どうする?

継承を使用した「差分プログラミング」を適用します。

 

ただ、差分プログラミングをうまく行うためには、いくつかの落とし穴に気をつけなければなりません。代表的な問題は「リスコフの置換原則(LSP)」違反です。

LSPは、「クラスの利用者が、それがサブクラスのオブジェクトであることを知らずに使えるべきである」という原則です。LSP違反を避けるための機械的な方法はありません。クラスがLSPを守っているかどうかは、そのクラスを使う側が何を期待しているかに依存します。

LSP違反を避けるためには、以下の経験則が役立ちます。

  1. 可能な限り、具象メソッドをオーバーライドしない。
  2. 具象メソッドをオーバーライドするなら、そのメソッドの中で、オーバーライド対象のメソッドを呼ぶことができるかどうかを確認する。

 

SOLID原則

オブジェクト指向設計原則 - Strategic Choice

優れたオブジェクト指向開発のための指針。

必ず守らなければならないのではなく、まずそれで考えることが重要。 

  • 単一責任の原則(SRP)
  • オープン・クローズドの原則(OCP)
  • リスコフの置換原則(LSP)
  • 依存関係逆転の原則(DIP
  • インターフェイス分離の原則(ISP

 

頭文字をとって「SOLID原則」ともいわれる。

 

アジャイル設計と5つの原則 - かまずにまるのみ。

リスコフの置換原則 (LSP : Liskov Substitution Principle)

派生型はその基本型と置換可能でなければならない。

 

継承による差分プログラミングは、「リスコフの置換原則」に違反しないよう注意が必要です。

 

オブジェクト指向の基本機能

オブジェクト指向の基本的な仕組みには、「継承」だけでなく「メッセージング」などもあります。

→ 新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡 - Qiita

→ オブジェクト指向技術の主要概念

  • 分散協調型計算モデル: 複数の自律的機能をもつオブジェクトがメッセージをやりとりしながら協調して問題を解決するような計算モデル
  • データ抽象化機能: 個々のオブジェクトをデータと手続きを一体化した自律的機能モジュールとして定義する機構
  • インスタンス生成機能: 機能が同じでデータの値だけが異なる複数のオブジェクトを効率良く生成する機構
  • クラスの階層化と継承機能: 上位クラスの持つ機能を下位クラスの機能として継承できるようなクラス階層構造を導入し、少しだけ機能の異なるオブジェクトを効率良く作成する機構

 

f:id:jsstudy:20170329205935g:plain

 

個人的には、「枯れた技術」(よく使われてノウハウが蓄積されている古い技術)は、適材適所で使えば、有用だと思っています。

 

決定版・ゲームの神様 横井軍平のことば (P-Vine Books)

決定版・ゲームの神様 横井軍平のことば (P-Vine Books)

 

 

ここまでの前提を基に、「継承による差分プログラミング」を使わないプログラミングスタイルについて検討してみましょう。

 

データ構造としてのオブジェクト

何らかの事情で、「継承」の使用が禁止されたコーディング規約があったと仮定します。(思考実験)

 継承を使わないでも、OOPは可能でしょうか?

→YES!

 

デメリット

差分プログラミングを行わないと、クラス数が激増するかもしれませんが、IDEの支援機能があれば、大した問題ではないでしょうw

=継承の代わりに、単純にクラスをコピペして、似たようなクラスを作ることは可能。

クラスが増える分だけ、管理が大変になりそうだけど、IDEで検索/管理すれば何とかなる?

JavaScript用のIDEだと「WebStorm」とかが便利?

samuraism.com

 

メリット

継承を使わない分だけ、クラス間の依存関係がなくなり、疎結合に保てますね。

クラス間のつながりは、メッセージングのためのAPIを考慮するだけでOK。

→テストも手軽になるかも!?

 

クラスは、型クラスを作り、データ構造の一種として利用するだけにとどめても良いのでしょう。

オブジェクトは、プロパティー、メソッドをまとめておく入れ物として利用すればOK。

 

PACアーキテクチャ

OOPで継承を使わない場合、高機能なエージェント(オブジェクト)が、お互いにメッセージを交換しながら、駆動することになりそうですね?

パターンカタログの中から、相性が良さそうなアーキテクチャーパターンを検討すると、PAC(Presentation-Abstract-Controller)アーキテクチャなどが良いかも。

 

階層型コンポーネント指向アーキテクチャによるビジネスアプリケーション構築 ~SystemDirector Enterpriseでの開発手法~ | デベロッパーセンター

1-2 UIモデルへの適合度が高いPACアーキテクチャについて

疎結合、非同期処理に優れたアーキテクチャとして、PACアーキテクチャパターンが、ソフトウェアアーキテクチャをまとめた本として有名な「Pattern-Oriented Software Architecture」に紹介されています。

  • MVCの View に相当する Presentation
  • MVCの Controllerに相当する Control
  • MVC の Model に相当する Abstraction

そして、それらをまとめたコンポーネントAgent という単位です。

  • Agent内では P→A , A→P といった通信はできず、C→P , C→A のみの通信を行います。
  • Agent同士は C→C で通信を行います。

f:id:jsstudy:20170329203045g:plain

 

f:id:jsstudy:20170329204344j:plain

(via http://objectclub.jp/

 

各エージェントのオブジェクトは個別に作れば、継承を使わなくてもOK。

PACパターンは、HMVCパターンとも似ているので、GUIを作るのに向いており、JavaScriptでSPAを作るときにも役立ちそうです。

 

Presentation–abstraction–control - Wikipedia

Hierarchical model–view–controller - Wikipedia

f:id:jsstudy:20170329205208p:plain

The structure of an application with PAC.

 

マイクロサービス指向アーキテクチャ

JavaScriptのエコシステムを利用して、Webアプリのフロントエンド、バックエンドをPACで作れば、マイクロサービスっぽく作れるような気がします。

疎結合のパーツがたくさん集まって、システムが構築されているイメージ。

 

マイクロサービス(Microservices) | NTTデータ

マイクロサービスとはアーキテクチャスタイルの1つであり、小さなサービスの組み合わせにより単一のアプリケーションを開発するアプローチです。

そして、その小さなサービスはそれぞれ自身のプロセスで動作し、軽量な方式で通信をします(通常、HTTP Resource APIが使われます)。

個々のサービスは、業務上の機能に沿って構築され、その配備は完全に自動化されたものになります。

それらサービスに対しての集中管理は最低限にし、また、それぞれのサービスは異なるプログラミング言語や異なるデータストレージ技術を利用します。

 

f:id:jsstudy:20170329211313j:plain

 

以上は、単なる思考実験に過ぎませんが、OOPで継承を使わずに、疎結合のエージェントを実装すれば、PACやMOAっぽい構造になると予想します。

パブリッククラウド全盛の時代にあって、Webアプリの設計としては、意外と良いかもしれない!?

 

ところで、継承を使わないJavaScriptフレームワークって、どんな実装、プロダクトがあるんでしょうか?

→ 一般的な制御の反転(Inversion of Control:IoC)、Delegateパターンが不要のフレームワークがあれば、ライブラリーっぽく使えて、学習コストが低いかも。

 

モダンなJavaScriptでは、「継承による差分プログラミング」を使わないようなので、みんなどんなコードを書いているのか、GitHubなどを拝見してみたいと思います。

 

 

JavaScript フレームワーク入門

JavaScript フレームワーク入門