強力の Callback プログラミング

こんにちは。開発担当のマットです。

最近、暇の時に、Unity というゲーム・エンジンで色々遊んでいます。
Unity で自由自在にゲームを作ることができ、武器を振り回して街を爆発させるゲームやゾンビー・ゲームやストラテジー・ゲームなど、色々作ったことはあります。

ところで、ゲームは割と複雑なものです。ビジュアルも、アニメーションも、効果音も色々ありまして、プログラムを正しく設計しないと、バグに繋がってしまいます。

従来の書き方

とても簡単な例でゲーム・プログラムの従来の書き方を紹介します。
例のゲームを、「マイ・ペット」と呼びましょう。このゲームにペットを育てることができます。
このゲームを作るには、データを持つクラスと、画面にペットを書き出すクラスは必要でしょう。

1. PetData クラス。
 このスクリプトの中に、ペットの色・サイズ・特徴など、全てのデータを記録しています。
2. DrawPet クラス
 このスクリプトは PetData のデータを使って、ペットを画面に描き出す(描画する)。

普通だったら、ゲームが開始されたら、DrawPet が PetData の中身を見て、ペットを画面に書き出します。

ところで、ゲームの中で「ピンク薬」という魔法なアイテムを使って、ペットの色が「ピンク」になった場合はどうしたらいいでしょう?DrawPet はペットを描き直さないといけませんが、データが変わったことにどうやって気づくでしょうか?

従来な方法は2つあります。

1. PetData の中のデータが変わる時、PetData は DrawPet のファンクションを呼び出す。(Function Call)
2. DrawPet は定期的に、PetData の中身が変わったかを確認する。(Polling)

ところで、どちらにも問題はあります。

Function Call の問題

データが変わった時に、DrawPet のファンクションを呼ぶことは大して悪くはないですが…
気をつけないと膨大してしまうプログラムの書き方です。

例えば、ゲームの中に「ペット詳細」の画面を追加しようと思った時、その「ペット詳細」画面を更新するファンクション・コールも必要になるでしょう。
それとも、色が変わった時、効果音を再生したい場合は?
アニメーションを実行したい場合は?

色のデータを変更するタイミングですべてのシステムにファンクション・コールをしないといけません。
そして、一つでも抜けたらバグ!

直感的ではありますが、問題ですね。

Polling の問題

確かに、DrawPet は PetData を確認したら、上記の問題は解決となります。

ただし、問題はタイミングとなります。DrawPet はいつ PetData を確認すればいいでしょうか?
一瞬で反応する仕組みを作りたければ、毎秒毎秒、何十回、何百回も繰り返しで PetData の中身を確認する必要が生まれてしまいます。

一つのペットなら問題ないかもしれませんが、ペットを増やそうと思ったら、その分の処理も増えます。
そして、DrawPetだけではなく、UI、効果音、アニメーションなど、それぞれのシステムは各々の PetData を連続的に確認する必要になりますね。

しかも、データはそれほど頻繁にかわらないので、無駄な処理ばっかり走っていますね。
ゲームがガタガタと遅くなってしまう恐れはあります。良くないですね。

Callback のチカラ

ここで紹介したいのは Callback の力です。

PetData は DrawPet などのファンクションを呼ぶことも良くないし、
DrawPet は PetData に毎回尋ねるのも、無駄な処理になりますので、
使えばいいのは Callback です。

PetData の方でファンクション参照先を登録できるようにすることです。
これを使って、DrawPet  はPetData に “RedrawPet” というファンクションを登録する。
DrawPet は “RedrawPet” のファンクションを実行するではなく、そのファンクションの参照先を PetData に登録するのだけです。

そして、PetData の方でデータが変わる時、PetData は登録された “RedrawPet” ファンクションを呼ぶことはできます。

このプログラミング方法を使うと、プログラマーはデータのクラスに、描画やUIや効果音やアニメーションのことを一切書くなくて大丈夫です。
それぞれのシステムはデータクラスにファンクションの参照先を登録をして、呼ばれるのを待つだけです。
「呼び返す」の感じですね。なので、Callback と言います。

ぜひ、次のプロジェクトで、Callbackプログラミングをお試しください。

Visual Studio Codeのユーザースニペットの使い方

Visual Studio Code(VS Code) を使う上で便利な機能の一つに「ユーザースニペット」というものがあります。
コードを書く上で同じ内容を書くことがよくあると思います。
よく使うコードは「ユーザースニペット」に登録しておくとコーディングが楽になります。

「ユーザースニペット」とは、コードをあらかじめスニペットに登録することでコードを簡単に呼び出せる機能です。

VS Codeの「基本設定」をクリックします。

ユーザースニペットを開きます。

特定の拡張子のみ適応させたい場合は、「css.json」などのファイル選択します。
「css、scss」両方に適応させたいなど、複数ファイルに適応させたいの場合は、「新しいグローバルスニペットファイル」を選択します。
(ここでは「新しいグローバルスニペットファイル」の方法を紹介しますが、特定の拡張子を選択した場合も同様です。)

ファイル名の入力を求められるので、わかりやすい名前を入力します。
今回は「global」と入力し「Enter」を押しました。

そうすると新しく「global.code-snippets」というファイルができるのでそこにスニペットを登録していきます。サンプルとして下記のような内容を登録します。

{
	"bg": { // スニペット名
		"scope": "css,scss", // 対象言語
		"prefix": "+bg", // スニペットを呼び出すための単語
		"body": [
			"background: url('') transparent top left / auto auto  no-repeat;", // 出力内容
		]
	},
}

保存後に、cssまたはscssファイルを開き、「+bg」と入力すると、候補が現れ、選択すると登録内容が出力されます。
複数登録する場合は下記のように続けます。

{
	"bg": {
		"scope": "css,scss",
		"prefix": "+bg",
		"body": [
			"background: url('') transparent top left / auto auto  no-repeat;",
		]
	},
	"@media": {
		"scope": "css,scss",
		"prefix": "+@media",
		"body": [
			"@media screen and (max-width: 900px){}",
		]
	},
}

下記のようにbodyの中に「$1」「$2」と書くと初期のカーソル位置を設定できます。
Tabキーを押すことで「$1」→「$2」の順に移動します。
${1:900}のように書くことであらかじめ、値を入力することもできます。

{
	"bg": {
		"scope": "css,scss",
		"prefix": "+bg",
		"body": [
			"background: url('$1') transparent top left / auto auto  no-repeat;",
		]
	},
	"@media": {
		"scope": "css,scss",
		"prefix": "+@media",
		"body": [
			"@media screen and (max-width: ${1:900}px){$2}",
		]
	},
}

今回はVS codeのスニペット機能について紹介しました。
コーディングの効率化の参考になれば幸いです!

[Solr]コレクションのコロケーション

はじめに

Solr にはコレクションのコロケーションの機能があります。
この機能はコレクションを跨いだJOINのために必要なものです。

コレクション作成時の指定

コレクション作成APIでwithCollectionパラメータを指定できます。
たとえば以下のリクエストでコレクションc1と同じ場所にコレクションc2を作成します。

/admin/collections?action=CREATE&name=c2&numShards=1&replicationFactor=2&withCollection=c1

ここでいう「同じ場所に」というのは、c1のレプリカが存在するいずれかのSolrノードと同じノード上に、という意味です。

既存のコレクションのコロケーション

コレクション変更APIもwithCollectionパラメータをサポートします。
たとえば以下のようなリクエストです。

/admin/collections?action=MODIFYCOLLECTION&collection=c3&withCollection=c1

ただし、この変更は自動的にはクラスタに反映されません。
多数のレプリカを直ちに移動させ始めるとシステムが不安定になる恐れがあるからです。
このリクエスト実行後に手動でどのようにクラスタを変更させるべきかを知るために、Solr Admin UI の Suggestion ページを利用できます。

コロケーション指定されたコレクションの削除

コロケーションのリンク付けをされたコレクションを削除する場合、先にコレクション変更APIでwithCollection属性を解除しておく必要があります。

/admin/collections?action=MODIFYCOLLECTION&collection=c2&withCollection=

注意事項

  • 1つのコレクションに対してwithCollectionでコロケーション指定できるコレクションは1つだけです。ただしwithCollectionによるリンクを繋げることで任意の数のコレクションをコロケーションさせることができます。
  • withCollection 指定するコレクションが持つシャードは1つだけで、かつその名前は shard1 でなければなりません。

Solrの記事リスト(〜2022年1月)

Prometheus連携

パッケージ管理

JSON Request API

Docket

日付表現

SolrCloudのリーダー選出

SolrCloud

インデックス作成

検索

Solrプロジェクト

その他

ワイヤレス充電器を買ってみた

こんにちは。

先日Amazonでセールをしていたので、Ankerのワイヤレス充電器を買ってみました🙌
以前から興味はあったものの、なかなか手を出せていなかったワイヤレス充電器。
値段はセールで1,200円!安いぞ!!
https://www.amazon.co.jp/dp/B07TJ1CRLF/

私が今使用しているiPhoneはiPhone 11Proなので、ワイヤレス充電に対応しています。
iPhoneだとiPhone 8以降が対応しているようですね。結構前の機種から使えることを今さら知りました。
https://support.apple.com/ja-jp/HT208078

使い方は、簡単 of 簡単😎
充電器本体にケーブルを挿して、iPhoneを本体の上に乗せるだけです。
充電器本体横に小さな青いランプが付けば充電中となります。すごい時代になったもんだ(遅い

あと、Ankerのワイヤレスイヤホンも持っていまして、そちらもワイヤレス充電対応だったので試してみました。
ほんとに置くだけで充電開始します。

買うのを躊躇っていた理由のひとつとして「充電スピードの遅さ」が気になっていました。
実際に充電した感想はというと…

「全然気にならんやん。。!」

バッテーリー残量20%からほぼ満タンになるまで約2時間半ぐらい。机の上にぽんと置いて仕事しているといつの間にか充電が完了してる感じです。
ただ説明にも記載のあるように、「Apple製スマートフォンに付属の充電器(5V/1A出力)には対応していない」ので、iPhoneシリーズで高速なワイヤレス充電を実現するためには、QC 2.0 / 3.0対応充電器を使用する必要があるようです。
↓多分このへんのやつ
https://www.amazon.co.jp/dp/B078RQ4FDC/

私の場合はすでに対応の充電器を持っていたので、特にそのあたりは気にすることなく使用できてるのだと思います。高速ワイヤレス充電バンザイ🙌

あ、ひとつデメリットがあるとしたら、充電器の表面がゴム製になっていてめちゃくちゃホコリが付きやすいのが嫌です(笑)充電中に滑らないようにするためだと思いますが、ホコリが嫌いな私にとってはめっちゃ気になるところでした😇気になったときに拭けば取れるのでいいですが、気になる人はご注意を。。(ホワイトの本体色を買うという手もあります)

それでは、みなさんも快適なワイヤレス生活を〜!