Posts for: #Health

風がなければ公園でバドミントンもできそう

風がなければ公園でバドミントンもできそう

先日購入した ポータブルネット を使って公園で屋外バドミントンを1時間ほどした。持ち運びするときの折り畳み状態が次になる。筒の中に紐が通っていてバラバラにならないので簡単に組み立てできる。初見でも2分あれば組み立ても片付けもできる。予想以上に組み立て/片付けの体験がよかった。

みなとのもりの運動

前回の所感 。水曜日に運動部の slack チャンネルに投稿していた。とがいさんが久しぶりにバスケの練習に来られた。9時から準備を始めて10時から公園で運動する。土曜日の午前中に運動の予定を入れるのは朝ちゃんと起きる理由にもなってよい。予定がなければ、お昼までだらだらしてしまっていたかもしれない。私はトラックを4周ジョギングしてストレッチをしてからバドミントンのひとり練習をしていた。とがいさんもバスケ練習が終えてから合流して一緒にバドミントンの練習もした。10時半頃から軽くウォームアップして、ネットを挟んで打ち合いをした。ネットがあるとバドミントンの練習をするモチベーションにもなるし、場所を固定するのにもよい。太陽とシャトルが重ならないような位置取り、風の向きなども考慮して場所を決めないといけない。2回休憩して11時半頃まで打ち合いの練習をして終えた。よい運動になった。

バドミントンは体力さえ続けば1時間ぐらいなんとなくでやってしまう。誰でもできる有酸素運動としてよさそうにみえる。テトリスのような、シンプルなゲームだからついついやり続けてしまう魅力がある。

ストレッチ

今週は毎日30-60程度はバドミントンの練習をしてきて汗をかくぐらいには運動してきて太ももに張りを感じていた。ゆっくりやっているつもりでもたまにチカラが入ってしまうときもある。以前 SPINE SALON さんで診察 してもらったときの状況に似ている。また筋が少しズレているのかもしれない。運動を再開してからはこのときに教えてもらった体操もしていた。トレーナーさんも気遣ってくれて右太ももを念入りにゆっくり伸ばしてくれた。そのせいか、ストレッチ前と比べてずいぶん楽になった。今日の開脚幅は開始前146cmで、ストレッチ後154cmだった。少し休みながら様子をみてみようと思う。

バドミントンのひとり練習

今日のバドミントン練習はリフティングを30分した。連続最大回数は27回だった。

最後の厄介なリファクタリング

10時頃に起きて11時にはオフィスへ来て作業をしていたと思う。昨日ジョギングと筋トレしたから寝起きジョギングはやめて普通にオフィスへ行って作業していた。この issue はどこまでリファクタリングするかの決めの問題もあり、少し寝かせてあった。私のもてるスキルを駆使して思い切りやることを決めて土日で大半を終わらそうと思う。いくつかの葛藤と逡巡を振り払って着手はした。昼間は既存のコードの本質的な問題の分析、再設計のための要項の調査、軽くコードを書きながらの感触の確認などをしていた。その後、ストレッチに出掛けて戻ってきてから続きをやるつもりが、いろいろ雑務をやっていたら22時ぐらいになってしまってまた明日でいいやと諦めた。モチベーションが足りない。一回休み。

ストレッチ

昨日、久しぶりに筋トレをして夜は全然平気だったのに寝て起きたらあちこち全身筋肉痛でストレッチもかなりきつかった。悪い痛みではないから筋肉をほぐしてもらった感じになる。今日の開脚幅は開始前146cmで、ストレッチ後153cmだった。筋肉痛だから硬めのように思えたが、数字だけ比べたら普段とそんなに変わらなかった。

トレーナーさんと自民党の総裁選挙の話題になって、一通りニュースをみて私も思うところはあったものの、政治的な話題のやり取りする場所がないから誰と話すこともないだろうとしまいこんでた矢先、トレーナーさんから話題が出てきたのでいろいろ話してみた。石破さんは自民党内で嫌われているから決戦投票で勝てないだろうという大方の見通しを覆したのは見事だったし、石破さんは良識なリベラル、且つ金融所得課税の強化に前向きだったりもするから市場の反応は悪い。これまでは総理大臣が変わったタイミングはご祝儀相場のように歓迎されることが多かったのに対して、月曜日は株価が急落するようにみられている。これほど市場からネガティブな反応が出るのも珍しいなという所感。余談だが、私はいまどちらのポジションもとっていないので株価が下がってもあまり影響はない。個人的にはシステムへの理解が深いという側面だけで河野さんを応援しているものの (一方で官僚に対するもの言いがパワハラ的なところがマイナス)、今回は後ろから2番目と不人気だった。日本では自民党総裁=総理大臣なわけではあるが、政治家が影響力をもつタイミングというのは本当に難しい。石破さんも5回目の総裁選ということで悲願が叶ってよかったんじゃないかと応援したい。

ひとりでできるバドミントンの練習

ストレッチを終えてから 購入したラケットを受け取り してきた。試し打ちではないけど、買ったばかりで使ってみたいから KALIDIA チャンネルから1人でできる練習を探してみた。次の練習はラケットとシャトルとの距離感を掴むための練習になるという。なるべく日課としてしばらく続けてみたい。

  1. シャトルのキャッチ
  2. バドミントンの技を3つ行う
    • スピンネット
    • ミニクロスネット
    • ロビング
  3. リフティング
  4. 屋外で向かい風に向かってロビングを打つ

よい土曜日

土曜日はだらだらしがちなのが、今日は朝から起きて活動できた。お昼に少しコードを書いて、夕方にストレッチして、夜はカフーツさんへ行ってきた。よい一日になった。

みなとのもりの運動

前回の所感 。起きてからシャワーを浴びようとしたときにふと軽く走ってこようと思い立って9時過ぎから公園へ出掛けてトラックを3周ほどジョギングしてきた。公園に近いマンションに引っ越したことのメリットを活用できた。運動するとそれだけで報酬系を刺激して気分がよい。これまでは起きてもしんどくて出掛ける余裕がなかった。ジョギングへ出掛けられるぐらいには体力が回復してきたのかもしれない。来週も朝からジョギングへ出掛けてみたい。

ラケット選び

うちらの業界で言えば未経験者が「どのプログラミング言語を学べばよいですか?」という質問の答えになる。私なら一番無難なのは typescript で、データ分析や汎用用途で学ぶなら python、バックエンドが好みなら go といったようにお奨めする。こういう答えのない問いは経験者にこれと決めてもらうのがよい。ラケット選びのサイトをみてもパラメーターがいくつかあるのは理解できたが、最初にどのラケットを選択してよいかがわからない。経験者のやまとさんに相談してみた。エントリーモデルの、価格帯は1万円前後のものでよいという。振った感じで合う合わないがあったりするから、お店へ行って店員さんに相談したり試し打ちさせてもらったりするのがよいとのこと。相談に乗ってくれる近所のバドミントンショップを教えてもらった。モチベーションを上げていく意図で道具を揃えていくのもよいと思う。

ストレッチ

水曜日にバドミントン をしたことによる筋肉痛が残っていた。腰や背中のあちこちが痛かった。あと右腕や右肩もバドミントンでラケットをたくさん振ったことによる影響で張りや硬さがみられた。運動した張りをストレッチでほぐすようなサイクルになれば健康にもよさそうにみえる。今日の開脚幅も開始前149cmで、ストレッチ後153cmだった。

カフーツさん訪問

ストレッチを終えてからビールとおつまみをもって久しぶりにカフーツさんへ行ってきた。先週末にだらだらしてしまったからその反省も踏まえて出掛けることにした。ちょうどバドミントンのイベントをよく手伝ってくれている方がいて、あちこち友だち探しをしているようにみえるのでその一つとしてカフーツさんを紹介していて 以前にもキャンプ飯部 に参加していた。知っている人がいないとなかなか参加しにくいと伺っていたので一緒に参加してきた。しかし、参加者内で女性1人なってしまって、これはこれで居心地が悪そうにもみえた。他に女性の参加者が何人かいそうなカフーツさんのイベントを紹介した方がよかったなと反省した。

書店というビジネスの在り方について、いとうさんと議論していて、この本を読めと 取り戻す旅 という本を貸してくれた。本当は自分で買ってよいのだけど、なんとなくそのまま借りてみた。読んで内容がよかったら買ってみようと思う。本書では Culti Pay(カルチペイ) という取り組みをしていて みんなの銀行 を介して著者に投げ銭のようなこともできるという。新しい価値観に触れるという意図でも読み終えた後でやってみようと思う。

連休の初日

昨日も2時頃までコードを書いていて帰って寝たらお昼ぐらいまで寝ていた。ストレッチ終えてからコードを書こうと思っていたものの、モチベーションがあがらなくてだらだらしていた気がする。

ストレッチ

今週もデスクワークの時間が長かったせいか、軽く腰の張りを感じた。トレーナーさんからも運動不足からカラダの硬さがみえるといった指摘があった。先週はレビューの時間が多くてあまり時間を時間を取れなくて業務があまり進捗しなかった。そのストレスもあってなのか、また生活の余裕がなくなってきた。今日の開脚幅も開始前149cmで、ストレッチ後153cmだった。

集中力の正体

昨日は20時半頃にお仕事を終えて帰った。スーパーで買いものして、家に帰って晩ご飯を作って食べて、休んだらオフィスへ戻るつもりがそのまま寝てしまった。

メッセージ作成

年一ゲストとして出演している terapyon channel100回記念公開収録 があった。いつもお世話になっているので私は参加できないがカンパ枠で応援していた。昨日てらださんから音声メッセージを作ってほしいと依頼され、本当は昨日の夜に作ろうと思っていたものの、疲れて寝てしまったので朝起きてから慌ててオフィスへ行って作成した。ubuntu の apt でインストールできるツールとして audacity を使って録音した。簡単に使えた。お祝いのメッセージを文章に書き出して、マイクテストも含めて最終的には7回撮り直した。文章を書いてから、話してみると、流れが悪かったり、語呂が悪かったり、途中で詰まったり、かんでしまったりと、なにか気になるところをみつけて、文章を推敲して録音しながら1時間ほどやってた。録音して聞き直すと、いかに自分の話し方が下手であるかがよくわかる。話し方を練習しないとうまくならないのだろうな。

みなとのもりの運動

前回の所感 。14時頃に作業を終えてストレッチまで1時間ほど時間が空いた。ふと運動してからストレッチへ行くとよさそうだと思い立ってジョギングと縄跳びをしてきた。前回が7月24日なので1ヶ月半ほど運動していなかった。1kmほどジョギングしてから縄跳びを15分間した。以前と比較したら軽めに流したにも関わらず、久しぶりに運動したら体力が落ちていてかなりバテた。習慣的に運動していないとすぐに衰える。久しぶりに運動できたので、また再開するきっかけになるかもしれない。

ストレッチ

今日の開脚幅も開始前148cmで、ストレッチ後152cmとあまり数値は出なかった。直前に運動して行ったのでよく伸びるかな?と予測したものの、測ってみるとそうでもなかった。それでも運動した後にストレッチを受けるのはカラダによさそうにも思える。ここ1ヶ月半ほど運動できていないものの、体重は67kg台を維持していて体脂肪率や筋肉量はあまり変わっていない。トレーナーさんとそういう話をしていたら、筋肉は落ちにくくつきにくいから1ヶ月ではそんなもんとのこと。

プログラミングの集中力と生産性への考察

ストレッチを受けているときにトレーナーさんと話していて思うことがあったのでまとめておく。いまの開発フェーズは開発者としてプロジェクトに参加している。平均すると1日10時間ぐらいお仕事していて、早く帰る日もあるから遅い日は日付が変わるぐらいまではコードを書いていることがある。家に帰ると休んでしまうからオフィスで晩ご飯を食べることも多い。なぜプログラミングに集中していると運動ができないのか?を考察してみた。

  • 他の余分なことを排除すると集中力が増す

いまやっている開発のお仕事は1日で完了するような簡単な開発ではない。1年半開発しているので残っている課題は厄介で複雑な問題への対応であることが多い。新規機能を追加するときも既存機能や仕様や依存関係を考慮しないといけない。そうすると2-3日かけて課題を解決することが多い。そのときに他の余分なことを排除した方が脳のリソースを課題解決に割り当てられる。通勤しているときも、寝ているときも、ご飯を食べているときも取り組んでいる課題のことを四六時中考えている。他のことに脳のリソースを割くと課題解決の品質が下がる可能性が高い。ずっと考え続けることが複雑な問題の課題解決に重要となる。

  • システム開発とはタイムアタック競技である

システム開発のプロジェクトマネジメントにおいてもっとも重要な概念はタイムボックスだと私は考えている。適度な期間 (うちは2週間) を設け、モノゴトに取り組む最初と最後を作ること。認知心理学の研究からも記憶の仕組みからも期間の最初と最後がもっとも学習効果が高いことを示唆している。このことは私の経験則においてもシステム開発で当てはまる。作業期間が適切でないと人間はだらだらしてしまう (パーキンソンの法則) 。プログラミングにおいて動くのは当たり前で、動いた上でいかに品質をあげられるかが腕の見せ所になる。エラー処理を適切に制御できているか、他人がコードを読んでも理解しやすく保守しやすいか、将来の拡張性を考慮して設計されているか、など品質をよくするための取り組みには答えがない。仕事ができる・できないを分ける行動の1つとして、答えのない問いにどれだけ準備できるか、考え続けられるかと言い換えられるかもしれない。答えがないからいくらでも品質をあげるための施策がある。しかし、現実の業務には期限があるため、期限内に最善の品質を目指すことになる。そのため、タイムボックスでシステム開発をマネジメントする限り、いつもタイムアタック競技をしているのと同義になるから時間が足りない。

プログラミングはいつも妥協を強いられる。完璧で最高のシステムなどありえない。その時々で開発途中における最善の動くものをスナップショットとしてバージョン管理しているに過ぎない。この妥協するレベルが私にとってはマネージャーと開発者という役割で大きく異なるのだろうと思う。マネージャーとしての遊撃なら先送りできても、開発者としては多少の負荷があっても解決してしまう。自身の基準を満たす働き方に違いがあるのではないかと思う。言語化してみると、この考え方はプログラミングに限らず、そのときに取り組む対象によって何にでも応用できそうに思う。

その後の台風の影響

台風の影響で昨日も今日も終日、新幹線は取りやめになっていた。木曜日に帰ってこれた ことには大きな意味があった。本当に助かった。

ストレッチ

今日の開脚幅も開始前149cmで、ストレッチ後156cmと普段通りの数値だった。運動できていないので筋肉痛もなく、デスクワークの疲労ぐらいしかない。いつも通りトレーナーさんと雑談して硬くなったカラダをほぐしてもらう感じだった。今週は出張していたのと、出張中の業務時間も普段より少なかったのでとくに疲労がたまっているわけでもなかった。運動せず筋肉痛もなくストレッチを受けるともったいないような気分にもなってきた。いまの開発フェーズが終わったらまた運動を再開できるかなぁ。

成就しない結末への期待

今期のアニメで 逃げ上手の若君 を見始めた。最初は「ながら」でみていたせいか、あまりぱっとしなかったものの、改めてちゃんと数話を見返したらおもしろい作品だと思えた。もともと私は歴史漫画が好きなので歴史ジャンルというだけでもみてしまう。著者の 松井優征 さんの作品は過去に「暗殺教室」を読んだこともあって好きな漫画家の1人でもある。したがって、私はもともとこの作品を知っていたし、関心をもっていた。いままで読んでいなかっただけ。主人公は 北条時行 という、室町幕府が成立する時代の、鎌倉幕府最後の北条家の跡継ぎになる。足利尊氏 は歴史の授業で習うが、北条時行を私は覚えていないから習わなかったのかもしれない。歴史の影というのか、この作品は敗者を描く作品になる。

余談だが、神戸駅のすぐ近くに 湊川神社 がある。逃げ上手の若君の作品内でも出てくる 湊川の戦い の、あの「湊川」であり、神戸という地元応援の文脈で 楠木正成 も応援している。楠木正成は没後から江戸時代まで知名度は低かったが、なぜか徳川光圀公に評価され、その後、幕末の維新志士から崇敬の対象となり、歴史上の時間が経ってから知名度があがった稀有な武将でもある。そういう背景もあってなのか、逃げ上手の若君の作品内でも特異な武将として描かれていて、史実から湊川の戦いで足利尊氏に負けてしまうのだけれども、それでも格好よく戦って、その智謀を発揮している。この作品を読んでさらに楠木正成への関心が出てきた。

歴史漫画は結果がわかっているから予定調和で読み進める。主人公が勝者であれば安心して読めるが、この作品は敗者なので結末は悲劇となる。ある意味、敗者だからあまり史実の資料が残っていなくて創造性を発揮できるところもあるだろう。そこが漫画家の腕の見せ所だと思う。北条時行による「中先代の乱」があったから南北朝が生まれ、その後の室町幕府への影響も大きかったように、この作品内では描かれている。敗者も歴史を作っていく上での重要な役割を担っているという表現になっていて歴史の背景を想像して楽しみながら読める作品になっていると思う。

multipart/form-data リクエストの扱い

9時に起きて2度寝して10時頃に起きたものの、お昼までだらだらしていた。それからオフィスへ行って溜まっていた日記をまとめて書いて、逃げ上手の若君 をみながら作業をしていた。来週は出張の週だから事前にやっておくことがいくつかある。

ストレッチ

先週は実家へ帰っていた ために2週間ぶりのストレッチになる。とはいっても、いまは運動をしているので筋肉痛もない。しかし、机に向かってデスクワークする時間が増えている分の負荷がかかっている。トレーナーさんからも腰から背中にかけて硬いと指摘された。今日は硬くなっているカラダ全体をほぐしてもらった感じだった。おかげで今後も体調よく机に向かえる。今日の開脚幅は開始前149cmで、ストレッチ後155cmと普段通りの数値だった。

multipart/form-data リクエストを扱う結合テスト

昨日の夜に汎用のファイル操作の api を実装した。今日はその結合テストを追加してマージリクエストを作成した。multipart/form-data のリクエストを作るのはちょっと面倒くさい。go のライブラリのテストコードや stackoverflow のサンプルコードなどを調べながら自分で実装した。次のような multipart/form-data リクエストを扱う writer や buffer を生成するためのユーティリティを作る。一通りの結合テストを実装するのに3時間ほどかかった。

func createMultiPartFormData(
	fileBody []byte, formField map[string]string,
) (*multipart.Writer, *bytes.Buffer, error) {
	b := new(bytes.Buffer)
	mw := multipart.NewWriter(b)
	for k, v := range formField {
		fw, err := mw.CreateFormField(k)
		if err != nil {
			return nil, b, err
		}
		if _, err := fw.Write([]byte(v)); err != nil {
			return nil, b, err
		}
	}
	fw, err := mw.CreateFormFile("file", "path/to/file")
	if err != nil {
		return nil, b, err
	}
	if _, err := fw.Write(fileBody); err != nil {
		return nil, b, err
	}
	if err := mw.Close(); err != nil {
		return nil, b, err
	}
	return mw, b, nil
}

このユーティリティを使って http リクエストのテストデータを生成するのは次のようなコードになる。

u := &url.URL{
	Scheme: "http",
	Host:   "localhost",
	Path:   path,
}
mw, body, err := createMultiPartFormData(fileBody, formField)
if err != nil {
	return nil, fmt.Errorf("failed to create multipart form data: %s", err)
}
req, err := http.NewRequest(http.MethodPost, u.String(), body)
if err != nil {
	return nil, fmt.Errorf("http create new request error. err: %s", err)
}
req.Header.Set("Content-Type", mw.FormDataContentType())

あと結合テストでファイルをアップロードすると実際にファイルシステム上に保存されてしまうのでそれらを削除するには Cleanup を使うと簡単に後始末できた。

func TestFileUpload(t *testing.T) {
    ...
	t.Cleanup(func() {
		if err := os.RemoveAll(file.FilesDir); err != nil {
			t.Errorf("failed to remove files directory: %s", err)
			return
		}
	})
    ...
}

寝ている間に再設計

昨日のもやもやは寝ている間に整理され、今日は標準的な開発者としての過ごし方になった感じがする。

マネージャーとの 1on1

これまでは私がマネージャーとして 1on1 をしてきたが、今後は交代したメンバーがマネージャーを務める。この開発フェーズでは私は開発者 (メンバー) として 1on1 をしてもらうといった感じかな。自分が開発者側だと思うと、いま私が取り組んでいることの話しをしやすかったりした。立場によって 1on1 のやり方は変わることを実感した。マネージャーはメンバーの話しを聞く方に注力したり、プロジェクト全体の話しをしがちになる。開発者として臨むと、自分の抱えている issue に集中して話せるといった違いがあった。

CPAP の中断

夜に睡眠外来へ行ってきた。以前に CPAP 装置 を借りて3ヶ月ぐらいやっていたものの、ここ2ヶ月ほどやらなくなってしまっていた。もともとは体脂肪コントロールの疲労回復のために始めたものだった。体脂肪コントロールがうまくいって目標達成したことで睡眠改善を行う目的もなくなってしまって関心を失ってしまった。借りているだけで毎月5千円ほどかかるので中断して機器を返却することにした。旅行のときなど、一時的に借りられないかを聞いてみたら、それは不可とのこと。また再開したくなったらいつでも言えばよいとのこと。

ツールの再設計

昨日の続き 。睡眠外来から帰ってきて、晩ごはん食べて、軽く飲みながら24時過ぎまでコードを書いていた。今日もまる一日ツールの再設計をしていた。昨日のノーアイディアな状況から少しずつ好転していって、ある処理で歯車が噛み合ってからはいつも通り着実に進捗していく様がみられた。意図的にやっていることではあるけど、課題について考えながら一晩寝ると、寝ている間に無意識に刷り込まれて脳が考えてくれる。それで徐々によい設計が現れてくるようになって明確な実装に落ち着いたのではないかと推測する。今日はよい感じに集中できた。

バドミントンという健康的な趣味

昨日、大きな仕様変更を入れた内容の、API ドキュメントを書き直していた。大きな変更をしたのでドキュメントの修正量も大きくて半日以上かかった。こういった効率化しにくい、地道にコツコツやらないといけない作業が忙しいときに降りかかるのがつらい。誰でもそうだとは思うけど。元来、私は積み重ねをしていく地道な作業は得意な方だと考えている。しかし、いまはリーダーとして他のメンバーを引っ張っていく立場にあるため、時間のかかる作業をしていると足踏みしているような罪悪感を感じてしまう。一方でそういった実務をちゃんとやることをメンバーにみせることも大事かなと思って、面倒な作業を自分でやるときもある。ケースバイケース。

体育館でバドミントン

前回の所感 。19時からバドミントンへ行ってきた。19時の時点では3人しかいなかったものの、後半にながいさんも来られて、最終的な参加者数は4人だった。ここ1-2週間は椅子にすわってデスクワークばかりやっていて、ほとんど運動できていないのでカラダを動かすのにちょうどよい機会になった。今回も line のオープンチャット 経由で加古川から初参加で来てくれた方がいた。三宮は職場の通勤途中になるらしく、それもあって立ち寄ってくれたようだ。その方も私と同じ世代で初心者からバドミントンを始めて1年ほどの経験らしい。毎週、地元の体育館で練習していると話されていた。うちらに比べればずっと上手だった。うちらはみんな初心者だから適当にやってきたのだけど、(うちらと比べて) 熟練者が来てくれたのでバドミントンの練習方法もいろいろ教えてもらった。その方は次の動画をみて勉強していると話されていた。私も後でみてみようと思う。

バドミントン経験1年の方の振る舞いをみていて、バドミントンは趣味でずっと続けていくのによいスポーツだなと思えた。運動にもなるし、カラダを痛めるといった健康を害することもなさそうだし、お金もかからないし、老若男女、初心者誰でもできるコミュニティ向けのスポーツでもある。教える方のスキルが高いほど、初心者の練習相手として、初めてイベントに来られた方がバドミントンに関心をもつ手助けもできそうに思えた。いまのお仕事の開発が一区切りつけば、有料のバドミントン教室へ通ってみて基礎を教えてもらいに行こうかなと思い始めた。

なにもしていない一日

お昼までゆっくりして午後からストレッチへ行ってオフィスで作業していた。本当は夕方から実家へ帰ろうと思っていたものの、作業がまったく捗らなくて翌日へ持ち越した。

ストレッチ

今週は運動も料理も何もせずひたすらコードを書いていた。どこも筋肉痛はなくなっているものの、腰に張りがあったりしたのは椅子に座っている時間が長かったからだと思う。今日の開脚幅は開始前151cmで、ストレッチ後156cmとこれまでよりは数値がよかった。筋肉痛だとカラダが硬くなってしまったりしているみたい。

mongodb も一応は外部結合できる

今日は出張中にたまっていた日記をまとめて書いていた。昨日筋トレしたから運動はおやすみ。

mongodb における外部結合

出張中のふりかえりやプロジェクトマネジメントの合間に mongodb の $lookup (aggregation) 機能を調査していた。一言で言えば、rdbms で言うところの外部結合 (join) を mongodb で実現する機能と言える。しかし、aggregation の機能として実装されていることから rdbms の外部結合とはパフォーマンスの側面で大きく違うのでは?と推測する。mongodb のような kvs では基本的に外部結合のようなことは行わず、結合済みのコレクションを定義するやり方がプラクティスとされる。一方で整合性を保証するには外部結合は有効なデザインパターンの1つなので使いたい場面があってもおかしくない。実際に mongodb に $lookup が実装されているのだから、そのニーズは大きいのだと思われる。

ちょうどいまやっている開発でその要件があったので mongo-go-driver の次のチュートリアルをみながら実装してみた。

例えば、次のような2つのコレクションがある。

type Group struct {
	ID          string      `bson:"_id"`
	Name        string      `bson:"name"`
	UpdatedAt   time.Time   `bson:"updatedAt"`
}

type MyData struct {
	ID           string    `bson:"_id"`
	GroupID      string    `bson:"groupID"`
	RegisteredAt time.Time `bson:"registeredAt"`
}

MyData の GroupID フィールドが Group コレクションの ID を保持して外部参照している。MyData コレクションに対する aggregate に渡すパラメーターとして pipeline を渡す。

myPipeline = mongo.Pipeline{
	{{
		Key: "$lookup", Value: bson.D{
			{Key: "from", Value: "group"},
			{Key: "localField", Value: "groupID"},
			{Key: "foreignField", Value: "_id"},
			{Key: "as", Value: "foreignGroup"},
		},
	}},
	{{
		Key: "$unwind", Value: bson.D{
			{Key: "path", Value: "$foreignGroup"},
			{Key: "preserveNullAndEmptyArrays", Value: false},
		},
	}},
}

$lookup の操作の後に $unwind で配列を flatten する処理がセットになる。result set にマッピングするためには flatten が必要になるのだと推測する。aggregate() を呼び出すと cursor が返ってきて、その cursor に外部結合される値の配列を渡すことで result set を取得できる。デバッグはややこしいし、コード上もちょっとわかりにくいけど、これは mongodb のお作法だと割り切ってユーティリティ化してしまえばよいものだと思う。

type joinedMyData struct {
	ID           string    `bson:"_id"`
	Group        Group     `bson:"foreignGroup"`
	RegisteredAt time.Time `bson:"registeredAt"`
}
...

cursor, err := collection.Aggregate(ctx, myPipeline)
if err != nil {
	return nil, err
}
var joined []joinedMember
if err = cursor.All(ctx, &joined); err != nil {
	return nil, err
}

また時間があるときにある程度のデータ量でどのぐらいの負荷に対してパフォーマンスが出るのかを測ってみたい。

ストレッチ

昨日1週間ぶりに筋トレをしたせいか、今朝から筋肉痛になっていてカラダが痛い。その影響もあって今日の開脚幅は開始前146cmで、ストレッチ後152cmとカラダが硬かった。足も腰も肩周りも全身にわたって軽い筋肉痛だった。それだけよい感じの負荷をかけて筋トレができていたと言えるのかもしれない。あちこち筋肉痛はあったものの、ストレッチを受けていての辛さのようなものは感じなかった。ちょうどよい感じにほぐされているような印象を受けた。もしかしたらトレーナーさんが気を遣っていつもよりは弱めにストレッチしてくれたのかもしれない。トレーナーさんが立候補していた店長選挙は落選してしまったらしい。もし店長になったらよそのお店へ転勤になって担当者が変わってしまうのかなとも思っていた。トレーナーさんは私が通っているお店の副店長を務める方向で調整しているらしい。待遇をあげていくにはキャリアアップをしていかないといけないといった背景もあるようにみえる。