対象読者
- プログラミング初学者の方
- 色々ググってみたが、本タイトルについて理解できなかった方
結論
両者をググったものをまとめると、
- ライブラリとは、再利用可能な部品をまとめたもの
- フレームワークとは、枠組みが予め決まっている部品をあつめたもの
と出てくる。
しかし、こんな抽象的な説明では、何を言ってるかワケワカメだ。
そこで、本記事では、
- プログラミングの語彙による説明
- 文章作成の比喩による説明(∵ソースコードは人間が読むための文章)
という2本立てで、ライブラリとフレームワークについて説明する。
ライブラリとは、再利用可能な部品のまとまり
プログラムにおける部品とは、再利用できる単位のことで、関数やクラスのことだ。部品をまとめたものをライブラリと呼ぶ。特に、クラスを集めたものをクラスライブラリと呼ぶ。
上のライブラリとフレームワークのまとめで、共通のキーワード「部品」が出てきた。まず、これを押さえなければ、ライブラリやフレームワークについて理解することはできない。
部品とは再利用できるプログラミングの単位
関数とは、ある入力に対して、出力を返すものだ(※1)。
その出力を得るための具体的な処理は、関数を使う側からは見えない(※2)。それ故に、コードの前後の文脈とは関係なしに、いつでも、どこからでも関数を使い回すこと(再利用)ができるため、部品と呼ぶことができる。
クラスとは、変数と関数をまとめた自作のデータ型のことだ。関連のあるグローバル変数と関数を1つにまとめたもので、関数よりも大きい部品だ。
関数の具体的な処理が状態によって変化する場合、グローバル変数を使うことになる。例えば、真偽値の状態を表すグローバル変数(フラグと呼ぶ)によって、関数の出力を変化させたりするような処理だ。
グローバル変数はその変数に依存した処理を作り出し、部品化を阻害する。上の例の場合、関数とフラグは絡み合っていて、関数のみを抜き出して、他の場所で再利用することができない。クラスはこの問題を解決できる、便利な部品だ。
※1
- 入力のことを引数と呼び、
- 出力を戻り値、返り値などと呼ぶ。
- 出力を持たない関数を特にサブルーチン呼ぶ。
※2
呼び出し側から見えなくすることは、プログラミングにおいて非常に重要で、カプセル化と呼ばれる。
ライブラリを用いたライブラリ
自分で作った部品をまとめるだけで、それは自作ライブラリとなる(例えば、関数を数個まとめる)。
1からライブラリを自作する場合、作者は組み込み(※1)のデータ構造と関数を組み合わせることで、部品を作ることになる。しかし、他のライブラリの部品を使ってもよい。こうして作られたライブラリは、謂わば、ライブラリに依存したライブラリと言える。
このように、ライブラリを用いたライブラリみたいなものも存在する。
※1 組み込み(ビルトイン)とは
組み込みとは、そのプログラミング言語に予め備わっている部品のことだ。例えば、データ構造や標準出力する関数(print)などだ。
配列や辞書のようなデータ構造は構造体やクラスを用いて自作することも可能だが、ユーザーの便宜を図って、予めプログラミング言語がそれらの機能を提供してくれる。これがビルトインだ。
フレームワークとは、枠組みが予め決まっている部品をあつめたもの
フレームワークも部品のあつまりのことであり、ライブラリだ。さらにその部品群に枠組みが備わった特殊な場合をフレームワークと呼ぶ。
この「枠組み」というのが抽象的で難しく、これを厳密に理解するためにはオブジェクト指向を理解しなければならない。
枠組みとは、インターフェースを守ることだ
ここでいう枠組みとは、部品群を予め決まった方法で組み合わせることでプログラムが強制されるこという。
本記事では、プログラミングを文章作成で例えることで、初学者の方にも分かりやすくライブラリとフレームワークの違いを説明する。
文章作成の比喩では、
- ライブラリは引用
- フレームワークは踏襲
である。
一方、プログラマが言いそうな感じでは、
- ライブラリは機能の再利用
- フレームワークは構造の再利用
である。
まずは、文章作成の比喩について説明し、その後、プログラミングの用語を用いてより厳密に説明する(文章作成の比喩をスキップはこちら)。
文章作成の比喩
通常、プログラミング言語とは、高級言語を意味する。高級言語とは、人間にとって分かりやすい言葉によって、パソコンへの命令を記述するためのものだ。
故に、プログラム(厳密にはソースコード)は人間が読むためのものであり、文章に他ならない。よって、ライブラリやフレームワークを文章作成の観点から説明することができる。
ライブラリとは引用である
文章を一から全てを書き尽くすことは大変だ。しかし、悩む必要はない、ライブラリさえあればね!
外部にある文章を引用することで、自前で書かなければならない文字数を削減することができる。引用した前提を土台として、より簡潔に、より高度な内容の執筆に専念できるようになる。
外部にある文章をライブラリと呼ぶ(故にライブラリを外部モジュールと呼んだりする)。以下で例を見る。
例:高校数学の教科書を書く
あなたが高校数学の教科書を書くことになったとしよう。
そして、余弦定理(\(c^2=a^2+b^2 -2ab\cos\theta\))についてまとめることになってしまった。これを証明するためには、
- 三平方の定理
- 三角形の相似
- …
等の中学数学の知識が必要になる。さらに、中学数学を理解するためには算数の知識が必要となる。しかし、それらの知識は高校以前に学習済みのはずであり、再び、それらを説明から始めるならば、大変な労力が必要となる。そこで、高校以前の内容は小中学生時代の教科書を参考にしてもらう(引用)ことにすれば、あなたは、余弦定理の証明のみに専念することができる。この例では、算数と中学数学の教科書がライブラリにあたる。
中学数学は算数を土台にしているため、中学数学の教科書は算数の教科書を引用している。同様に、ライブラリを利用して作られたライブラリも存在する。
フレームワークとは踏襲である
文章をどのように組み立てれば、より良く内容を伝えることができるのだろうか。特に、長文を書く時、文章の構成はより重要となる。しかし、悩む必要はない、フレームワークさえあればね!
文章構成のテンプレートのことをフレームワークと呼ぶ。これがあれば、テンプレートに沿って書き進めるだけでよく、文章の組み立てに悩むことはない。しかも、実績のあるフレームワークを使えば、より優れた文章を安心して構成できるし、優れた書き方の勉強にもなる。
以下でフレームワークを用いて物語を作る例を見る。
例:物語作成[1]
あなたは小説を書きたいとしよう。
物語を一から作り出すには相当な妄想力や知識が必要になりそうだ。しかし、既存の物語である「浦島太郎」にアレンジを加える、というやり方なら、簡単に物語を作れそうだ。フレームワークは「浦島太郎」のストーリー展開であり、以下のような内容だ。
- 浦島太郎は子供がいじめている亀を助ける
- 後日、亀がお礼に竜宮城に連れて行ってもらい、もてなされる
- 竜宮城にて乙姫から「決して蓋を開けてはならない」玉手箱をもらう
- 浦島太郎は玉手箱を開けてしまい、白い煙に当てられ、老人になる
この物語をアレンジしよう。亀をドラゴンに書き換えてみたら、よりファンタジーな感じになりそうだ。しかし、
- 子供にいじめられる
- 浦島太郎に助けられる
- 浦島太郎を竜宮城へ招待する
みたいな役割はそのまま踏襲する訳だ。竜宮城ではなく、魔王城にするとかのアレンジも考えられる。
このように、既存のフレームワークを利用すれば、簡単に小説が書ける。しかし、踏襲することは便利である反面、自由度が制限されることもある。元の役割から逸脱するようなアレンジをしてしまうと、物語が成り立たなくなるだ。
「やっぱ、竜宮城に行くのは終盤にして、ドラゴンと浦島太郎が一緒に旅をする、という新展開を追加したい」、と思ったとする。
そのような元の物語と乖離した展開を追記する場合、フレームワークに頼ることはできず、自前で書かざるを得ない。
その新展開をまた別のフレームワーク「ヘンゼルとグレーテル」から踏襲する、みたいな、複数のフレームワークの合わせ技もあり得るし、込み入った詳細を引用する、というライブラリを用いたフレームワークもあり得るだろう。
プログラミングによるライブラリ・フレームワークの説明
以上が文章の比喩による説明だ(文章の比喩の説明はこちら)。ここからは、プログラミングの視点から、より厳密に説明する。
ライブラリは機能の再利用である
プログラムを一から全てを書き尽くすことは大変だ。しかし、悩む必要はない、ライブラリさえあればね!
数学的な操作やファイル操作など、多くの人が使う汎用的な機能を各々が一から実装するのは非生産的だ。そこで、特定の用途の機能をまとめたものを作成し、それをみんなで使い回すようにすれば便利だ。このような再利用するための機能群をライブラリという。
ライブラリの機能群をimportし、利用することで、自前で実装しなければならない機能を削減でき、プログラマはアプリケーションの開発に集中できるようになる。
/*
また、個人で開発する上でも、同じ用途の機能をまとめ、別のファイルに分離し、ライブラリ化しておくのも、プログラムを整理し、理解しやすくするためには有用だ。他人が自分のコードを利用したい、
*/
機能とは、関数という単位で提供される。つまり、引数を与えると出力が返ってくるものを集めたものがライブラリだ。
単に機能を寄せ集めても、動くプログラムを作ることはできない。
ライブラリを利用するということは、引数に何を与えるか、関数の呼び出し順序、条件分岐等の制御ロジックを全て自作しなければならない、ということだ。
ライブラリは文脈に依存しない粒度である関数を提供するだけだからだ。だからこそ、自由度はフレームワークよりも高い。
フレームワークは構造の再利用である
プログラムの規模が大きくなってくると、ちゃんと設計して秩序を持たせたり、うまく規模の大きなプ太刀打ちできない。しかし、悩む必要はない、フレームワークさえあればね!
文章構成のテンプレートのことをフレームワークと呼ぶ。これがあれば、テンプレートに沿って書き進めるだけでよく、文章の組み立てに悩むことはない。しかも、実績のあるフレームワークを使えば、より優れた文章を安心して構成できるし、優れた書き方の勉強にもなる。
以下でフレームワークを用いて物語を作る例を見る。
役割としての粒度の部品群であるフレームワークは、オブジェクト指向で書かれている。クラスごとの役割分担とそれらの協調の設計が既に決められおり、制御ロジックはポリモーフィズムで書かれている。
フレームワークにおいて、制御ロジックは既に完成しており、役割に応じて設計されたクラス間で協調して仕事を行う手順が決まっている。そのため、ユーザーは継承、オーバーライドによって独自の処理を組み込んだサブクラスを作成し、制御ロジックで用いられるクラスと差し替えることでカスタマイズしていく。
そこにフレームワークの自由さがある。しかし、役割は固定されている分、ライブラリより自由度は”劣る”。”劣る”と書くと、ライブラリの方が優れているように見えるかもしれないが、自由度が低いからこそ、ユーザーは楽ができるため、一概に優劣はない。
コメント