今週の知見 (2022/02/13~2022/02/18)
ノートにメモった知見をブログに残そうと思います。
…後で見返しにくそうですが笑
- メッセージを送り合う形にするとロックしなくても非同期で動かせる
- 同期処理のコンポーネント接続はインターフェースで考える
- IN→OUTを考える
- VSCodeはVimのプラグインがある
- C# のテストフレームワークは主なものは3つある
- 軽い=実行数が少ない
- Unityでテストするときはアセンブリをつかう
- Assertはビルドすると消える
- でかいファイルはそもそもGit管理にしない
- ユニットテストしにくいコードはAdapterパターンと依存注入でテストしやすくなる
- マルチコアとコールスタックは相性が悪い
- テストは名前で分かるようにする。
- ちゃんと分けて作らないと、あとでマージするときに困る。
メッセージを送り合う形にするとロックしなくても非同期で動かせる
達人プログラマーに書いてあったことから。
もちろん、それだけでなく「メッセージを受け取るメッセージボックス」
「メッセージボックスが溜まったら順番に実行する」
「状態はプライベートに、返り値もなし」
「データを返したいときはそれ用のメッセージを送りつける」
と言った仕組みも必要みたいです。
C#だと Akka.NETというライブラリ?で実現できますが、
いかんせん日本語の情報がすくない… 人気はあまりない模様。
同期処理のコンポーネント接続はインターフェースで考える
データという形でやり取りするにはどうしたらいいのかなぁと考えていました。
インターフェースにすると受け取り手、送り手の情報の形が保証されるのでよさげ。
このあと非同期に組みたい場合でも、この考えは適用できそう。
IN→OUTを考える
shellスクリプトなんかはこの典型ですが
なんの情報が入ってなんの情報が出てくるかを考えると
関数の組み合わせで柔軟なプログラムを組むことができます。
関数型プログラミングはその形が顕著なのかと。
データの型だけ保証できれば、どんなプログラムでも繋げられるって思うとすごいですね。
オブジェクト指向でもここを意識することでStaticなクラスや関数が組みやすくなるんじゃないかと見込んでます。
VSCodeはVimのプラグインがある
慣れてくると、キーだけでコピーや削除、移動が出来るようになって、コーディングが捗りそうです。
が、今までVSCodeで作業していたので、全部取り替えはちょっと微妙なので調べたらプラグインでありました。
今は、VSCode上でVimのコマンドを駆使しながらコーディングをしています。
C# のテストフレームワークは主なものは3つある
MSUnit xUnit NUnit の3つですね。
UnityがテストランナーでNUnit を使っているので、
とりあえず私はNUnitを使おうかと。
軽い=実行数が少ない
これは、パズルゲームを考えていたときに思ったこと。
描画などでまるごと描き直すのは、処理を組むのはカンタンですが、
変える必要のない部分も変えているのも事実。
それに、リソースが余っているときは気になりませんが、
リソース不足やレスポンスの遅延で後々痛い目を見そうです。
いわゆる軽い処理というのは、必要最低限の処理しかしていないということなのでしょう。
更新があった部分だけ描き直す。
繰り返しでやっている部分を繰り返さなくてすまないか?
そういうところを考えていると軽い処理になりそうです。
Unityでテストするときはアセンブリをつかう
これはテスト環境を構築しているときに詰まったことです。
Unityはテストランナーをつかう場合、Testsというアセンブリをつくることになるのですが、
これは本体のコードの参照を持っていないため、本体のコードを参照に入れる必要があります。
んで、本体にもアセンブリを入れるのですが、人によってはエラーが続出すると思います。
なんでかというと、もともとスクリプトは見えない部分で
全部入りのアセンブリに入れられていたからです。
アセンブリをつくると、ここから分離させるので、全部入りでは参照できていたのが
参照できなくなるんだそうです。
全部入りの方で作業するのは楽ちんですが、これも後々ビルドしたときに肥大の原因になったりするので
分割して、必要な分だけ参照する形のほうが、スッキリしたビルドになるんじゃないかと思います。
Assertはビルドすると消える
Assertとはコードの正誤を確認するためのメソッドで、
例えば 0以下は入っちゃいけないのに -3が入っていた とかを確認するときに使えます。
ふつうはテストなんかで使われるので、本番では要らぬ、ビルドに含めないほうが軽くなる
…という考えなのでしょう。
が、このとき考えていたのは「プログラムの一機能として事前条件を満たしていない入力は認めない」
という作りにしたかったので、Assertが使えないのがちょっとショックでした。
仕方がなかったのでIF文で判定していたのですが、もっと良いやり方ないかなぁと思う今日この頃です。
でかいファイルはそもそもGit管理にしない
MagicOnionのセットアップをしていたときに起こったこと。
gRPCの公式ライブラリには100MB以上のファイルがあるため、
今回会社の上司にこの部分をどうすればいいかと確認したところ、
Git管理にしないというアドバイスをもらいました。
今回は公式からダウンロードできるファイルなので、わざわざこちらで管理する必要もありませんし
これは盲点だったと思いました。どうすれば入れるかしか考えていなかったので…
ユニットテストしにくいコードはAdapterパターンと依存注入でテストしやすくなる
詳しくはこの記事で
いじれない部分を置き換えることでテストしやすくなるということですね。
インターフェースのテストしたいけど、クライアントもサーバーもないしどうしよう…
となったときに調べたものです。
ちなみに、こちらについてはテストコードにダミーをつくることで実現しました。
マルチコアとコールスタックは相性が悪い
これはAkka.NETでアクターモデルを調べていたときにかいてあったことです。
コールスタックはどの関数がどれを読んだかを積んだリストのようなもので、デバッグのときに重宝するやつです。
マルチコアの場合、コアをまたぐスタックを負えないため、デバッグが難しくなります。
そのため、マルチコアでテスト等をしたい場合、コールスタックとは別のデバッグ処理が必要になると思います。
因みにAkka.NETではアクターが数珠つなぎで親のアクターの参照を持っており、
子のアクターがエラーが起きたら、親のアクターにエラーメッセージを伝搬させる仕組みになっているらしいです。
テストは名前で分かるようにする。
わたしなんかは Test+関数名 で名前をつけてしまうことが多いのですが、
何を確認するかが分かると、あとで実行したときにひと目で分かるようになっていいですね。
ほかにも有用な単体テストのベストプラクティスが載っているので、
.NETを使っていなくても勉強になると思います。
ちゃんと分けて作らないと、あとでマージするときに困る。
これは設計粒度とかの話になるかなと思います。
今回MagicOnionを使ったミニアプリをつくっているのですが、
MagicOnionではクライアント、サーバー、共用と大きく分けて実装していきます。
んで、実装していると「クライアントの処理をつくったけど、サーバーや共用ができていないので確認ができない」
「参照先が無くてエラーになる」と言った自体にぶつかることになりました。
今回実装自体は一人で行っているので、つくる順番を変えたり、参照先をつくったりして対応はできたのですが、
これを複数人で行うとしたらまずい方法だなというのは今の自分でも分かります。
要は相手先に依存してしまう形になっているので
ちゃんと独立して機能がつくれるようにしないとまずいなぁと反省しました。
今週はこんなところですね。
それではまたあいましょう!