Posts for: #Design

よく働きよく動く

今日の運動は腕立て,スクワット,縄跳び(両足跳),散歩をした。統計を 運動の記録 にまとめる。

ou エントリーの更新対応

ここ2週間ほどずっと、お仕事のある機能開発で テンパった開発状況 でやってきたものがようやく終わった。私は自社の経営だったり、プロジェクトのマネージャーだったりで、普通の開発メンバーのような集中した開発を時間的にできないものの、それでも私が1つの機能に2週間もかける開発はそうそうない。想定以上にこの対応のために、扱う LDAP エントリーのデータ定義や既存システムの実装変更を余儀なくされた。逆に言えば、既存の実装にそういった考慮が当初の設計に足りなかったと言える。この改修において ID 連携におけるノウハウをメンバーと共有したとも言える。

運用視点からは出来て当然の、しかし、開発視点からは厄介な仕様変更の開発を完了できた。いまの時点では完璧に作ったので将来的な拡張も含めて、さまざまな要件に対応できる設計になったと思う。自画自賛だが、時間をかけた分のよいものができたと思う。

みなとのもりの運動

今週の前半は雨降りだったり、雨が断続的に降ったりやんだりでお出掛けできなかった。お仕事も一区切りついた開放感と久しぶりによい天気だったのもあって みなとのもり公園 へ行って縄跳びしてきた。運動できない日々が続いて体力を回復していたせいか、15分間のワークアウトで過去最高の 1113 回となった。前回よりも大きく回数が増えたので、もしかしたら100ほど計測ミスがあるのかもしれない。いまの目標としては15分間で最低800回跳ぶことを想定している。跳んでいるうちにカラダが慣れてきて、ミスしなくなったり、フロー状態に入って速く巧く跳べて回数が増えたりする。

縄跳びの前後にストレッチをできるよう、大きめのレジャーシートも買った。100円ショップなどで売っているレジャーシートに比べたら少し厚手になる。折り畳んで持ち運びできるのがいいなと思って購入した。公園へ持っていくのに便利。1人なら完全に寝転がって広々とストレッチできる。よいと思う。

テンパった開発状況

今日の運動は腹筋ローラー,スクワットをした。統計を 運動の記録 にまとめる。

開発がなかなか進まない

本当は次の開発課題に着手しないといけないところだが、先週からずっと新機能のための、既存コードのリファクタリングに時間を費やしている。データ構造を変えたり、主キーを変えたりしているので影響範囲が大きくて、テストコードもあちこち修正しないといけなくて時間がかかる。結合テストの実行そのものにも時間がかかるし。

なかなか開発がテンパっているものの、今日でようやく一通りのリファクタリングを完了して、意図していた新機能のための web api が動くところまで確認できた。なんというか、新機能を作るために既存コードの改善に8割の時間を費やした感じ。おかげで新機能はなにも開発していないのに勝手に動いた (違) ような気持ちになった。今後、同様に個別データの拡張や新たなデータ追加のときは既存データに影響を与えず、独立して追加しやすい設計となっている。将来的に私がいなくなった後に拡張するときにこの設計は役に立つだろうと思う。

awesome-go へ道

昨日の続き 。contribution guidelines を読んでいて最低限やれと書いてあることの1つに Go Report Card report を作れと書いてあった。これは静的解析したスコアのようなものが表示される。すべて100%が表示されるようにした。

カバレッジも測れとあったので github actions の workflow ファイル を設定して計測してみた。63.9 % といまいちだった。コアなところしかテスト書いてないからかな。ユーティリティや cli のテストもちゃんと書いたら 80-90% ぐらいはいくのかな?また後日、時間のあるときにやってみる。余談だけど、久しぶりに github actions を触ったらもうワークフローファイルの文法とか覚えてなくてずっと触ってないとすぐ忘れるとか思ったりもした。

if the library/program is testable, then coverage should be >= 80% for non-data-related packages and >=90% for data-related packages. (Note: the tests will be reviewed too. We will check your coverage manually if your package’s coverage is just a benchmark result);

Quality standards

主キーの特性

今日の運動は腹筋ローラー,腕立て,スクワット,縄跳び(両足跳)をした。統計を 運動の記録 にまとめる。

コレクションデータの再定義

ある mongodb のコレクションのデータ定義で _id に ldap の dn の値を使っていた。dn は一意な値なので主キーとして使ってもよさそうに思えたが、ここで運用上 dn の値が変更されるケースがいくつかあることがわかってきた。例えば、dn に姓名が含まれる場合、結婚して姓名が変わると dn の値が変わることはありえる。他にも dn に含まれる ou の値が現実の組織名を表している場合、組織変更によって ou の値が変わったときに dn の値も連動して変わってしまう。一意な値というだけでデータベースの主キーにするのはよくないということがわかってきた。主キーは一意な値、且つ immutable が望ましい。

たとえば mongodb では _id を主キーとして使う。mongodb は主キーの値を変更することはできなくて実装上は delete & insert になる。

delete & insert の運用上の問題は更新時にトランザクションを使わないといけないため、パフォーマンスが悪い。さらに id 連携という業務に特化して言うと、たとえば、姓名の変更は名前が変わったというだけでその人が退職したわけではない。これをシステム上 delete & insert で扱うと、古いユーザーデータを削除して、新規にユーザーデータを作成するといった振る舞いになってしまう。そうすると、古いユーザーがもっていた権限やデータなどを移行しないといけないわけだが、それらをすべて自動化できるか?という難しい課題も積み重なってしまう。本質的に rename を delete & insert で扱うことそのものが誤っているのだ。

メンバーと相談して _id に uuid を発行して dn はフィールドに unique 制約を課して保持するよう設計を変更することに決めた。コレクションのデータ定義の主キー変更なのであちこち修正してテストコードも修正しないといけない。一意な値、且つ immutable な値のみを主キーとして使うのが今回の学びとなった。私自身、初期の設計に関わったときにこのことに気付かなかったから、これは私のレビューの失敗・見逃しでもある。

go の generics に慣れてきた

今日の運動は腹筋ローラー,スクワット,縄跳び(両足跳)をした。統計を 運動の記録 にまとめる。

go の generics の扱い

今日はほぼまる一日コードを書いていた。あるデータ型のリファクタリングをしていて次のような constraint とメソッドの組み合わせで型チェックできることを理解した。generics 使って1年以上開発しているので感覚的にも慣れてきた。User と Group のどちらかを受け取る constraint とそのデータストアの定義は次のようになる。

type UserOrGroup interface {
	User | Group
	GetPrimaryID() string
}

type UserOrGroupStore[E UserOrGroup] interface {
	generic.Store[E]
	FindByPrimaryID(ctx context.Context, primaryID string) (*E, error)
}

この型定義を使う関数では次のようになる。

func find[
	E entry.UserOrGroup,
](
	ctx context.Context, store entry.UserOrGroupStore[E], primaryID string,
) (*E, error) {
	e, err := store.FindByPrimaryID(ctx, primaryID)
	if err != nil {
        ...
    }
	ee := *e
    // ee.PrimaryID はコンパイルが通らない
	_ = ee.GetPrimaryID() // 現時点ではメソッド呼び出しが必要
}

ここで UserOrGroup に GetPrimaryID() というメソッドを追加している。本来は両方の構造体に保持するメンバー属性ではあるものの、現時点の go のコンパイラはメンバー属性を正しくチェックできない。そのため、メソッドにして generics の型チェックが正しく通るようにしないといけない。go の issue にも上がっているのでいずれはメンバー属性を解決できるようになるのだろうと推測する。

ordered map という適当な粒度の課題

1時に寝て4時に起きて CPAP 治療忘れて寝ていたことに気付いて、装着してまた寝て6時半に起きた。

今日の運動は背筋をした。統計を 運動の記録 にまとめる。

orderedmap ライブラリ

json のオブジェクトの属性を意図した順番に並び替えたいという要件があって 適当なライブラリをみつけられなくて 最終的には自分で実装した。そのときに参考にしたモジュールではネストした配列やオブジェクトの順番を維持できないことに気付いて、どうせ実装するなら json の marshal/unmarshal の処理を完璧に実装しようと思って、再度フルスクラッチで作り直した。要は python の OrderedDict のようなものの go 版になる。

orderedmap というキーワードで検索するといくつもオレオレの実装がみつかる。次の3つを参考にしながら、私も自分の思う「ぼくのかんがえたさいきょうの orderedmap」 を作ってみた。

実際に作ったものが次になる。

インストール

$ go get -u github.com/kazamori/orderedmap

go のモジュールは GOPROXY protocol を介してプロキシサーバーから取得される。デフォルトでは proxy.golang.org が設定されている。

$ go env | grep GOPROXY
GOPROXY='https://proxy.golang.org,direct'

プロキシサーバーではモジュールがキャッシュされているため、利用する側でリビジョンを更新しようとしても短い間隔だとすぐには反映されない。プロキシサーバーに存在しないモジュールのリビジョンを取得したい場合は GOPROXY の環境変数でダイレクトモードに変更する。

$ GOPROXY=direct go get -u github.com/kazamori/orderedmap

generics 対応して汎用の map を扱えるのがちょっとお気に入りなところ。他人が作ったライブラリを使うことはできるけど、プログラミング勉強として自分で実装してみるのもよい気はする。ちょうど kyoto.go のイベントがあってそのトークに orderedmap について話して来ようと思う。

キャンセルが続くような日

3時半に寝て7時前に起きた。昨日はコーディングに集中していた。

今日の運動は腹筋ローラー,腕立て,スクワット,散歩をした。統計を 運動の記録 にまとめる。

明石海峡大橋海上ウォークのキャンセル

明石海峡大橋海上ウォーク の当日。こみやさんが関東からわざわざ来るというので私も付き添いで参加することにしてした。朝起きて準備して元町駅から8時半頃の電車に乗って舞子駅へ向かう。途中で slack に一報したらこみやさんから今日は中止だよと連絡が入る。新長田駅で折り返して三ノ宮に返ってきた。当日6時に強風予報のため中止になっていたらしい。普通に晴れているのに。橋の上を歩くイベントは強風で当日中止とかになるんやということを学んだ。

雑談会のキャンセル

毎年行っているある大学の先生との雑談会を13日に予定していた。大阪のバーで飲むイベントだったのだけど、家族全員がコロナにかかってしまったという話しで周りへの感染予防のためには飲みに行くわけにはいかないという連絡がきた。それでお店の予約をキャンセルした。早めに連絡をいただいたのでキャンセル料を支払う必要はなかった。感謝。私も開発合宿と出張の移動疲れで疲労困憊になっているのでこれはこれでよかったのかもしれないと思えた。

ordered map の開発の続き

複雑なデータ構造のときに map (json で言えばオブジェクト) のキーの順序を保持できないことにもテストを書いていて気付いた。そこの部分も作り直さないといけないとデバッグしたり設計をやり直したりしていた。

昨日の続き

json を自前でパースしないといけないという判断を下し、json パーサーを探してみて ujson というパーサーを使ってみることにした。今日は ujson を使った json のデシリアライズの処理を設計したり実装したりして試行錯誤していた。こういうシンプルなライブラリは私のやりたいことを邪魔しないので好み。

ストレッチ

本当は午前中に明石海峡大橋海上ウォークへ行くつもりだったからストレッチは夜の時間帯に変更していた。先週は開発合宿でお休みしたので2週間ぶり。散歩する機会が多くなったせいか、右足の太ももが筋肉痛であることは自覚症状があった。今日の開脚幅は開始前150cmで、ストレッチ後155cmだった。トレーナーさんのストレッチを受けて、足は左右とも前も後ろもあちこち痛かった。トレーナーさんからもあちこち張りがあるという指摘があった。運動の成果というのか、散歩をたくさんするようになって足に負荷がかかっているのは間違いないようだ。こういうときこそプールを使うべきなんだけど、なぜか夜に予定が入りまくっていてなかなかスケジュール調整ができない。土曜日が一番時間の調整しやすいのにプールの制約によって利用できない。カラダが疲労していると脂肪燃焼の効率が悪くない。カラダを休めるのも必要なことかもしれない。

ordered map 開発のきっかけ

0時に寝て6時半に起きた。神戸に戻ってきてようやく落ち着けた。

今日の運動はスクワットをした。統計を 運動の記録 にまとめる。

ordered map の開発

金曜日は打ち合わせが何もない曜日の1つ。疲労困憊で神戸に戻ってきたので今日はずっとコーディングに集中していた。本当はお仕事終えてからプールへ行こうと思っていたものの、逆にコードを書くのに集中し過ぎて晩ご飯に一旦帰って食べた後も、もう一度オフィスに来て、さらに1時ぐらいまでコードを書いてた。

go の map をイテレートすると意図的にランダムに key-value を返す仕様になっている。これは開発者がキーの順序に依存した実装をしてしまって潜在的バグを混入させてしまう懸念を取り除くため。その設計思想は理解できるものの、go の map を json で返すときに ux の視点からキーの順序を保証したい場面がある。そんなときに ordered map のようなものが必要になる。go のコード内で ordered map を実装しているライブラリはいくつかあるものの、json のシリアライズ/デシリアライズも考慮してキーの順序を保証するライブラリはあまりみつけられなかった。それを考慮しているライブラリの1つに mapslice-json がある。しかし、このライブラリの実装はイケてなくて致命的なバグを1つみつけて PR を送ったものの、おそらく3年ぐらい保守されていない。あとジェネリクスを使うと使い勝手がよくなるからコードを書き換えたい。

結局このライブラリからアイディアだけもらって自分で再実装することにした。そして、array や map が入れ子になるような、複雑なデータ構造のときに map (json で言えばオブジェクト) のキーの順序を保持できないことにもテストを書いていて気付いた。そこの部分も作り直さないといけないとデバッグしたり設計をやり直したりしていた。これは会社の oss ライブラリとして作ってもよいかもしれない。

よい開発文化をもつチーム

今回は寝台列車であまり寝付けなかったのか、fitbit に睡眠時間が記録されていなかった。おそらく2-3時間は寝たと思う。

今日の運動は合宿明けと移動疲れがあるのでお休みにした。統計を 運動の記録 にまとめる。

会議の準備

この3日間で私が主催の打ち合わせが5つある。主題だからそのすべてに私が資料を作らないといけない。もちろん先週から準備はしていたものの、完全ではなく、週末には城崎温泉でいっぱいいぱいになっていて余裕がない状態のまま出張になってしまった。打ち合わせの成否はそれまでにかけた準備時間に比例する。私の持論だ。最低限このぐらいの資料や段取りを組んでやらないといけないという私なりの基準がある。今回はぎりぎりまで資料を作ったり、打ち合わせ内容を練ったりして自身の基準すら満たすのにとてもしんどかった。

定例会議

いつものマイルストーン単位の定例会議。

特定の path 配下の web api にミドルウェアで認証や認可を適用している。こうしておけば認証しなければいけない web api の認証設定を実装し忘れるということが絶対に起きない。一方で未認証の web api もある。/auth/login/status/ping といったものだ。これらは未認証で呼び出せるのでトップレベルの path をわけたい。そうすると、既存のトップレベルに設定してある /api/xxx という名前が論理的におかしい。web api は他にもあるのに認証を要するものだけ api というトップレベルの path を付けるのは奇妙に思えてくる。

/api/ping

チームで話し合ったり、私が思いついた最終結論としては1文字の path を設けることにした。ミドルウェアを適用したいという目的なので path さえあればよい。認証を要することを表す単語をつけると path が長くなってそれはそれで違和感を感じるし、開発者はタイプ量が増えることを嫌う。そこで一文字にしようと提案した。

/p/ping

permit, private, protected の意図で p という文字を使う。

3次開発の大きなふりかえり

事前に資料を作っておいた 開発の大きなふりかえり。2時間を使ってふりかえりを行う。前回の大きなふりかえり を経て、今回も若手のメンバーが大きく成長してくれて、その成長度合いが課題管理システムの統計からみてとれた。私がプロダクト開発に参加してチームを組んで1.5年経った。初期からのメンバー2人はどちらも十分に課題管理をうまくできるようになった。その結果、チームがよい開発文化を形成するようになった。

今回は新たに入りかけた若いメンバーはうまく立ち上がらなかったという反省があるだけで、その他のことについては開発全般うまくいっているし、プロダクトの品質も上がっているし、バックログの課題もたくさん自分たちで見つけられるようになってきた。私からみてもこのチームは十分によい開発チームに育ったと思う。マネージャーとしての私にとっての次の課題は途中からチームに参加するメンバーをいかに早く開発に馴染んでもらうか、よい開発文化を形成するようになってもらうかという取り組みになる。

スライドのあちこちに次の文言を埋め込んである。

ふりかえりなくして成長 (改善) なし

初期から課題管理に取り組んでいる2人のメンバーはどちらも成長が著しいし、ふりかえりの効果を実際の業務で体感してもらえていると思う。私自身も初めてのマネージャー経験、初めての課題管理をプロジェクトマネジメントとして導入するという経験、それらの PoC としての答えは出たと思う。間違いなく、課題管理は開発プロジェクトをよりよくするものだし、適切に課題管理すればプロダクトの品質も高くなっていく。今回のふりかえりは課題管理をビジネスにすることへの確信につながった。

致命的バグをみつけた

2時頃に寝て5時過ぎに起きた。お風呂に入るときに fitbit を外して、その後付けるの忘れて寝てしまったから睡眠時間を計測できなかった。

今日の運動はレッグレイズ(椅子),腹筋ローラー,腕立て,スクワットをした。統計を 運動の記録 にまとめる。

agent の致命的なバグ

先週から QA テストをしていて agent の致命的なバグに気付いた。もともとあった java 製の agent から私が設計して作り直した go 製の agent になる。ldap エントリーの更新リクエストのテストツール を作ったことでシビアなタイミングによるバグを検出できた。

ツールを使ってテストしていて、成功するはずのリクエストが失敗して、ログを調査しながらデバッグしていた。ldap エントリーを扱う難しさの1つに、ldap サーバーはエントリー間の依存関係やデータの整合性といったものを検証しない。そういった用途はアプリケーションの役割であって、ldap プロトコルはあくまで id を管理することに特化したものという役割分担になっているのだと推測する。そうすると、(open) ldap サーバーへ登録できたエントリーが次の agent や api サーバーといったアプリケーションのレイヤーでエラーになることがある。このとき、ldap サーバーではエラーが発生していないため、直接的なエラーを検知することができなくて、デバッグや調査に時間がかかる。

agent の実装として、ユーザーエントリのストリームとグループエントリーのストリームの2つに分割して、非同期にそれぞれのエントリーを id 連携する設計にしていた。というのは、ldap エントリーにはユーザーやグループといった概念は原則として存在しない。そのエントリーがユーザーなのか、グループなのかはアプリケーションが判断している。アプリケーションの用途としてはこの2つを明確にわけないと不便なことから、ワークアラウンドもしくは実務的な解決策として検索するときのフィルターと base dn で管理するようにしていた。そして、これらをそれぞれ別のストリームとして扱うよう、私が設計していた。このことがタイミングによってはユーザーエントリーとグループエントリーに依存関係がある場合、データの整合性を保証できないことに気付いた。なぜならば、ユーザーエントリーとグループエントリーそれぞれ非同期/並行に処理されてしまうから。

結論としては、ldap サーバーからエントリーの更新の順序を保証するには1つのストリームを subscribe しないといけない。そして、ストリームから取り出したエントリーがユーザーなのか、グループなのかはアプリケーションが判別しないといけない。テストツールを作ったことでシビアなバグも検出できた。

定額減税

定額減税 特設サイト が公開されたらしいというニュースをあちこちでみつける。従業員の税金が安くなるので経営者としての私がなにかしないといけないと思っているけれども、まだ何をしていいのかよくわかっていない。時間をみつけて調べないといけない。税制が変わるとこういった事務手続きが突発的に入ってくるのがマイクロ法人の面倒なところ。

ホットクックのレシピを upnote で書く

2時半に寝て5時過ぎに起きた。それから二度寝して7時に起きた。

今日の運動はレッグレイズ(椅子),腹筋ローラー,腕立て,散歩をした。統計を 運動の記録 にまとめる。

トランクルームの契約

家電を購入すると大きな箱が付いてきて物理的にその置き場所がない。箱を捨てるという戦略もあるが、オリジナルの箱があると引っ越しや売買/処分するときに便利なのでできれば残しておきたい。これまでデスクトップマシンの箱やオフィス備え付けの椅子などをマンションの部屋に保管したりしていたけど、家電の箱が増えてくると邪魔になってきて、トランクルームを借りることにした。面倒なのであまり調べていないが、スペラボ というサービスの屋内型トランクルームをレンタルすることにした。0.7畳で6,450円/月(税込)になる。会社の経費だしこのぐらいの金額ならいいかと思って、朝から内見に行って問題なさそうなので即決した。

ホットクックレシピの公開

ホットクックのレシピをどこかに整理したい。スマホ上でも調理しながら簡単に確認したいとなると web よりもアプリの方がよい。そこで evernote から移行した upnote に書くことにした。実際に調理してみて、デスクトップマシンでレシピを編集・整理して、写真はスマホアプリからアップロードするといった使い方ができる。View shared notes によると、ノート単位で web 公開もできる。試しに次のレシピを公開してみた。ノートブック単位で公開設定して一覧ページがあるともっとよいが、その機能はないみたい。公開リンクを作成する一手間はあるけれど、そんなにレシピノートを書くわけでもないから気にはならない。

ホットクック調理は材料入れてボタン押したら終わりではないか?と思うかもしれない。いや、そうでもないようだ。たしかに材料を内鍋に入れてボタン押したら人間ができることは何もない。だからこそ、ボタンを押す前の過程が大事になってくる。どんな切り方をするのか、素材のサイズはどうか、初期配置はどうか。例えば、豚ロース肉の生姜焼き用を買ってきて、適当に切って3枚4枚重なった状態で投入したらそのままの状態で出来上がった。かき混ぜ棒があるからうまいこと豚肉もバラけるだろうと期待したが、ぴったりくっついているようなお肉をバラかすほどのパワーはないようだ。人間が最初からバラかした状態で内鍋に投入すると、出来上がりのときに豚肉のかたまりがなくなってよいと思う。

あと気付いたこととして、野菜もお肉も素材を少し小さめに切った方がおいしいように感じる。というのは、ホットクックは圧力鍋ほどの火力で調理しない。圧力鍋に慣れていると、少し大きめに切っても原形がなくなって溶けてしまったり、出来上がり時点で原形があっても混ぜたりしているうちに角がとれて、どんどん小さくなっていく。小さくならなくても口の中でとろけるので大きいままでも問題ない。相対的にホットクックはそこまでの火力はないから、小さめで味が染み込むような出来上がりになるため、小さめに切っても原形は保ったままで溶けてなくなってしまうことはない。これは良い悪いではなくて、それぞれの製品の特徴と言えるだろう。ホットクック調理は素材を小さめに切るというのが、いまところ、私が作ったレシピではうまくいっている。ホットクックでは、小さく切った複数の素材をほお張って食べるのがおいしい。

go-ldap への context 導入の考察

go-ldap の issue は subscribe しているので、たまたま initial cut of context support #406 の draft pr のコメントに気付いた。過去に context を導入しようとして途中で断念した残骸みたいな pr になっている。いまの go の api は context を受け取るのが当たり前になっているので確かにほしいというのは理解できる。

代わりに私がやってみようかとソースコードを読んでみた。オリジナルの draft pr は client の interface に WithContext なメソッドを追加しようというもの。go の context の扱いとしてもっとも基本的なもの。それでもよいけれど、net/http の実装はどうなっているのかを調べていたら Request 構造体のメンバーとして context を保持していることがわかった。このやり方は原則のルールに反するものだけど、context を状態として扱わず、限定的な用途にのみ使っている。これは既存の interface を変えずに context 導入をしようという意図があると推測する。この考え方でいくと、go-ldap の Request 構造体に context を保持するように変更する方が既存の API の変更を少なくして net/http の Request も同様にやっているからと説明もしやすいように思えた。

type Request struct {
...
	// ctx is either the client or server context. It should only
	// be modified via copying the whole Request using Clone or WithContext.
	// It is unexported to prevent people from using Context wrong
	// and mutating the contexts held by callers of the same request.
	ctx context.Context
...
}

今日のところは go-ldap と net/http のソースコードを読んで設計をしていた。また明日余裕があったらサンプル実装してみる。

野菜スープ改

2時前に寝て6時半に起きた。たぶん夜中には起きていない。夜は野菜スープしか食べてないから安眠できたのかもしれない。

今日の筋トレはレッグレイズ(椅子):20x1,スクワット:20x1,縄跳び(両足跳:50x2,駆け足跳び:10x3)をした。今日もお昼休みに公園へ行って縄跳びした。昨日縄跳びしたせいだと思うが跳ぶと膝の後ろの筋が痛い。普段やらないことしたら変なところの筋肉が痛くなる。

scim パーサーの実装

半年ほど前に scim 向け urn パーサーの提案 を PR で送っていた。これまでその PR は放置されていた。数日前からライブラリの作者が PR をみてくれたようだ。私が送った PR 自体は作者の意図したものではなかったようでクローズされたが、作者が scim の仕様を把握して代わりに作ってくれた。パーサーの実装が automaton? のようになっていてパッと見ではロジックがよくわからない。

せっかく作ってくれたのでこの機能を使って、お手伝いしている会社のアプリケーションの scim urn のパース処理を書き直した。これまでは正規表現で実装されていた。rfc に準拠した go-urn を使うことでバリデーションもできるし、パフォーマンスもよいし、urn の部分文字列も参照できる。ライブラリの学習コストや依存ライブラリを増やすデメリット以外はとくに問題はない。

テックブログを読む会談義

テックブログ一気読み選手権20240129杯 に参加した。イベントが終わってから軽くにしはらさんに お手伝い先で社内イベント を始めたことを情報共有した。にしはらさんが知る限り、このイベントを他社でもやり始めたというのは初めてのことらしい。とても洗練されたよいイベントなのに社内でもその価値を理解できる人たちは少ないという。前にも書いたけど、まさにこれだと思う。

恐ろしく速い手刀。オレでなきゃ見逃しちゃうね

お手伝い先ではまだ始まったばかり。1回目はそれなりにうまくいったつもり。毎週30分を4週やってみてメンバーに感想を聞いてみる。そして継続しようと決まったらまたブログにでもそのことを書こうと思う。

野菜スープのレシピ改

昨日初めて作った野菜スープ はいくつか気付きがあったので再挑戦。

メニューから「野菜スープ」を選択すると最初から画面に約25分と表示されて急加熱しているようにみえる。残り20分ぐらいのところからスマホのタイマーと一緒に比較しながら画面の時間がどう遷移するのかを観察していた。すると、スマホのタイマーと比べてホットクックの時間経過は遅くなっていった。残り13分の状態がもっとも長かった。残り7分のところでスマホのタイマーは20分経過した。残り7分で画面上に残り時間が大きく表示される。この後の時間の推移はスマホのタイマーとだいたい同じぐらいだったので信頼できる残り時間のようにみえる。したがって、ホットクックの調理をスタートした時点での、残り時間表記は目安であってまったく信頼できない。この野菜スープの調理時間は約25分とあるけど、今日作った分量とレシピでは約40分ほどかかっていた。ホットクックは内鍋を加熱して予熱したり、水があれば沸騰させたりする時間が必要らしい。その予熱時間が10分強はかかるとみておくとよさそう。

圧力鍋と比べるとホットクックの方が調理時間そのものは大きいというのは概ね正しいとは思う。しかし、ホットクックは基本的にスタートボタンを押下したら他にやることないので放ったらかしにする感覚でよいと思う。圧力鍋は圧力がかかったら火加減を調整したり圧力を下げて蓋を開けたらかきまぜしたりしないといけない。その「かきまぜ」の手間暇がホットクックはないのだから多少調理時間がかかっても全体としては気にならないと思う。

昨日のオリジナルを改変したレシピをさらに改変して今日のレシピはこれ。

  • にんじん x 1
  • 新玉ねぎ x 1
  • かぼちゃ 1/4切れ
  • ミディアムトマト x 8
  • セロリ x 1 の葉っぱ部分
  • しめじ 1袋
  • えのき 1袋
  • ローリエ 1枚
  • 塩コショウ 適当
  • コンソメ (小さじ4杯)
  • 水 600cc

にんじんは乱切りをやめて 1cm 程度の正方形に切る。かぼちゃもにんじん同様、1-2cm の正方形に切る。セロリの茎の部分は使うのをやめて、葉っぱが付いている部分を適当なサイズに切って入れる。野菜を小さくしたことで、いろいろな食材を一緒に口に運べるようになって、にんじんやかぼちゃだけ頬張るのではなく、複数の素材の味を一緒に楽しめるようになった。そうすると、えのきは石づきを切り離してそのままの長さで入れていたが、他の野菜と一緒に食べやすくしようと思ったらもう半分ぐらいに切り落として短くした方がよいのではないかと思えた。あとスープも少なかったので昨日よりも水を 200cc 増やした。

昨日作ったものは薄味の、なにかひと味足りないというところに、コンソメはうまくはまった。レシピに入れろと書いてあるものを勝手に抜くのよくない。足りなかった旨味が揃ったことで他の食材とのバランスも断然によくなった。セロリを減らしたことでセロリの癖も弱くなってちょうどよくなったと思う。昨日と比べて、お料理ベーコンを買い忘れてなしで作ったが、あってもなくてもそんな変わらない気がする。コンソメにより肉エキスも入ったことで鶏もも肉をちょっと入れてみてもよいような気がした。お肉的なたんぱく質のアクセントがあってもよいんじゃないかと思えた。次に作るときに試してみる。

昨日作ったものよりもおいしくなって料理としての完成度は増したように思う。野菜スープと一緒におにぎりを2個食べた。100 kcal + (200 kcal * 2) = 500 kcal ぐらいかな。晩ご飯のカロリーとしてちょうどよい。

仮に調理の味付けを失敗したときでもなにかふりかけのようにかけて味変できるものがあるとよいと思う。昨日のコンソメ抜きの野菜スープも鰹節をふりかけたらおいしくなった。フレークタイプのカレーで市販のカレールウに比べて油脂分が少ないらしい。こういうのも容易しておくと失敗したときに誤魔化せるかもしれない。