20200426

食事

朝なし昼スパゲッティ夜カレー

住居とは

外出をしない土日だった。自宅にこもっていても生存できる、それはつまり、この狭い部屋に人間が生きるために必要な機能を密集させ、さらにそのために必要なリソースを逐一引いてきているということだ。想像するだけですごい手間だ。共通化が禁じられたプログラミングのようなものだ。

そこまでやらなくてもいいんじゃないかと思う。たとえば風呂とトイレを集約するだけで配管と掃除の手間は激減するのではないか。その代わり排泄と入浴のタイミングが完全に自由ではなくなるが、それほど重大なこととは思わない。家賃が安くなるのならばそうしてほしい。

ScalaでDBを使いたい

温度管理サーバーは現状データをCSVに保存しているが、ダサいのと勉強のためにちゃんとDBを使いたい。ということでslickを導入しようとしている。今はチュートリアルをやっている。

たぶんapplication.confのurlを適切に設定すれば自分が用意したDBに接続できるはずで、docker-composeとかで用意すればいいかな。

同時に開発環境も整備した。これまではdockerコンテナの中で動かしていたが、それをやめてマシン上にJavaとsbtを入れた。このとき両者のバージョンを正確にこれまでのものと合わせないと依存関係が解決できずvscodeのmetals拡張が壊れる。sdkmanを使うと楽。

iceiceiceのDota2

今日はBTS Pro Series: Southeast AsiaというDota2の大会の決勝があった。名前の通り東南アジアのプロチームが参加する大会だ。決勝戦はFnatic vs TNC。僕はFnaticのiceiceiceのプレーを見ていた。

決勝戦第3試合の彼のNature's Prophetの動きが素晴らしかった。Nature's Prophetは一切の下準備なしにマップの任意の場所にテレポートするスキルを持つ、ある意味Dota2のルールを逸脱したヒーローだ。iceiceiceはこのヒーローの性能をフル活用してマップを縦横無尽に移動して支配し、チームを勝利に導いた。

人間性能も凄い。攻撃動作によって透明状態を解除しようとしたときに敵が視界に入り、瞬時に反応して攻撃動作をキャンセルするシーンがあった。iceiceiceは29歳、プロゲーマーとしてはかなり年長なのだがすごい反応速度だ。

20200414

食事

朝なし
昼我流ペペロンチーノ
夜レーズンパン・カントリーマアム・ヨーグルト

house-temperature-core

Github Actionsによる自動デプロイが完成した。

https://github.com/chao7150/house-temperature-core/blob/master/.github/workflows/main.yml

  1. docker build & docker push
  2. docker-compose.ymlをscp
  3. sshしてdocker-compose up

という3段構成になっている。リモート側のディレクトリのオーナーがなぜかrootになっていてscpの書き込みに失敗し、しかもそれがエラーメッセージからわかりにくかったのですこし手間取ってしまった。

Scala+Playのproduction buildは速い

https://github.com/chao7150/house-temperature-core の話。

以前droneで自動テスト(sbt test)を試みたときはScalaやsbtのダウンロードでとんでもない時間(30分以上)がかかってしまって実用的ではなかったのだが、今回Github Actionsでsbt distを実行したところ1分くらいで終わった。何も調べてはいないが、とりあえず経験知の共有として。

ありがたい技術情報

Scala+PlayでDIする情報を漁っていたらScalaでDI(Play framework2.7 + Guice編)を発見した。控えめに言ってこれは神。一番素晴らしいのはPlay framework2.7で2019年7月12日という新しさ。Playやその他Scalaのフレームワークは容赦のない変更をぶっこんでくる(慣れてないからそう感じるだけかもしれないが)ので、バージョンが違うと全然動かないということはよくある。

技術情報で何より重要なのは新しさだ。記事になっているからには書いた人の環境で、書いたときには動いていたのだろう。しかし時間が経てば経つほど同じコードが動く確率は下がっていく。

だから古い記事の内容を持ち出してきて「これは今でも動く」と書いてくれているだけの情報でも素晴らし価値がある。発信していけ。

ついにDIを書いている

何もわかってないけどPlayFramework2.4におけるDIのテスト方法とかWriting functional tests with ScalaTestとかトレイトの応用編:依存性の注入によるリファクタリングとか読みながらそれっぽい形をした何かを書いている。DIが何をするものなのかはわかってきたが、結局それを実現するためのライブラリの使い方もわからなきゃいけないのでは…?

今週末はすごい嵐になるらしい。停電覚悟で本でも買っておこうか。水と食料。なんで台風いつも休日に来るの?

サウナでホラー/Dota2覚醒/依存性注入

いつもは日曜日にやることだが、3連休なので今日銭湯に行った。サウナは磨りガラスで仕切られていて、そこに中でタオルを振り回す人間の影が映っていてちょっとしたホラーだった。

この3連休で割と熱心にDota2をプレイした。最近は上達の感覚がある。行動とその効果の関係を以前よりも鋭く捉えられるようになった気がする。ちょっとした移動や位置取りでより貪欲にアドバンテージを取っていけるようになった。現在のMMRは4051だ。

Scalaはなかなか進まない。GETリクエストを受けてDBからデータを取り出して返すメソッドのテストをどう書くべきか思案している。DBという外部システムへの依存はユニットテストには持ち込まないのが原則だ。つまりDBからデータを取り出す部分を別の関数に切り出し、本番とテストで別の関数を呼び出すようにする。逆に言えば2種類の実装を本番とテストでそれぞれ注入するということになり、このテクニックを依存性注入(Dependency Injection)と呼ぶ。たぶん合ってるはず。

ガチで知りたい人はこの辺読んでください。僕も今読んでます。

前倒し勤務

今日は10時に出勤して19時に帰ってみた(帰れてはいない)。

夜に空腹になる前に帰宅できるので間食を削減する効果は確かにありそうだ。午前10時は午前11時に比べて涼しいというのもいい。

逆に世の一般的な通勤時間に近づくので電車は混む。難しいところだ。多数派と違うことをすることでメリットが生じる場合もあるが、それ以前に多数派というのはメリットがあって多数になっているのだ。

帰宅してScalaを書いていた。PlayのFormではmodelのunapplyメソッドが必要になる。フォームのデフォルト値としてmodelの情報を入れておくような機能のためだ。

unapplyはcase classだと勝手に作ってくれるのだが、そうでなければ自分で実装する必要がある。コップ本の26章を読むといろいろわかる。Scalaの武器であるパターンマッチの一種、コンストラクターパターンに使われているとか。

Dota2のSoloMMR(サポート)が4051になり過去最高になった。最近はDazzleスパムをやめてAncient ApparitionやWarlockを使っている。どちらもダメージを出せるサポートヒーローで楽しい。だが両者の操作感は全く違う。前者はスキルのクールダウンが短く、アイテムとのコンボも必要になるアクション要素の高いヒーローだ。一方で後者はスキルのクールダウンが長く、タイミングや立ち回りが求められる。

未来の重圧/case classをやめた

未来のある時点に向かって準備しなくてはいけないものが出現したのでなんとなく落ち着かない気分だ。大学にいる頃からこの感覚がひどく苦手で、会社員になるとだいぶ緩和されていたのだが、やはり人生そう甘くはない。毎日死の準備をしながら生きていこうな。

Scalaのクラスはcase classにするとapplyメソッドが自動で生えるのだが、これと合わせてコンパニオンオブジェクトで自前のapplyも実装するとコンパイラがどっちを使うか判断できなくて怒る。

sealed abstract case classという手もあるらしいが、インスタンス化したいクラスなのでこの手は使えない。結局どうにも出来なかったのでcase classにすることをやめた。それほど恩恵を受けていたわけでもないし。

ScalaでUnion型

普段仕事ではTypeScriptを書いているので
const x: "kinoko" | "takenoko" = "kinoko";
みたいなの(Union型という)に見慣れていた。

趣味ではScalaを書いており、同じようなものを書きたくなった。具体的にはActiviryPubのActor Typesを表現するためにApplication, Group, Organization, Person, Serviceのどれかの値(いずれも文字列)をとるという型を作りたかった。

case class

しかし調べてみるとScalaにUnion型はない。自分でパッと思いついたのはcase classだ。ドワンゴのScalaテキストに近い用例が載っている。下にそれを引用する。

sealed abstract class DayOfWeek
case object Sunday extends DayOfWeek
case object Monday extends DayOfWeek
case object Tuesday extends DayOfWeek
case object Wednesday extends DayOfWeek
case object Thursday extends DayOfWeek
case object Friday extends DayOfWeek
case object Saturday extends DayOfWeek

sealed修飾子をスーパークラス/トレイトに付けることによって、その(直接の)サブクラス/トレイトは同じファイル内にしか定義できない

ので、パターンマッチするときにコンパイラがいい感じにチェックしてくれるというメリットがある。

上記を参考にこんな感じで実装してみた。欲しいのは文字列なので、toStringをoverrideしてクラス名をそのまま取得できるようにした。

objectにするとgetClass.getNameの末尾に$がついてしまうのでinitしている。最後の1文字を除去するというメソッドがある多機能さ、いかにもScalaっぽい。あるいはcase objectじゃなくてcase classにすればこんな小細工は不要だが、パラメータリストが必要になるという面倒臭さがある。どうあるべきなのか、自信ニキは教えてほしい。

Enum

もう一つ、これは同僚に教えてもらったものだが、Enum型を使う方法もある。

こちらは採用しなかったのであまり深入りしていない。もしかしたらこっちのほうが良かったかもしれない。いや、いま猛烈にそんな気がしている(表現したいのが単なる文字列なので)。

それにしても大事なのはググり力だ。僕が「Scala ユニオン型」で検索してもいい情報は得られなかったが、「代数的データ型」という言葉を知っていればこの記事に辿り着けただろう。思うに、体系的な勉強は裏切らないのだ。

型の道は深く険しい…

爆速帰宅無為ゲーム/ScalaのEvolutionsを捨てた

8/29

月末なので労働時間調整のために早く退勤した。時間が出来たのでDota2を3ゲームやったが全部負けた。自分一人の力ではどうしようもないと感じる負け方だったので辛い。

Scala+Play FrameWorkで作っているアプリケーションでDBの初期化のためにEvolutionsを使おうとしていたのだが

Unexpected exception[JdbcSQLSyntaxErrorException: Table "PLAY_EVOLUTIONS" not found;

というエラーがでてどうやっても解決できなかったので諦めた。情報がなさすぎる。

Evolutionsを使わなくても、適当なクラスのコンストラクタでcreate tableすれば済む話だった。ちゃんと公開するときはDBは別で作ればいいし。