はじめに
以前、下記記事にイベントハンドラの命名案を記載しました。
RxはC#のevent構文の上位互換と言われています。
では、同じ解釈を適用する場合、Rxの IObservable
等の部品の命名パターンはどのように構築すれば良いのか考えてみます。
今回の内容は下記記事に記載したRxの解釈に基づいたものとなります。
Rx全般に適用可能だと思いますが、ここではUniRxのみを検討範囲とします。
クラス別命名案
以下の形で整理できるのではないかと考えました。
Subject
Subject
という型の名前自体は、恐らく「主題」という意味で使用しているのではないかと思います。
Observer
と繋がるように「観測テーマ」と意訳しても良いと思います。
イベントを発火させる役割で利用する場合は、 Subject
はイベントのフィールドの置き換えとなります。
private EventHandler eventHandler;
private readonly Subject<Unit> eventHandler = new Subject<Unit>();
このため、イベントハンドラと同じ命名方法が使えそうです。
public class Enemy
{
public event EventHandler OnDead;
}
public class Enemy
{
private readonly Subject<Unit> onDead = new Subject<Unit>();
}
Observable
event構文を置き換える場合、Observable
はイベントプロパティを置き換える部分となります。
private EventHandler eventHandler;
public event EventHandler EventHandler
{
add { this.eventHandler += value; }
// removeの方は検討範囲外なので省略
}
private readonly Subject<Unit> eventHandler = new Subject<Unit>();
public IObservable<Unit> EventHandler => this.eventHandler;
このため、こちらもイベントハンドラ名と同じ命名方法でいけそうです。
public class Enemy
{
public event EventHandler OnDead;
}
public class Enemy
{
private readonly Subject<Unit> onDead = new Subject<Unit>();
public IObservable<Unit> OnDead => this.onDead;
}
Observer
Observer
そのものについては、インスタンスに名前を付けて保持することがまずないので、検討対象外とします。
Observer
に登録する、イベント発火時に呼び出すメソッドの登録処理は以下のように置き換わります。
this.EventHandler += this.OnFired();
this.EventHandler.Subscribe(_ => this.OnFired());
このため、こちらはイベントハンドラのメソッド名と同じ考え方が使えそうです。
public class Enemy
{
public event EventHandler OnDead;
}
public class Player
{
public void StartBattle(Enemy enemy)
{
enemy.OnDead += this.OnEnemyDead;
}
}
public class Enemy
{
public IObservable<Unit> OnDead { get; }
}
public class Player
{
public void StartBattle(Enemy enemy)
{
enemy.OnDead.Subscribe(_ => this.OnEnemyDead());
}
}
例文で検証
上記の考え方で書いたプログラムが「英語の自然言語に近いプログラム」となり得るのかどうか、例文を作って検証してみます。
public class Enemy
{
// (1)
private readonly Subject<Unit> onDead = new();
public IObservable<Unit> OnDead => onDead;
public void Die()
{
// (2)
this.onDead.OnNext(Unit.Default);
}
}
public class Player
{
public void SratBattle(Enemy enemy)
{
// (3) (4)
enemy.OnDead.Subscribe(onNext: _ => this.OnEnemyDead());
}
private void OnEnemyDead()
{
// 敵死亡時の処理
}
}
(1)〜(4)それぞれのコードを英文になるように組み立て、翻訳サイトDeepLで翻訳して意味の通る日本語となるか検証します。
(1) Subject<Unit> onDead
まずは(1)の部分を英文にしてみます。
RxをPub/Subパターンで捉えてみるの解釈では、 Subject
のインスタンス生成は、 Subject
の内部 Observer
が Subject
利用クラスを観測開始することを意味するのでした。
この役割を示すような英文を考えると、以下のようになりました。
A subject of onDead is messages published on the enemy’s being dead.
→onDeadの観測テーマは、敵が死んだことで発行されるメッセージです。
翻訳サイトの翻訳結果から、 Subject
の部分のみ「観測テーマ」に変更しています。
onDead
から創造されたとは思えない程長くなってしまっていますが、以下の部分以外はボイラープレートです。
- onDead - フィールド名
- enemy - クラス名
- being dead - イベント発火タイミング
(2) onDead.OnNext()
続いて(2)の方です。
自然な文となるように、 onDead
(Subject
)をJohnとします。
John, do the process for on next message's having been published.
→ジョンさん、次のメッセージが公開された時の処理をしてください。
OnNext()
は、上記の文章の中で一番重要な部分のみを抜き出しているという考えです。
(3) enemy.OnDead.Subscribe()
enemy.OnDead
と Subscribe()
に分解して考えます。
enemy.OnDead
RxをPub/Subパターンで捉えてみるの解釈では Observable
はBrokerとなるので、それを説明する文を作りました。
An observable one called OnDead is a broker for messages published on the enemy’s being dead.
→OnDeadと呼ばれる観察可能なものは、敵が死んだ時に発行されるメッセージの仲介者です。
(1)と同じで、以下の部分以外はボイラープレートです。
- OnDead - プロパティ名
- enemy - インスタンス名
- being dead - イベント発火タイミング
Subscribe()
RxをPub/Subパターンで捉えてみるの解釈では、 Subscribe()
は Observable
に対して購読の手続きを行うように命令しているのでした。
これを説明するように英文を組み立てます。
自然な文となるように、今度はJaneに OnDead
(=Observable
)になってもらいます。
Jane, start procedure for subscribing to messages.
→ジェーンさん、メッセージを購読する手続きを開始します。
命令文として訳してほしいところですが、残念ながら平叙文になってしまいました。
とりあえずそのまま貼っておきます。
(4) Subscribe(onNext: _ => this.OnEnemyDead())
Subscribe()
の引数である onNext: _ => this.EnemyDead()
の部分はこのようになります。
Player
の代表はJackに務めてもらいます。
Jack, on next message's having been published, do the process on enemy's being dead.
→ジャック、次のメッセージが公開されたら、敵が死んだときの処理をしてください。
こちらも以下の部分以外はボイラープレートです。
- enemy - インスタンス名
- being dead - イベント発火タイミング
文を繋げると…
(1)〜(4)の英文とその訳を繋げました。
便宜上付与したJohn等の名前はメンバ名に戻し、理解しやすいように少し日本語訳に手を入れました。
A subject of onDead is messages published on the enemy’s being dead.
"onDead, do the process for on next message's having been published. "
An observable one called OnDead is a broker for messages published on the enemy’s being dead.
"OnDead, start procedure for subscribing to messages."
"Player, on next message's having been published, do the process on enemy's being dead."
onDeadの観測テーマは、敵が死ぬことで発行されるメッセージです。
「onDead、次のメッセージが公開された時の処理をしてください。」
OnDeadと呼ばれる観察可能なものは、敵が死んだ時に発行されるメッセージの仲介者です。
「OnDead、メッセージを購読する手続きを開始してください。」
「Player、次のメッセージが公開されたら、敵が死んだときの処理をしてください。」
これだけで仕様を説明する文章を作ることができました。
おわりに
補完しているしている語句が多いので、こじつけのように感じられるかもしれません。
しかし、補完している部分は、クラス名やインスタンス名、イベントの内容が変わってもそのまま使えます。
このため、場面によって変わる部分のみコードに記載し、共通部分は脳内でテンプレート化しておいて随時脳内補完するという整理も可能なのではないかと思います。
この脳内補完と翻訳がスムーズに行えるようになると、プログラムを理解する速度が上がりそうです。