# OTPの全体像

> Source: https://www.ymotongpoo.com/works/adopting-erlang-ja/development/otp_high_level/


Erlang/OTPは、同じく仮想マシンを使う環境も含め、世の中の大半のプログラミング環境とは一線を画しています。
アプリケーションをどう構造化すべきか、どの程度の分離を保つべきか、そしてErlangのVMにできることとソフトウェア側にできることをどう切り分けるかについて、Erlangは明確な考え方を持っています。
Erlangは単なるプログラミング言語ではなく、システムを構築するためのフレームワークそのものです。
この核となる原則を理解しておくことが、後になってすべてを書き直す羽目にならずに素早く始めるための鍵となります。
そうすることで、すべてのアプリケーションがうまく組み合わさり、アップデートを稼働中に行え、コードに計装を入れて観測しやすくできるのです。

本章では、Erlangの仮想マシンと、OTPの中核となる概念を大づかみに見ていきます。

## Erlangランタイムシステム

すべての土台となっているのは、BEAMと呼ばれるErlangの仮想マシンそのものです。
BEAMは技術的にはErlang仮想マシンの一実装にすぎず、他の実装もありえます。
たとえばErllvmはLLVM上に構築された実装であり(動かすために独自のパッチを当てています)、90年代にはJAMと呼ばれる古い実装もありました。
Erlang VMはCで実装されており、プロセスを動かすスケジューラ、ガベージコレクション、メモリアロケータ、イベント用のタイマーホイール、OSの機能を抽象化して統一的なインターフェースを提供する数々の仕組み(時刻管理やファイル操作のドライバなど)、Erlang自身で書くより高速に動く組み込み関数(BIF)、他の言語でネイティブに実装された関数を呼び出すためのインターフェース(NIF)とその専用スケジューラといった、凝った仕組みを大量に抱えています。
実際にはもっとたくさんの要素がありますが、BSDやLinuxのカーネルと同じようなもの、つまりその上により洗練されたものを組み立てるために必要な低レイヤーの仕組みだと考えれば十分です。

仮想マシンだけがあってもErlangのコードは動きません。
標準ライブラリもなければ、コードをロードするためのライブラリすらないからです。
そこから動き出すまでには込み入ったブートストラップ処理がありますが、その中身まで理解する必要はありません。
仮想マシンにはあらかじめ限られた数のErlangモジュールが同梱されており、それらを使ってネットワークやファイル操作の仕組みを立ち上げ、さらにモジュールを読み込んで実行できるようになる、とだけ知っておけば十分です。
もっと詳しく知りたい場合は、[The BEAM Book](https://happi.github.io/theBeamBook/) や [BEAM Wisdoms](http://beam-wisdoms.clau.se/) を参照してください。

仮想マシンと、あらかじめ読み込まれた仕組み、そしてコードロードを可能にする細々としたユーティリティ一式を合わせたものが、いわゆる**Erlangランタイムシステム**(ERTS)です。
ランタイムシステムは起動時に、何を起動すべきかを指定した**ブートスクリプト**という仕組み(人が手で書くものではありません)の指示に従います。

Erlangには、シェルを起動して自分のアプリケーションを書き始めるために必要最小限のコードだけを読み込むブートスクリプトが標準で用意されています。
ここまで済めば、仮想マシンだけでなくErlangそのものについて考え始められます。

## Erlang/OTP

ここまで説明してきたのは、オペレーティングシステムでいうカーネルに相当する部分です。
次に必要なのは、ユーザースペースのコンポーネントのための土台であり、Erlangにおいてこれを担っているのがOTPです。
OTPは、仮想マシン上で動く「コンポーネント」をどう構造化すべきかを定めています。
Erlangという言語には「プロセスとメッセージ」だけでは語り尽くせない部分があり、コードを構造化するための明確に定義された一つのやり方が存在するのです。

{{< message >}}
OTPは**Open Telecom Platform**の略ですが、これはErlangがEricsson社内にあった昔、オープンソース化するために付けられた、文字どおり意味のない名前です。
{{< /message >}}

Erlang/OTPのシステムは、**OTPアプリケーション**と呼ばれるコンポーネントを単位として構造化されています。
インストールしたErlangのバージョンやそれで作ったシステムには、いずれもいくつかのOTPアプリケーションが同梱されています。
OTPアプリケーションには大きく分けて2種類あります。単なるモジュールの集まりである**ライブラリアプリケーション**と、モジュールの集まりに加えてsupervisorツリーの下にステートフルなプロセス構造を持つ**実行可能アプリケーション**です。
本書全体を通じて、OTPアプリケーションについては次の用語を使うことにします。

- **ライブラリアプリケーション**: ステートレスなモジュールの集まり
- **実行可能アプリケーション**: ステートフルなsupervisorツリー構造を起動し、その中でプロセスを実行するOTPアプリケーション
- **OTPアプリケーション**: ライブラリアプリケーションと実行可能アプリケーションのどちらも指す総称

誰もが標準で組み込む2つのOTPアプリケーションが `stdlib` と `kernel` です。
`stdlib` は `list` や `maps` といった中核の標準ライブラリモジュールを含むライブラリアプリケーションであり、`kernel` はOTPアプリケーションに依存して動くErlangシステムの中核構造を立ち上げる実行可能アプリケーションです。

ノードが起動すると、必要なOTPアプリケーションすべてのモジュールがメモリ上にロードされます。
続いて `kernel` が起動し、以後のシステムのライフサイクルを管理します。
他のすべてのOTPアプリケーションとその設定は `kernel` を通じて扱われ、分散やホットコードアップデートといった独自機能もここが担います。
先ほどのオペレーティングシステムの比喩に戻るなら、`kernel` というOTPアプリケーションは、Linuxカーネルにとっての `systemd`(`systemd` が好きでない場合や BSD を使っている場合は `init`)のようなものだと考えられます。Windowsユーザーであれば、他のサービスを動かすサービスだとイメージするとよいでしょう。

実際のところ、基本的なErlangシェルを動かすのに必要なアプリケーションは `kernel` と `stdlib` の2つだけです。
`erl` と入力する(Windowsでは `werl` を起動する)と、VMが `kernel` とともに立ち上がり、`stdlib` があらかじめ読み込まれます。
それ以外はすべて任意で、後から読み込むこともできます。

標準のErlangディストリビューションには、次のようなアプリケーションが含まれています。

- `kernel`
- `stdlib`
- `crypto`(暗号プリミティブ)
- `ssl`(TLS終端ライブラリ)
- `inets`(FTPやHTTPクライアントなどのネットワークサービス)
- `ct`(Common Testフレームワーク)
- `wx`(グラフィックツールキット)
- `observer`(`wx` 上に構築された、Erlangノードを管理するコントロールパネル)
- `compiler`(自分のプロジェクトをビルドするためのErlangコンパイラ)
- ほか多数

これらすべてをまとめたものが、Erlangの**リリース**と呼ばれるものです。
リリースとはOTPアプリケーションの集合であり、仮想マシンそのものの完全なコピーが同梱されることもあります。
実際、Erlangをダウンロードしてインストールすると、手に入るのは `Erlang/OTP-21.3.4` のような名前を持つ一つのリリースにほかなりません。
標準ディストリビューションのOTPアプリケーションの一部を取り出し、自分のアプリケーションと組み合わせて、独自のリリースを自由に作ることもできます。

たとえば `ssh` と `ssl`(この2つはさらに `public_key`、`crypto`、`stdlib`、`kernel` に依存します)に依存する `proxy` というアプリケーションを書くとしたら、次のすべてのコンポーネントを含むリリースを作ることになります。

- ERTS
- kernel
- stdlib
- crypto
- public_key
- ssl
- ssh
- proxy

これを図にしたものが下の図です。

![proxyリリースを組み立てる様子を図示したもの](proxy_release_draft.png)

要するに、Erlangシステムを作るということは、VMと標準ディストリビューションが提供するいくつかのアプリケーション、そして自分のアプリケーションやライブラリを、一つに束ね直すことなのです。

## Erlang/OTPとともに生きる

Rebar3のようなコミュニティ製の標準的なツールは、書いて公開するものはOTPアプリケーションであるという前提に立って作られており、それを扱うために必要な機能をすべて備えています。
これは、どこかのファイルに `main()` という名前の関数さえあればよいという多くのプログラミング言語とは大きく異なる考え方です。
この言語がしばしば単に「Erlang」ではなく `Erlang/OTP` と呼ばれるのはこのためです。
単なるプログラミング言語ではなく、あらゆる作業に基本的な構造を要求する汎用的な開発フレームワークだからです。

組み込みソフトウェアを書いていようと、ブロックチェーンシステムやデータベースを書いていようと、誰もがこの流儀に従います。
OTPに従うか、さもなくば何もない、というくらいの徹底ぶりです。
他の言語の多くは、始めるときには特に何も要求せず、後になって(パッケージマネージャと連携するときなど)要件が追加されていくものですが、Erlangとそのコミュニティ全体は、最初からOTPアプリケーションとして書くことを求め、あとの面倒はツール群が見てくれます。

したがって、Erlangを素早く始めるための鍵は、しばしば上級者向けの内容として扱われがちなこのフレームワークを知ることにあります。
本書ではあえて順序を逆にし、まず完全に動くリリースから出発して、そこから構造を掘り下げていきます。
続く各章では、この要件の中でどう作業していくかを理解することに焦点を当てます。

