@nqounetです。
「イベント駆動プログラミング」という言葉を聞いたことはありますか? なんとなく難しそうに感じるかもしれませんが、実は私たちの身近にあるものです。スマートフォンのボタンを押したら画面が変わる、メールが届いたら通知が表示される──これらはすべてイベント駆動の考え方で動いています。
この記事では、Perl の Mojo::Log モジュールを使って、イベント駆動プログラミングの基礎を学びます。覚えるのは on と emit の 2 つだけです。この記事を読み終えるころには、自分でイベント駆動のコードが書けるようになっているはずです。
はじめに - イベント駆動プログラミングを学ぼう
「ボタンを押したら画面が変わる」も実はイベント駆動
日常生活でイベント駆動の例を考えてみましょう。
- スマートフォン: 画面をタップすると反応する
- エレベーター: ボタンを押すと来てくれる
- メールアプリ: 新着メールが届くと通知される
これらに共通するのは「何かが起きたら、それに応じて処理が実行される」という仕組みです。この「何かが起きた」ことを「イベント」と呼びます。
プログラミングでも同じ考え方が使えます。「ログが出力されたら、ファイルに保存する」「エラーが発生したら、管理者に通知する」──このように、イベントをきっかけに処理を実行するのがイベント駆動プログラミングです。
この記事のゴール:on と emit を使いこなせるようになる
イベント駆動プログラミングで覚えるべきことは、たった 2 つです。
- on: 「〇〇が起きたら、これをして」と登録する
- emit: 「〇〇が起きたよ!」と通知する
この 2 つを理解すれば、イベント駆動プログラミングの基礎はマスターしたも同然です。
対象読者:プログラミングの基礎を知っている初心者
この記事は、以下のような方を対象としています。
- Perl の基本的な文法(変数、サブルーチン、ハッシュなど)を理解している方
- イベント駆動プログラミングに興味があるが、どこから始めればよいかわからない方
- 実際に動くコードで学びたい方
30秒でわかるイベント駆動の考え方
同期処理との違いをたとえ話で理解
イベント駆動を理解するために、まずは「同期処理」との違いを見てみましょう。
同期処理:レシピ通りに順番に料理する
同期処理は、レシピ通りに 1 つずつ順番に作業を進めるようなものです。
| |
1 つの作業が終わるまで、次の作業には進めません。
イベント駆動:「注文が入ったら作り始める」レストラン
イベント駆動は、レストランの厨房のようなものです。
| |
それぞれのイベント(出来事)に対して、対応する処理が実行されます。複数のイベントを効率よく処理できるのが特徴です。
---
config:
look: handDrawn
theme: neutral
---
flowchart LR
subgraph 同期処理["🍳 同期処理(家庭料理)"]
direction TB
S1["1. 野菜を切る"] --> S2["2. 肉を焼く"]
S2 --> S3["3. 調味料を加える"]
S3 --> S4["4. 盛り付ける"]
end
subgraph イベント駆動["🍽️ イベント駆動(レストラン)"]
direction TB
E1["📋 注文が入った"]
E2["✅ 料理ができた"]
E3["🔔 お客さんが呼んでいる"]
E1 --> A1["👨🍳 料理を作り始める"]
E2 --> A2["🚶 配膳する"]
E3 --> A3["💬 対応する"]
end
同期処理では 1 つの作業が終わるまで次に進めませんが、イベント駆動では各イベントに対して独立した処理が実行されます。
on と emit - 覚えるのはこの2つだけ
イベント駆動プログラミングの核心は、この 2 つの操作です。
on = 「〇〇が起きたら、これをして」と登録
「メッセージが出力されたら、ファイルに保存して」のように、イベントに対する処理を事前に登録しておきます。
| |
emit = 「〇〇が起きたよ!」と通知
イベントが発生したことを知らせます。登録されている処理が実行されます。
| |
たったこれだけで、イベント駆動プログラミングの基本形が完成します。
---
config:
look: handDrawn
theme: neutral
---
flowchart LR
subgraph 登録フェーズ["📝 登録フェーズ"]
ON["on('message', 処理)"]
REG["処理を登録"]
ON --> REG
end
subgraph 実行フェーズ["⚡ 実行フェーズ"]
EMIT["emit('message', データ)"]
FIRE["イベント発火!"]
EXEC["登録した処理を実行"]
EMIT --> FIRE --> EXEC
end
REG -.->|"購読中"| FIRE
on で処理を登録しておき、emit でイベントが発火すると、登録した処理が自動的に実行されます。
Mojo::Log とは - イベント駆動学習に最適な教材
Mojolicious のシンプルなロガー
Mojo::Log は、Perl の人気 Web フレームワーク「Mojolicious」に含まれるロギングモジュールです。
なぜ Mojo::Log がイベント駆動の学習に最適なのでしょうか?
- シンプルな API: 覚えることが少ない
- イベント駆動の設計: 内部で on と emit を使用している
- すぐに動く: インストールが簡単
Mojo::Log は、ログを出力するたびに message イベントを発火します。このイベントを on で購読すれば、ログ出力をカスタマイズできます。
環境を準備する
まず、Mojolicious をインストールしましょう。cpanm(CPAN Minus)を使うと簡単です。
| |
インストールできたか確認してみましょう。
| |
「OK」と表示されればインストール成功です。
基礎を学ぶ:on でイベントを購読する
最小限のコードで始める
それでは、実際にコードを書いてみましょう。まずは 10 行で動く最小限のサンプルです。
| |
このコードを event_basic.pl として保存し、実行してみてください。
| |
出力結果:
| |
注意: 実際には Mojo::Log のデフォルトハンドラも動作するため、2 行出力されることがあります。自分のハンドラだけを動かしたい場合は、「パターン1:カスタムフォーマットで出力」で説明する unsubscribe を使います。
おめでとうございます! これがイベント駆動プログラミングの第一歩です。
message イベントを理解する
上のコードで何が起きているのか、順番に見ていきましょう。
$log->on(message => sub { ... })で、messageイベントに対する処理を登録$log->info('Hello, Event-Driven!')でログを出力- Mojo::Log の内部で
messageイベントが発火 - 登録しておいた処理(sub { … })が実行される
message イベントのコールバック(処理)には、3 つの引数が渡されます。
$log: Mojo::Log オブジェクト自身$level: ログレベル(debug, info, warn, error, fatal)@lines: ログメッセージ(複数行の場合もある)
---
config:
look: handDrawn
theme: neutral
---
sequenceDiagram
participant User as 👤 ユーザーコード
participant Log as 📋 Mojo::Log
participant Handler as ⚙️ on で登録した処理
Note over User,Handler: 1. 事前に処理を登録
User->>Log: $log->on(message => sub {...})
Log-->>Log: 処理を保存
Note over User,Handler: 2. ログ出力でイベント発火
User->>Log: $log->info('Hello!')
Log->>Log: emit('message', 'info', 'Hello!')
Log->>Handler: コールバック実行
Handler-->>Handler: [$level] @lines を処理
Handler-->>User: 処理完了
この図のように、$log->info() を呼ぶと内部で message イベントが発火し、on で登録した処理が自動的に実行されます。
複数の on を登録する
同じイベントに対して、複数の処理を登録できます。
| |
出力結果:
| |
1 つのイベントに対して、複数の処理が順番に実行されています。これがイベント駆動の強力な点です。処理を追加したいときは、既存のコードを変更せずに on で新しい処理を登録するだけでよいのです。
emit を理解する:イベントの発火
Mojo::Log では内部で使われている
emit は「イベントを発火させる」メソッドです。Mojo::Log では、ログを出力するメソッド(info、warn など)の内部で emit が呼ばれています。
概念的には、次のような処理が行われています。
| |
つまり、私たちが $log->info('Hello') と書くと、内部で emit が呼ばれ、on で登録した処理が実行されるというわけです。
自分で emit を使う場面
Mojo::Log を使うだけなら、emit を直接呼ぶ必要はありません。しかし、自分でイベント駆動の仕組みを作りたい場合は、emit を使うことになります。
例えば、カスタムイベントを定義する場合です。
| |
出力結果:
| |
このように、emit を使えば独自のイベントを作成できます。
実用例で身につける:3つのログ処理パターン
ここからは、実際に役立つ 3 つのパターンを紹介します。
パターン1:カスタムフォーマットで出力
標準のログ出力を、見やすいフォーマットにカスタマイズしてみましょう。
| |
出力例:
| |
ポイントは unsubscribe('message') です。これでデフォルトの出力処理を解除し、自分のカスタム処理だけを実行できます。
パターン2:複数の出力先に同時配信
1 つのログを、コンソールとファイルの両方に出力してみましょう。
| |
出力例:
| |
2 つの on を登録することで、1 つのログ出力が複数の場所に配信されています。
パターン3:エラー時だけ特別な処理
エラーレベル以上のログだけ、特別な処理をするパターンです。
| |
出力例:
| |
return unless で条件をチェックすることで、特定のログレベルだけに反応する処理を書けます。
もう一歩深く:Mojo::EventEmitter
Mojo::Log の親クラス
ここまで使ってきた on と emit は、実は Mojo::Log だけのものではありません。Mojo::Log は Mojo::EventEmitter というクラスを継承しており、イベント処理の機能はすべてこの親クラスから来ています。
| |
つまり、Mojo::EventEmitter を継承すれば、どんなクラスでもイベント駆動の仕組みを持たせられるのです。
その他のメソッド
Mojo::EventEmitter には、on と emit 以外にも便利なメソッドがあります。
once - 1回だけ実行
| |
unsubscribe - 購読を解除
| |
has_subscribers - 購読者の確認
| |
まとめ - イベント駆動の第一歩を踏み出した
この記事で学んだことをまとめます。
覚えるのは 2 つだけ
- on: イベントに対する処理を登録する
- emit: イベントを発火させる(通知する)
Mojo::Log で学んだこと
messageイベントはログ出力時に自動で発火する- 複数の
onを登録すれば、1 つのイベントで複数の処理が実行される unsubscribeでデフォルトの処理を解除できる
3 つの実用パターン
- カスタムフォーマット: ログの見た目を自由に変更
- 複数出力先: コンソールとファイルなど、複数の場所に同時出力
- 条件付き処理: エラー時だけ特別な処理を実行
次のステップ
イベント駆動プログラミングの基礎を身につけた今、次のステップとして以下を試してみてください。
- Mojo::EventEmitter を使って独自クラスを作る: 自分でイベントを定義してみる
- Mojo::IOLoop を学ぶ: 非同期 I/O とイベント駆動を組み合わせる
- Mojolicious アプリケーションを作る: Web アプリでイベント駆動を活用する
イベント駆動プログラミングは、最初は少し不思議に感じるかもしれません。しかし、一度理解すれば、コードの見通しがよくなり、機能の追加も簡単になります。ぜひ、実際にコードを書いて試してみてください。
関連記事
Perl の非同期処理やMojoliciousについてさらに学びたい方は、以下の記事も参考になります。


