イベント駆動型プログラミングについて:子供向けプログラミング言語Scratchのプログラムパラダイム

Scratchプログラミングパラダイムプログラミングの基本的な考え方の枠組み)は、イベント駆動型(イベントドリブンとも言います)です。
今回は、イベント駆動型プログラミングの概要を説明し、Scratchプログラミングパラダイムイベント駆動型であることに関連したプログラミング方法などをお話しします。

なお、プログラミングScratchの初心者の方には、6.まとめから先にご覧いただくことをお勧めします。

【目次】
1.プログラミングパラダイムとは
2.Scratchのプログラミングパラダイム―イベント駆動型
3.イベント駆動型プログラミングとは
4.Scratchのイベント駆動型プログラミングの特徴を生かしたプログラミング方法
5.Scratchのプログラミングパラダイム―オブジェクト指向型!?
6.まとめ

1.プログラミングパラダイムとは

プログラミングパラダイムは、プログラミング言語の開発時期や開発の目的などに伴って、そのときの流行の、または、まったく新しいコンセプトやスタイルなど、開発者によって設計され、実装された、そのプログラミング言語の基本的な枠組みです。

プログラミングパラダイムはプログラミング言語を分類するための枠組みではなく、プログラミングバラダイムとプログラミング言語は多対多に対応します。
例えば、プログラミング言語Aのある部分Xを見て、あるコンセプトXXが実現されているのでパラダイムXXXと言えるとき、同時に、このプログラミング言語Aの別の部分Yを見て、あるコンセプトYYが実現されているので、このプログラミング言語AはパラダイムYYYでもあることがあります。
そして、その逆に、プログラミングパラダイムXXXをもつプログラミング言語が、プログラミング言語Aとプログラミング言語Bとプログラミング言語Cの3つあるということもあります。

次に例としてあげるものは、プログラミングパラダイムの名称です。
構造化プログラミング
手続き型プログラミング
命令型プログラミング
関数型プログラミング
論理型プログラミング
オブジェクト指向プログラミング
イベント駆動型プログラミング
フロー駆動型プログラミング
・・・

よく知られているプログラミングパラダイムの名称だけでも、上記以外に世の中にはまだまだたくさんあります。
プログラミングパラダイムの集合は、ハードウェアの進化やソフトウェアへの時代の要求に伴って、日々変化しています。
長い期間主流のパラダイムとして君臨しているものや、変化して新しいパラダイムとして追加されたものがあると共に、まったく新しいパラダイムが随時追加されていっている状況です。
その上、あるパラダイムを語るためにその対比として既存のパラダイムを(または、その一部分を)新しい別の名称で呼ぶことなどもあり、プログラミングパラダイムの一覧を探し整理して提示しようと挑戦はしたものの、困難で断念してしまいました。

2.Scratchのプログラミングパラダイム―イベント駆動型

子供向けプログラミング言語 Scratchプログラミングパラダイムイベント駆動型です。
このことは、Scratchを開発したMIT(マサチューセッツ工科大学)のライフロングキンダーガーテン(生涯幼稚園)グループが管理運営するScratchコミュニティーサイト日本語版Scratch WikiScratchの特色欄で明示されています。

3.イベント駆動型プログラミングとは

イベント駆動型プログラミングイベントドリブンプログラミングとも言います)は、手続きがイベントによって駆動される仕組みを持つプログラミングパラダイムです。
ここでイベントとは、キー入力やマウス操作など、実行中にプログラムからの指示ではないユーザー自身の意図したタイミングでプログラムに対して行う操作や、システム内部の状況がある状態になったなど、実行中のプログラムに対する何らかの働きかけ(これをトリガーと言います)となる出来事のことです。

イベント駆動型プログラミングと対比して取り上げられるプログラミングパラダイムに、フロー駆動型プログラミングがあります。
フロー駆動型プログラミングは、プログラムに書かれた処理の流れに従って、すべての実行の流れが決まるプログラミングパラダイムで、多くの手続き型言語がこのプログラミングパラダイムをもっています。
フロー駆動型プログラミングが、プログラミングによってすべてのプログラム実行の流れを制御できるのに対して、イベント駆動型プログラミングでは、実行時のユーザーの操作など、プログラミング時に予期できないタイミングのイベントによって実行の流れが決まっていくので、プログラミングだけですべての実行の流れを制御することはできません。

イベント駆動型プログラミングでは、イベントによって起動される手続きのことを、イベントハンドラと言います。
イベントハンドラは、プログラム中のオブジェクトごとに作成します。
なお、ここで言う“オブジェクト”という用語は、オブジェクト指向型プログラミング言語などで定義されるオブジェクトとは異なり、“イベントを受理するもの“という(程度の)意味での”もの=オブジェクト“という意味で使用しています。

プログラム 実行中のキー入力やマウス操作などユーザーの操作により発生するイベントについて、1つのイベントイベントハンドラの処理が終わる前にユーザーが次のイベントを発生させてしまうことがあります。
ユーザーが次々にイベントを発生させた場合、それらのイベントは、前のイベントハンドラが終わるまで、イベントキューと呼ばれる待ち行列に保存されます。

ユーザーが次々にイベントを発生させた場合でも、プログラミング言語が並行処理の機能を持つ場合は、対応するイベントハンドラそれぞれが並行して実行されます。
ただし、並行処理の機能を持つ場合でも、同じイベントが前のイベントハンドラが終わる前に再度発生したときの動きなどは、問題なく動くように考慮してプログラミングする必要があります。

なお、プログラミング言語が同時に複数の手続きを並行処理する仕組みをマルチスレッドと言い、これに対してプログラミング言語が同時に1つの手続きしか処理しない仕組みをシングルスレッドと言います。
Scratchはマルチスレッドのイベント駆動型プログラミング言語なので、並行処理を実現できるプログラミング言語です。

イベント駆動型プログラミングでは、イベントを発行する事象が、先に説明した実行時のユーザーの操作以外にもあり、例えば、各手続きの中でプログラミング言語の命令の1つからイベントを発行して、イベントハンドラを起動することができるものがあります。
この、手続きから発行されるイベントメッセージと言い、その発行をメッセージ送信とも言います。
ちなみに、メッセージ送信された結果起動した手続きは、“メッセージを受信した”といいます。

4.Scratchのイベント駆動型プログラミングの特徴を生かしたプログラミング方法

<Scratchのオブジェクトは、ステージとスプライト>
Scratchでは、手続きはスクリプトか自分で定義するブロックと呼ばれるものとしてプログラミングします。
Scratchスクリプトも自分で定義するブロックも、ステージスプライトの1つに紐づけして作成します。
すなわち、Scratchイベント駆動型プログラミングとしてのオブジェクトは、ステージスプライトということになります。

Scratchエディターで、スプライトリストステージスプライトサムネイルをクリックすると、画面右半分がそのオブジェクトのスクリプトエリアになり、そのオブジェクトに紐づけされたスクリプトと自分で定義するブロックを作っていくことができます。

スクリプトエリアの例:猫のスプライトのスクリプトエリア
スクリプトエリアの例:猫のスプライトのスクリプトエリア

なお、Scratchで用意されているブロック(手続きを形成する1つ1つの命令)の操作対象は、紐づけされているオブジェクトです。
スクリプトや自分で定義するブロックでは、そのオブジェクトに対する操作の記述しかできず、他のオブジェクトに対する直接的な操作をするブロックは用意されていません。
他のオブジェクトに対する操作を行いたいときは、メッセージ送信を使用します(この記事の後方でもう少し具体的に説明します)。

<Scratchのイベントは、[イベント]グループの[・・・とき]ブロックで確認できる>
Scratchで使用できるイベントは、Scratchブロックパレットの[イベント]グループのブロックを見るとわかります(このあと、1つ1つ確認します)。
Scratchで作ることのできる手続きはスクリプトと自分で定義するブロックの2種類あり、イベントハンドラにできる手続きはスクリプトです。
スクリプトは、ご存知のように、ブロック(命令)の並びで構成する手続きです。
スクリプトイベントハンドラにするには、[イベント]グループの[・・・とき]ブロックをそのスクリプトの先頭に付けるだけです。
なお、[イベント]グループの[・・・とき]ブロックは、その形からハットブロック(帽子型のブロックという意味)と呼ばれ、スクリプトの先頭にしか付けることのできない形のブロックになっています

[イベント]グループの[・・・とき]ブロック(ハットブロック)
[イベント]グループの[・・・とき]ブロック(ハットブロック)

では、Scratchブロックパレットの[イベント]グループのブロックを1つ1つ確認します。

・[イベント]グループの[緑の旗がクリックされたとき]ブロック

[緑の旗がクリックされたとき]ブロック
[緑の旗がクリックされたとき]ブロック

Scratchを使う人が必ず覚えておかなければならない決まりの1つが、エディターステージ右上にある緑の旗のクリックによって、プログラムプログラムのことをScratchではプロジェクトと言います。以降、この記事ではプロジェクトという用語を使います)の実行が開始されること。
エディター以外でも、Scratchプロジェクトステージのど真ん中に大きく緑の旗の図が表示される場合があり、そのときはそこをクリックすれば、そのプロジェクト実行が開始されます。
そして、この開始の合図である緑の旗のクリックもイベントの1つになっていて、プロジェクト実行開始直後、先頭に[緑の旗がクリックされたとき]ブロックが付いたスクリプト実行されます。

Scratchマルチスレッドに対応しているため、複数のスクリプトの先頭に[緑の旗がクリックされたとき]ブロックが付いていても問題ありません。
もちろん、先頭に[緑の旗がクリックされたとき]ブロックが付いたスクリプトが1つもないプロジェクトであっても構いません。

・[イベント]グループの[■キーが押されたとき]ブロック

[■キーが押されたとき]ブロック
[■キーが押されたとき]ブロック

[■]の部分は、その横の下向き▼をクリックすると一覧が表示され、選択して設定します。
選択できるのは、次のキーの中の1つです:
〇スペースキー
〇上下左右の矢印キーのどれか1つ
〇任意のキー
〇アルファベットのどれか1つ
〇数字のどれか1つ

このハットブロックを付けたスクリプトは、そのキーが押されたことをトリガーにして起動されます。
例えば、aキーとスペースキーと上向き矢印キーのどれを押しても同じ手続きを行わせたい場合、ハットブロックだけ違い(先の3つのキーそれぞれが押されたときのハットブロックで始まる)それ以下のブロックの並びが同じスクリプトを(要はスクリプトを3つ)用意する必要があります(あるいは、ハットブロック以外の共通する部分を自分で定義するブロックで1つ用意し、それを各ハットブロックの下で呼び出す記述をします)。

下の図は、aキーとスペースキーと上向き矢印キーのどれを押しても、猫が「ニャー」と2秒言うプロジェクトです。

猫が「ニャー」と2秒言うプロジェクト
猫が「ニャー」と2秒言うプロジェクト

・[イベント]グループの[このスプライトがクリックされたとき]ブロック

[このスプライトがクリックされたとき]ブロック
[このスプライトがクリックされたとき]ブロック

スプライトがクリックされたときに実行したいスクリプトの先頭に付けるハットブロックが、[イベント]グループの[このスプライトがクリックされたとき]ブロックです。

・[イベント]グループの[背景が■になったとき]ブロック

[背景が■になったとき]ブロック
[背景が■になったとき]ブロック

Scratchではステージ背景を複数用意することができ、その背景が[■]に切り替わったことをトリガーとするイベントハンドラにつけるハットブロックです。
[■]の部分は、その横の下向き▼をクリックすると、選択可能なすべての背景の一覧が表示されるので、選択して設定します。

通常、新規作成でScratch エディターを起動した直後のステージ背景は、デフォルトで真っ白なもの1つが用意されているだけです。
このハットブロックを使用するときは、少なくとも、もう1つ別の背景を自分で用意しているときになります。

・[イベント]グループの[■が>〇のとき]ブロック

[■>〇のとき]ブロック
[■>〇のとき]ブロック

デフォルトでは、[音量>10のとき]をトリガーとするイベントハンドラハットブロックで、デフォルトで[音量]となっている[■]の部分は下向き▼で他に[タイマー]と[ビデオモーション]からの3択、デフォルトで[10]となっている[〇]部分は数値を入力して設定します。

・[イベント]グループの[■を受け取ったとき]、[■を送る]、[■を送って待つ]ブロック

[■を送る]ブロック
[■を送る]ブロック
[■を送る]ブロック
[■を送る]ブロック
[■を送って待つ]ブロック
[■を送って待つ]ブロック

[■を受け取ったとき]ブロックメッセージ受信のハットブロック、[■を送る]ブロックと[■を送って待つ]ブロックメッセージ送信ブロックです。

メッセージを使う典型的なプログラミングの例で、これらのブロックの使い方を説明します。
その例とは、2つのスプライトがあり、1つをボタンのスプライトとし、ボタンのスプライトがクリックされると、もう1つのスプライトが変化するプログラミングの例です。
例えば、もう1つを猫のスプライトとして、ボタンのスプライトがクリックされたら、猫のスプライトの色が変わるプロジェクトを作りたいと思います。

猫のスプライトの色を変えるプロジェクト
猫のスプライトの色を変えるプロジェクト

もうご理解いただいている通り、Scratchで作るスクリプトでは、対応するオブジェクトだけが直接操作できることから、猫のスプライトの色を変える手続きは、猫のスプライトスクリプトで記述する必要があります。
一方、ボタンのスプライトがクリックされたときの手続きは、ボタンのスプライトの[このスプライトがクリックされたとき]ブロックが先頭にあるイベントハンドラスクリプトでのみ、プログラミングできます。

イベント駆動型プログラミングでは、ユーザーが実行時に操作したときにイベントが発生するのと同様、プログラムの中で意図的にメッセージ送信されたときにもイベントが発生すると、先に説明しました。
メッセージ送信で発生するイベントも、ユーザーが実行時に操作したときに発生するイベント同様、その瞬間にすべてのオブジェクトで認識できます。
このことから、あるオブジェクトに対してユーザーが実行時にした操作によって、別のオブジェクトのスクリプトを起動したいときは、メッセージ送信を利用します。

今回の例では、ユーザーが実行時にボタンのスプライトに対して行ったクリック操作によって、猫のスプライトスクリプトを起動するために、ボタンのスプライトの[このスプライトがクリックされたとき]ブロックが先頭にあるイベントハンドラスクリプトの中でメッセージ送信をします。

メッセージ送信の方法は、具体的には、[■]に送信するメッセージとして適当な名称を付けて、[■を送る]ブロックか[■を送って待つ]ブロックを記述するだけです。

[■を送る]ブロックか[■を送って待つ]ブロックのどちらかのメッセージ送信ブロック実行されると、プロジェクト全体にメッセージ送信され、このオブジェクトに限らず別のオブジェクトであっても、とにかく、このメッセージイベントとして受け取る[■を受け取ったとき]ブロックハットブロックを先頭に持つイベントハンドラがすべて(複数存在する場合もあるので)実行されます。

例えば、今回の例では、ボタンのスプライトに、[このスプライトがクリックされたとき]ブロックハットブロックとするスクリプトを作り、そのスクリプトの中の処理の1つとしてメッセージ送信ブロックメッセージの名称[■]を[ボタンクリック]にした[ボタンクリックを送る]ブロックを記述します。

ボタンのスプライトのスクリプト([ボタンクリック]のメッセージ送信)
ボタンのスプライトのスクリプト([ボタンクリック]のメッセージ送信)

さらに、猫のスプライトスクリプトに、[ボタンクリックを受け取ったとき]ブロックハットブロックとするスクリプトを作り、そのスクリプトで猫のスプライトの色を変える手続きを記述します。

猫のスプライトのスクリプト(色を変える手続き)
猫のスプライトのスクリプト(色を変える手続き)

なお、[■を送る]ブロックと[■を送って待つ]ブロックの使い分けは、[■を送る]ブロックではメッセージ送信後、すぐにこちら側の次のブロックの処理の実行が行われ、[■を送って待つ]ブロックではメッセージ送信後、送信先のイベントハンドラのすべての手続きが終わるのを待ち、終わってから、こちら側のその次のブロックの処理の実行を行います。

5.Scratchのプログラミングパラダイム―オブジェクト指向型!?

ScratchコミュニティーサイトScratch Wikiに、“Whether or not Scratch is Object-oriented is disputable.”(Scratchがオブジェクト指向かどうかは議論の余地がある)と記述されています。

日本語版Scratch WikiScratch特色欄 にも、「(Scratchは)根源的にイベントドリブン型である」と書かれている一方、「(Scratchが)オブジェクト指向型プログラミングであるかどうかはコミュニティ内での議論がわかれている」との一文があります。

6.まとめ

Scratchプログラミングパラダイムは、イベント駆動型プログラミングです。

Scratchプログラミングするとき、初期設定など、はじめに行いたい手続きがある場合は、先頭に[緑の旗がクリックされたとき]ブロックを付けたスクリプトとして、任意のオブジェクト(スプライトステージ)のスクリプトエリアに作成します。
なお、プロジェクト内に、1つも先頭に[緑の旗がクリックされたとき]ブロックを付けたスクリプトが存在しないプロジェクトであっても構いません。

そもそも、Scratchには各オブジェクトのスクリプトエリア以外にスクリプトを作るための場所が存在しないため、どのオブジェクトとも関係ないような手続きであっても、スクリプトはどれか1つのオブジェクトと紐づけられる必要があります。
どのオブジェクトとも関係ないような手続き(計算をするだけの手続きや、リストの並べ替えをするだけの手続きなど)をスクリプトとして作成するときは、新規作成の際にデフォルトで用意されている猫のスプライトスクリプトを作ったりします。

コメントを残す