Posts for: #2023/02

開発の追い込みに集中

23時に寝て2回ほど起きて7時に起きた。土日コードを書いて疲れていたので月曜日は早めに業務を切り上げて実家のいろいろをやっていた。

開発の追い込み

サーバーサイドとフロントエンドはほぼ開発が完了し、これからテストするだけといきたいところが、想定外のことがあってまだそうはなっていない。

予想外のことは起こるものだ。ガトーは良くやっている by エギーユ・デラーズ

と言っているほどの、予想外というわけでもないが、思った通りに進捗しなくてリリースの危機を迎えている。なにが起ころうとプロジェクトの全責任はマネージャーにある。いま溜まっている issue をメンバーに再分配して乗り切ろうと定例会議で話した。私が2人分ぐらいの作業をすれば1週間もあれば取り戻せる程度の遅れではある。ただ残り時間が1ヶ月しかないだけ。また週末働いてその足で東京に行くのだろうなと直近の未来を想像していた。

上司道 野村監督から学ぶリーダーの器のつくり方

お仕事にテンパっているものの 第86回上司道 野村監督から学ぶリーダーの器のつくり方 に参加した。上司道 に参加するのは2回目。

以前 野村ノート を読んだことがある。 野村監督は言語化にこだわりのある方で選手としても監督としても一流だった氏の実践知の言語化は参考になるかもしれないと思って読んだ。本書は期待した通りでプロ野球に限らず、一般のビジネスパーソンにとっても汎用的に役に立つアイディアがいくつもあったように思う。

例えば、野村監督が捕手に求めるものとして次がある。判断というのは知識と経験を根拠になんらかの基準をもってくだすといったことが書いてあった。判断の前に分析と観察と洞察の3つの段階を語れる人がどのぐらいいるのだろうか。

  1. 分析
  2. 観察 (目に見えるものをみる)
  3. 洞察 (目に見えないもの = 心理を読む)
  4. 判断
  5. 記憶

今思うのは、小さいことを重ねることが、とんでもないところに行くただ一つの道だと感じている。

これはイチローのコメントだが、この言葉は野村監督の野球観に通じていて感銘を受けたと書いてあった。そんな風に野村ノートがおもしろかったので、その延長上で野村監督に関するイベントなら参加してみようと思った次第。

実際のイベントについては、期待値も高かったのかもしれないが、私の求めていたイベントの内容ではなかった。野村監督と付き合いの長い番記者が野球人としての野村監督というよりも、一般人としての野村監督の在り方を伝えるような著書やそのイベント内容だったと思う。あと野村監督の話しを聞きに行ったのだけど、半分以上は講師が自分のことを多く話すのでその点もアンマッチだったと言える。上司道のイベントは2回目なんだけど、これまでどちらも私の求めていたものではなかった。もしかしたらマネジメントやリーダーシップのイベントで話すのはなかなか難しいのかもしれない。それはいろんな業界・業種の人たちにとって参考になるリーダーシップのようなものはないのかもしれないなと感じた。ドメイン知識も含めてのリーダーシップの話しをしないと、宗教のような徳を積んで治めなさいといったありがたい話しの一般化になってしまう気がする。

人間力は定性的なもので言語化が難しい。それよりも実践知はもう少しスキル寄りなものだと私は考えていて、習慣だったり洞察だったりなら誰でも訓練すれば身につけられるのではないかと思う。少なくとも野村ノートからはそういった片鱗が私には読み取れた。

go 1.20.1 を使い始めた

0時に寝て何度か起きて7時半に起きた。あまりうまく眠れなかった。

go 1.20.1 へのアップグレード

リファクタリングの区切りがついたらやろうと思っていて遅れた。すでに 1.20.1 がリリースされている。先日 Go 1.20 リリースパーティ に参加して、いろいろ聞いていると改善されているところや新しい機能を試してみたいものがいくつかみつかった。単純にアップグレードするだけでも最大でビルド時間が10%短縮される可能性がある。1.18 と 1.19 で generics 対応でビルド時間が遅くなっていたのが 1.17 相当に改善されたらしい。やっぱり generics はコンパイラを複雑にするものなのでコンパイル時間が長くなる傾向があるんやなと話しを聞いていて思ったりもした。ついでに依存ライブラリなどのバージョンアップもまとめてやった。単体テストと結合テストが普通には揃ってきたのでバージョンアップなども安心して実行できる。

rocky linux のネットワーク設定

テスト環境に使っている rocky linux の ip アドレスを変更する必要があったので調べてみた。ちゃんとした公式のガイドが出てきてすごいなと感心した。

ip アドレスを確認するコマンドが ifconfig から ip に変わっていたり、ネットワーク設定のためのツールも私が知っているものとは全然変わってしまっている。

$ ip addr

Network Manager のサービスで設定されているようでそのための設定ファイルは次の場所に保存されていた。

/etc/NetworkManager/system-connections/my-device.nmconnection 

これを書き換えるツールとして nmtui という tui ツールと nmcli という cli ツールの2つがある。tui とか懐かしいなとか思いながら操作していた。ssh 経由で設定していたので cli でいきなり設定を反映するよりも tui で設定ファイルを書き換えて os を再起動するのがよいだろうと考えてやってみた。ドキュメントに書いてある通りに操作したら意図した ip アドレスを設定して変更できた。

コードを書いていると後から改善点に気づく

1時に寝て7時に起きた。起きてからドラクエタクトをだらだらやってて10時前に起き上がってそれからオフィスへ行って活動してた。

リファクタリングのリファクタリング

昨日書いたマージリクエストの変更点についてドキュメントの更新だけしようと作業していたら、その後、一緒に修正した方がよい追加の機能拡張に気付いて3時間ほど追加の実装をしていた。その後、お昼ご飯を食べているときに午前中に書いた実装を改善した方がよいところに気付いて、さらに追加で1時間ほどリファクタリングしていた。コードを書いていて、一旦はできたつもりになってその時点ではよさそうに思うのだけど、時間が経ってから考え直すと考慮漏れやもっとよい実装のアイディアを思い付いたりする。私の頭が悪いだけかもしれないが、最初からよい実装や設計を行うことは多くの人にとって難しいことだと思いたい。何度も考えて作り直したり改善したりしているうちにもっとよい方法に気付く。

多くの開発者はもっとよいアイディアを思い付いたとしても実際にリファクタリングをしようとしない。動いているコードを修正して壊れるリスクや他に優先度の高い作業があるとか、いろいろやらない理由を言う人たちもいる。私はそのやらない理由を議論している合間にリファクタリングしてしまう。というのは、誇張した比喩で実際にはもっと時間がかかることもあるけど、設計も見直す数千行レベルの変更を気軽に行う。もしそれで壊れたらどうすると聞かれてもシンプルに謝るだけ。謝ってから直す、テストを書く、再発防止のための仕組みを考える。やることはそれだけ。問題のあるコードを見て見ぬ振りをする開発者の方が普通という感覚がある。10年以上開発をやってきて思うこととして、そういう価値観を上位の開発者が壊していって模範を示すことがよい開発文化への第一歩となる。しんどいことに対して口だけでは人は動かない。個々の開発者が問題だと思ったらどんどん書き直していく、リファクタリングしていくという文化は一朝一夕ではできない。そういう開発文化を醸成していくと大きな技術的負債が溜まるといったことはなくなるのではないかと考えている。

リファクタリング一段落

1時に寝て7時に起きた。前日も21時頃までオフィスにいて、今日も午後からコードを書いていて22時ぐらいまでやってた。コードを書いていると時間がどんどんなくなる。本当は三宮.dev の勉強会があったんだけど、このリファクタリングは週末にやってしまわないとやばいという野生の勘でキャンセルした。

ストレッチ

今日の開脚幅は開始前156cmで、ストレッチ後160cmだった。だいたいいつも通り。先週から右すねの外側の筋に張りがある。先週よりちょっとよくなった気もするけれど、まだ張りが継続している。あと今週は右腰に張りがあった。今週はリファクタリングしていて座ってきる時間がいつもより長かったためだろうと推測する。どんなに忙しくてもストレッチだけは休まないようにしている。ストレッチに通い始めて2年以上経つが身体的に体調が悪いということは記憶にほぼない。日記にはその週のどこそこに張りがあるとか調子が悪いといったことを書いたりしているが、それは日常生活を送る上で支障が出るようなレベルではない。そうならないように予防している。健康を維持する上でストレッチは大きな影響を与えているため、中長期の展望から忙しくても継続するようにしている。

機能拡張とリファクタリング

今日は休日出勤して go のコードを書いていた。ある機能を作るときに内部的には汎用の api にしてしまって他のコレクションのデータ型でも再利用できるようにしたい。先週ずっと go の generics を使って mongodb 周りのコレクションとそのクライアントのリファクタリングをしていた。go の generics の理解も進んで crud なインターフェースを generics でどのように定義して実装すればいいかわかってきた。その過程で web api のアプリケーション層と mongodb のインフラ層 (データ層) の役割分担も明確になりつつある。どちらも generics を駆使して型チェックされた上でソースコードを共通化し、汎用 api としてリファクタリングしながら設計している。その集大成としてアプリケーション側で汎用的な機能を追加するときに、理想的には1つのコードを追加・変更すれば、別のデータ型でもすべて同じように動くといった機能として実装した。4つのコレクションのデータ型で同じ振る舞い (機能) を共通化する。その実装も丸1日やれば完了できるぐらいに設計の効率化ができてきた。

go はオブジェクト指向言語ではないので generics を駆使しても、java でいうところの抽象既定クラスを用いたテンプレートパターンの実装ができない。それぞれの構造体で基本的にはコピペとなる構造体のメソッドを定義しないといけない。もちろん別のヘルパーに移譲するといったことはできるけど、状態をもっていないコードの再利用はたしかに安全ではあるけれど、状態を参照できないからそのために値をコピーするといった整合性の懸念やボイラープレート的なコードを書く必要がある。これは設計におけるトレードオフになるので go の処理系の設計に不満があるわけではない。但し、generics でできることにはまだ機能不足がある。とくに直和型の扱い。できないのかな?とググると proposal の issue がみつかるので今後の機能拡張に期待したい。

正直マネージャーが開発に工数使っていて何やってるんだとみられているかもしれない。1-2週間集中してリファクタリングしてみて、いまのアプリケーションの設計の勘所が以前よりも理解が進んだ。コードレビューだけではわからないフィードバックがある。結合テストもいくつか追加したので今後の開発で役に立つはず。これで私の (リファクタリング) 開発は終了しようと思う。

今日作ったマージリクエストの diff が次になる。

51 files +1314 -648

diff の行数だけ数えると今週だけで1万行近くは変更したと思う。

mongodb のトランザクションの考え方

1時に寝て8時に起きた。3時頃に気分悪くて起きて少し吐いてそれからまた寝た。丸1日機能拡張とリファクタリングのために go のコードを書いていた。

mongodb のトランザクション管理

2つの web api から同じコレクションの異なるフィールドを更新したい。mongodb で厳密なトランザクションを管理するようなアプリケーションではないけど、なるべく整合性を維持できるように努めることはやっておきたい。mongodb でトランザクションに近いことを実現する方法として次の記事が参考になった。

この記事では findOneAndUpdate() という api を使って、更新時に必ず変更されるフィールドを含めることで find したときのそのフィールドの値が変わっていればエラーになってくれることでトランザクション相当の機能が提供されると書いてある。必ず変更されるフィールドとして ObjectId を使えば他の更新処理を検出するのに役立つだろうとある。いま私が開発しているアプリケーションでは同じフィールドを複数の web api から更新するわけではないのでここまで厳密なトランザクション管理は必要にない。

既存の処理が Replace を使って実装されていたのを Update を使うように変更する。Replace と Update の違いはドキュメント全体を更新するのか、一部のフィールドのみを更新するのかの違いになる。具体的には go のドライバーにおいて次のメソッドの使い分けになる。

これらのメソッドを使うことで find と replace/update の操作を1回の処理でできるから効率もよいらしい。

結合テストのリファクタリング

0時に寝て7時に起きた。前日は久しぶりに飲んでいい気分で寝てた。朝コンビニ寄ったらいつもほぼ満席のイートインが閑散としているなと思いつつ、オフィスへ行って始業報告して、今日祝日だよとツッコミもらった。全然気付いていなかった。まだ新しい天皇誕生日に慣れてない。

go のテストにおける setup/teardown 関数の実装

昨日から結合テストのリファクタリングをしていてせっかくオフィスに行ったので続きをする。結合テストだとデータを作ったり削除したりをテスト単位にやりたい。例えば、ユーザーを作成してテスト実行し、終わったら作成したユーザーを削除したい。次のように setup 関数を書き、返り値として teardown の関数を返す。このときに t.Helper() を呼び出しておくと、エラーがあったときにどの呼び出し元のテストでエラーが発生したかがわかる。

func setupUsers(t *testing.T, users []mongodb.User) func() {
	t.Helper()
	user := mongodb.NewUserCollection(url, username, password)
	for _, u := range users {
		if err := user.Save(u.ID, u.Attributes); err != nil {
			t.Fatalf("failed to create a user: %s", err)
		}
	}
	return func() {
		t.Helper()
		if err := user.Truncate(); err != nil {
			t.Fatalf("failed to truncate the user collection: %s", err)
		}
	}
}

使い方は簡単で setup 関数を呼び出すと teardown 関数が返ってくるのでそれを defer で呼び出すとよい。

teardown := setupUsers(t, usersTestData)
defer teardown()

しかし、この setup 関数をサブテストと一緒に並行実行すると意図したように動かない。どうやらサブテストを並行実行すると親テストが呼ばれた後に呼び出されるという仕組みになっていて、サブテストを実行する前に teardown が呼ばれてしまうので意図した制御にならない。How to handle parent test teardown with parallel subtests in golang の回答 によると、サブテストからさらにサブテストを実行するとよいとある。この場合、親テストとサブテストは同期的に実行され、サブテストの中でさらにサブテストを並行実行するという考え方で意図した振る舞いになる。並行実行するときは次のようなコードになる。

func TestMy(t *testing.T) {
    tests := []struct{
        // test cases
    }

	teardown := setupUsers(t, usersTestData)
	defer teardown()

	t.Run("wrap for setup process", func(t *testing.T) {
		for _, tt := range tests {
			tt := tt
			t.Run(tt.name, func(t *testing.T) {
				t.Parallel()
                // do test
            })
        }
    })
}

zeromq の多言語対応がすごい

1時に寝て7時に起きた。昨晩は食べ過ぎて気分が悪かった。

エレベーター点検の間違い

朝オフィスの入っているビルへ着くと、エレベーターに張り紙があって使えないことが書いてある。問題があれば、エレベーターの保守会社へ連絡してくださいとある。その張り紙をみて、エレベーターが故障したのかな?と勘違いした。その横でオフィスの利用者が10人ほど復旧を待っていた。仕方ないから一旦、家に戻って午前中は家からお仕事することにした。これはこれで docker で開発環境を作っていると、普段使っていないマシンでもすぐに開発環境を構築できることのメリットを実感する機会となった。11時頃に再訪したら普通にエレベーターが動いていて、あれ!?と思って、そのときに初めてビルの掲示板を見に行ったら、7:30 - 8:30 の時間帯でエレベーター点検だと書いてあった。私は8時前後に出社するのでこの時間帯は厳しい。エレベーターが動いていなかったらまず点検を疑うことにするのを学んだ。

zeromq の調査

昨日から zeromq の調査をしていた。ネットワークの通信におけるプラクティスとも言える、ØMQ - The Guide というごっついガイドもあって学びが多い。少し古いバージョンなら翻訳版も ØMQガイドブック(日本語版) にある。英語が苦手な方はまずこれを読んで概要を掴むのもよいかもしれない。ちなみにこの翻訳者の方といま一緒に働いていて設計のレビューをお願いして教えていただいている。感謝。

zeromq を使うときの注意点の1つとして、バックグラウンドで i/o スレッドが動いていて zmq_send() は実際に通信しているのではなく、バックグラウンドの i/o スレッドにメッセージを渡すだけになる。そのため、i/o スレッドが実際にノード間の通信を非同期で行う。これは接続先の相手がダウンしていても送信バッファにメッセージを溜めておいて再送してくれるので都合がよい。ちなみに送信バッファのサイズは zmq_setsockopt()ZMQ_SNDHWM を指定して調整できる。ソケットが常時接続されていれば、メッセージの順序は維持されるらしいが、ソケットを接続/切断するような使い方をすると zmq_send() が呼ばれたメッセージの順序は保証されない。一般の queue をイメージしてメッセージの順序が保証されることを前提に開発すると落とし穴があるので注意しておく必要がある。そういう so や issue も登録されているのを確認した。

近況報告の雑談

約1年ぶりにやすだ先生と大阪でオフライン飲み会をした。毎年2-3月頃に近況報告して経営のアドバイスなどをいただいたりしている。今回で3回目。今年は私がいま実家のいろいろとリファクタリングなどでいっぱいっぱいなのでとくに近況報告の資料を作る余裕がなくて、普通に飲み会しながらその場での近況報告となった。昨今の web 開発の当たり前として ci/cd や k8s のことを共有しながら、大学のシステムはどうこうみたいな話しもした。やすだ先生も副業が好調らしく、東京に出張する機会も多いとご活躍されているそうだ。

今回 クラフトビアハウスモルト 梅田店 というお店に初めて行った。私のような普段着の人間でも気軽に入ってよいようなお店であることもわかった。また接待で使おうと思う。食べものはちょっと上等なおつまみがある程度なのでビールを飲むのをメインとする相手がよいだろう。飲み放題コースにしたので、食べものの選択やビールの値段を気にせず注文できたのも接待としては考えることが減ってよかったと思う。阪急グランドビルの31Fという最上階にあって、あまり広いお店ではないが、気軽に夜景をみながらクラフトビールを飲める。早めに予約したおかげだと推測するが、カウンター席の一番端だったので座席もよかった。その横におそらく VIP ルームがあって、個室かどうかよりも店内が広くないので広いスペースを使う意図で VIP ルームもよさそうにみえた。追加料金なく借りれるのかな?2人で借りるのは難しいかもしれないが、4人ほどいれば借りてみたいと思う。

気付きスキルをあげるための指導とか

1時に寝て7時に起きた。すでに疲労困憊の様相。

仕様は誰が決めるのか

たまたま定例会議である仕様について話題になった。この作業はなぜ止まっているのだっけ?と確認したら、とくに理由なく、決めの問題を誰が決めるのかでお見合いしてしまっていたような状況であることがわかった。担当の開発者は新人さんなのでスキルや経験が未熟だったりするのはよいとして、仕様を決めていくときの作業の段取りをどうやって学んでもらえばよいかについて、私が考えるよいきっかけとなった。誤解のないように書いておくと、仕様確認できずに作業が止まっていたのはマネージャーである私の責任なので担当者に非はない。

開発の仕様を決めることは難しい。要件であればお客さんに確認しなければいけないこともあるし、背景を調査したり一定の技術知識がないと決められない仕様もある。誰もが最初は上司や先輩に仕様を教えてもらいながら開発経験を積み、自分で仕様を考えたりできるようになっていく。仕様を誰かから与えられるのを待っている ==> 自分が決められる仕様は自律的に決めて作業を先に進めていくの間にある、なにか気付きを与えないといけないと実感した。

この話題でこみやさんと話してみた。

「自分が決めていいこと」の中にはこのあたりが含まれていると思う。

  • ある程度正しい判断ができること
  • 判断に自信がない場合に相談ができること
  • 判断に自信を持てること (先に進める胆力があること)

自ら枷をはめる人は結構いるとは思っていて、明示的にやっていいことを伝えてチャレンジする雰囲気を作りたいのは同意です。ということで、判断できないというのは

  • 担当範囲かどうかわからない (自分で決めてよいかわからない)
  • 対応が適当であるかわからない (自信がない)

あたりに二分されるのでは、と集約されるのかも。

後者のレベルの人に対しては相談してくれ、ブロッカーを排除するのを手伝うから、とホウレンソウを覚えてもらう感じかなあ、というのが最初のコメント。仕様を決める能力がなくても、聞きに行く能力は持っていてほしい、という感じ。困ったら騒いでほしい、というのが僕が求める最初のステップですね。

スプリントを完了させるのがミッションなので、それができないとチーム全員不合格だよ。このまま待ってていいの? 仕様はどうやったら決まるの? って伝えそうだな、僕なら。

いくつかキーワードがあるように思える。

  • 自信
  • ホウレンソウ
  • 納期の認識

「とりあえずやってみて」とか「まずは自分で考えて」が、今の若者に響かない理由。 の記事によると、いまの若い人は答えを知った後に試行錯誤したり、その後の応用で差をつける文化があるといったことが書いてある。その賛否はともかく、他のマネジメントのイベントでもいまの若い人たちは非効率なことや無駄なことをやりたがらないという話しを聞いたことがある。

まず私が教えないといけないことは、開発や設計において答えなんてないという真理だと思う。確かに経験のある開発者が行う設計は答えのようにみえるかもしれないが、設計は要件の変化によって大きく影響を受ける。いわば時間制限付き論理最適解のようなものだ。またドメイン知識の有無によっても変わってくる。設計とは、そのときに1回判断したら終わりではなく、ずっと考え続ける行為である。試行錯誤することは無駄なことではなく、よい設計を行うための最短の方法であることを教えないといけない。

自信をつけてもらうにはどうすればいいだろうか?これは成功体験を積み重ねるしかないと思うが、成功体験がない初期はどうすればよいのだろうか?パッと思いつくのは心理的安全なチームを作って、ここで失敗しても自分の過失やストレスにならないとメンバーが感じられて挑戦する雰囲気を作ることに思える。このこともそれを体現するのはリーダーの役割なので私がうまくその雰囲気を作れていないと言えるだろう。

ホウレンソウは課題管理を推奨する私にとっては得意分野なのでここでは割愛する。今回の一件もホウレンソウができていないわけではない。課題管理システム上に仕様を決めなければいけないことをコメントに書かれていてそのことに私も気付いてはいた。作業が止まっていることに気付いていなかっただけ。

最後の納期についてはどうだろうか。いまのところ、意図的に私は納期についてほぼチームに言及していない。それはメンバーの1人は十分に理解して自律的に動いてくれているので言う必要がないのもある。新人さんは納期に間に合わせるよりも適切な仕事のやり方や考え方を学んでほしいと私は考えている。納期を意識して不十分な品質の成果を出すよりも時間がかかっても一定の品質の成果を出せるように指導していきたいという私の考えから言及していないので、これも私の非であることは疑いようがない。

1つずつみていくと課題があるのはマネージャーのマネジメントにみえる。なかなか難しい。過去にタイムラインでつぶやいたことを思い出した。

コンテキストによるキャンセル処理

1時に寝て7時に起きた。昨日がっつりコードを書いていたせいか、起きてから今日は休みたいと思いながらだらだらしてた。休めないのだけど。貧乏暇なし。

echo のリクエストコンテキスト

昨日の続きで mongodb のリファクタリングをしている。mongodb はほぼすべての処理で コンテキスト を受け取れるように設計されている。メンバーが go の context の扱いを理解していないのでコンテキストを渡すようなインターフェースになっていない。私もこれまでのコードレビューでキャンセル処理は些事なのでそれよりも機能開発を優先して後回しにしていた。それで、いま機能が一通り開発完了したのでインターフェースにコンテキストを受け取るようにリファクタリングした。デフォルトのコンテキストとして echo のリクエストコンテキストを渡す。Canceling request #1815 によると、echo のリクエストコンテキストは次の状況のときにキャンセルしてくれる。

  • クライアントのコネクションがクローズされたとき
  • http2 でリクエストがキャンセルされたとき
  • ServeHTTP() が返るとき
    • サーバーがシャットダウンするタイミング?

使い方はこんなイメージ。

ctx := c.Request().Context()
store := c.Get(myStore).(Store)
store.Get(ctx, request.From, request.To)

mongodb の view 調査

4時半に寝て11時に起きた。午後から go のコードをリファクタリングしてた。平日はメンバーの issue を監視して困ってたらコメントしたり、マージリクエストをレビューしたり、管理画面の振る舞いを検証したりと、コードを書いていても途中で作業がちょくちょく中断する。休日にコードを書くとその中断がない分、いつもよりかなり捗った。リファクタリングに思いの外、時間を取られている気がしたのはそのせいもあるか。

mongodb の view 作成

実はこれまで mongodb を扱ったことがなくて今回初めて触っている。とくに難しくもないのだけど、ドキュメントを探してやりたいことを調べたり、デバッグや開発のためのツールとしてどういうものがあるかといった知見がない。ないものは仕方ないので1からドキュメントを読みながら開発というか、リファクタリングをしている。mongodb そのものの知見はなくても、様々なデータベースを操作する開発をしてきたのでやりたいことに対して実装方法はいくつか検討がつくし、その実装を支援するための機能もあるはずだと予測がつくので探すのも早い。

ある collection から複数のデータ構造のレスポンスを返すような処理がある。こういったものは view を使うとうまく整理できると知っているので調べると mongodb view が提供されていることがわかる。3.4 から追加されたらしい。いまクエリの中で aggregation pipeline を書いている処理のいくつかは、あらかじめ view を定義してクエリすることでインフラ層を堅牢にした上で実装もシンプルにできる。さらに 4.2 から on-demand materialized view が追加されていて、標準の view と比較して aggregation pipeline の計算結果をディスクに保持するのでパフォーマンス上のメリットがある。元データの更新が頻繁でなければ on-demand を使った方がよいのだろうと推測する。

またこれまで mongodb の管理画面に mongo-express を使っている。view の振る舞いを確認しようとしたところ、どうも view には対応していないようにみえる。web ベースの管理画面を他にも探してみたが、どうも他に適当なものがない。mongodb が公式に compass というデスクトップアプリケーションの gui クライアントを提供している。macos なら brew からインストールできた。

> brew install mongodb-compass

このツールは collection も view も両方扱えるし、クエリやパイプラインも実行できて機能も充実している。web ベースじゃないとインフラとして共有はできないところだけが残念なところ。それでも開発する上ではとても強力なツールにみえる。適当にデータをインポートしたり、テストで aggregation pipeline を作成してみて、それをエクスポートして view を生成するときのスキーマ定義も作ることができた。ui も洗練していて、こんな優れたデスクトップアプリケーションは久しぶりにみたと思うぐらい感心した。

右すねの外側の筋に張りがある

23時に寝て7時に起きた。旅行のときにもっていく歯磨きセットを実家に忘れてきた。髭剃りが見当たらないと思っていたのは、その歯磨きセットに入れていたからのせいだと気付いた。髭剃りを買い直してもいいかもしれない。

ストレッチ

今日の開脚幅は開始前156cmで、ストレッチ後159cmだった。2-3日前から右の足首に違和感があって歩くときにかばってしまう。トレーナーさんに相談してみたところ、右足のすねの外側の筋に張りがあることがわかった。なぜそうなってしまったのか分からないけど、それがために立つときなどの、足首に力が入る瞬間に若干の痛みや違和感を感じるらしい。足首の違和感については、すねの外側の筋か、ふくらはぎのどちらかに起因するという。さすがプロという感じで、私が曖昧に、痛いわけではないけど足首に違和感を感じると言っただけで的確にその原因となっている筋を突き止めた。その延長で調子の悪い部位を丁寧にストレッチしてもらった。毎週ストレッチしているからこういった体調管理もできる。いまやストレッチが私の健康管理の中心になっている。

車の1ヶ月点検

ストレッチが終わってからお昼ご飯を食べてディーラーさんへ1ヶ月点検に行く。すでに契約は完了していて、実際に私も車に乗っているわけだけど、自動車重量税の請求額が間違っていましたということで9,600円を返金していただく。なぜか営業さんは返金したつもりになっていて、口座への振り込み確認はしましたか?と尋ねられて、数日前の時点では入金はなかったものの、今日チェックしているわけではないのでひとまず 「分からないです。」と回答しておいた。そしたら、そもそも返金先の口座を聞いていなかったので口座を教えてくださいとなって、そんな勘違いの失敗ある?って思って、ちょっと私の中の担当者さんの信頼を落とすやり取りとなった。

実は車の取引の請求書を作り直すのは今日で2回目になる。1回目はナンバーの登録手数料の金額が間違ってました。2回目は自動車重量税の金額が間違ってました。 それはなんらかの省庁の都合で急に金額が変更されるものだろうし、そういう間違いはあるだろうと受け入れていたんだけど、返金したつもりになっていて口座すら聞いてないというのは違うだろうと思えた。担当の営業さんはよい人なんだけど、なんか仕事の詰めの甘さみたいなのが垣間みえる雰囲気がする。補足として請求書に貼り付けしている200円の収入印紙はどうなるのだろう?と思って調べてみたら 印紙税過誤納[確認申請・充当請求]手続 という手続きがあって、誤って使ってしまった収入印紙ののお金は返金されるみたい。それがなかったら2回の請求書誤りで400円の損害になる。