Posts for: #Design

設計の見直しとリファクタリング

2時ぐらいに寝て起きたかどうかあまり覚えていないが7時に起きた。あまり寝た気がしない。

エージェントアプリケーション開発

昨日の続き 。一晩寝かした甲斐があったのかどうか、意識的にはわからないが、少なくともつまづくことなく1つずつ設計の見直しや処理をパラメーター化していって一通りプロトコルの差異以外のところは整理できた。今日は自分のコードを書く余裕はなかったけれど、1日かけて既存の設計の見直しを終えられたことをうまくいったと自分で肯定しておこうと思う (他人からみたらそうじゃない可能性はある) 。

関数は1つの機能のみを実装して、入力しか依存関係をもたないようにシンプルにすべきという基本概念がある。その基本概念をちゃんと理解できていないと、設計のアンチパターンの1つとして、渡すパラメーターがどんどん増えていってしまうことに気付いた。まずは既存の処理やフローを変えずに設計を見直したのでそうなってしまっている。また後で時間があったら、インターフェースを明確にして根本的な設計を見直してもよいかもしれない。

真夏の休出 第1週

2時に寝て6時に起きてだらだらしてたらいつの間にか2度寝して9時に起きた。8月は開発の佳境なので基本的には土日を働く予定。

晩ご飯を外食して、夕方から NieR:Automata Ver1.1a というアニメが2期決定というニュースをたまたまみて、1期のコンテンツを見始めた。品質の高い作品だとは思うけれど、世界観 (設定) が私の頭の中のなにかとあわない。世界観の違和感や矛盾を受け入れ難いものがあって引っかかりを覚えるような作品だった。もともとゲームが原作らしい。人によって評価が分かれそうに思えた。

事例紹介のたたき台

先日のプレスリリース の続き。こういった会社の正式な文章を書くのは、その労力以上に面倒臭さが上回って後回しにしてしまう。簡潔な文章なので、過去の体裁やフォーマットなどをみながらやればすぐにできた。今回は私はマネージャーとしてプロダクト開発しているので、うちが作ったんよ的なノリでちょっと前のめりにプロダクト紹介をしてみた。私がもっている課題管理のノウハウを駆使して開発プロジェクトをうまくまわした工夫も書きたいところだけど、そうすると事例紹介と課題管理のプラクティスの話しがごっちゃになって訳の分からん記事になってしまう。事例紹介とは別に、今回の事例をベースに課題管理のプラクティスの記事を別途ブログに書こうと思った。他にもお客さん先のテックブログにも書かないといけない記事が2つ溜まっている。私は文章を書くのが遅いからなかなか捌けない。日記を書いて練習しているうちに早く書けるようにならないかな?と期待しているが、まだまだそんな予兆はみえない。

syncrepl を使ったエージェントアプリケーション開発

昨日のレビュー対応したものがマージされた 。それをもって自分たちのアプリケーションのコードを書かないといけない。以前に ldap の dirsync というプロトコル をメンバーが実装して、それを使ったアプリケーションのコードがある。その実装といくつか共通部分を再利用しつつ、プロトコルの違うところだけを追加できるようにしたい。既存のエージェントアプリケーションのソースを読みながら、どういう風に設計していくかのイメージを膨らませておいた。今日のところはコードを読んで頭の中に入れて考えるだけ。この状態で一晩寝かすと、寝ている間に脳が無意識に考えてくれて効率がよいはず。これは休日の時間のよい使い方だと思う。

最後は人のチカラがモノを言う

2時半に寝て寝たのかどうかよく分からないながら5時頃に寝落ちして7時半に起きた。

差分比較のための機能

id 連携で運用のための非機能要件の1つとして更新された内容を確認できるようにしたい。非機能要件だから私が作るかと思ってあたためておいた issue に着手した。wikipedia によると差分という言葉には次の2つの用語があるのをみつけた。

数学やコンピューターの用語的には delta (ギリシャ語で変化を表す) という言葉を使う。os のパッケージングシステムで一部のパッケージをアップデートするようなことをデルタアップデートと呼ぶ。一方でコンピューターサイエンスにおいて2つのデータセット間の差分については diff という用語を使う。データの差分においては diff でよいのではないかと思う。そういった用語の定義から始めた。mongodb のコレクションのデータ定義をしたり、結合テストを書いて動かしてみたり、インフラのレイヤーから開発に着手した。

上司道 企業家として生き様と、人として求められること

第92回上司道 企業家として生き様と、人として求められること に参加した。なんとなくタイトルに惹かれた。上司道 に参加するのは3回目。

講師の牛島さんは昨日が誕生日だったらしく90歳だという。90歳になって zoom でオンライン勉強会の講師を務めるというのを、私はまったく想像できないけど、コンサルタントの第一線で活躍されてきた方の貫禄があった。もともとどういう主旨の勉強会だったのかよく分かっていないけれど、内容はビジネスの自己啓発セミナーに近いものになった。牛島さんが90年も生きてきて大事だと思える内容には普遍性や汎用性があるのだと思う。いくつか共感できる考え方もあった。

  • これからは頭の良い人 (IQ が高い) よりも心が豊かな人 (EQ が高い) の方が大事で組織に貢献する
  • 一番大切なのは幸せであること
  • 楽しく生きる (働く)

過去に働いた会社でも頭がよくて何でもよく理解しているのにプロジェクトにあまり貢献しない人がいることに気付いた。さぼっているわけでもない。その違いを「心が豊かな人 (EQ が高い) 人」という言葉でいくつか説明できるのではないかと思えた。新規プロジェクトのような、常に変化して、正解もわからないまま進める業務において、論理や頭のよさだけでうまくいくことはなくなってきつつあるのではないか。なんのためにそのプロジェクトをやるのか、自分はなぜここで働いているのか、といった問いに答えをもっている人は普通の社員とは行動が異なる。自身の価値観や展望と比較して、現状の課題や改善に気付くのでプロジェクトを前向きに進めていける。頭のよい人は「あれが問題」「これが問題」と問題を指摘してエスカレーションするだけで自らが課題をどう解決するかの答えをもっていない。そんなことを考えながらこの話しを聞いていた。

次の2つは最近の私の人生観や働き方と重なるところがある。私はもう無理してがんばったりしないし、自分が嫌なお仕事も一切しないように決めている。一般的にいう「働きたくない」という生き方を目指している。もちろん実際には働いているわけだけど、それはなるべく働く時間を、遊んでいる時間に置き換えられないかと模索している。その過程で辛いことやしんどいことも避けようと考えている。

なぜそれができるかというのも、20代30代と約20年働いてきて自身の価値観を育ててきたからだと捉えている。私はなにが楽しくて、なにが辛くて、なにをやりたくないか。これは人それぞれに違う。私には私にしかない価値観をもっている。それがわかってきたから、いま自分の会社を経営していて、毎日がとても楽しいし、自分の価値観にあわないことはすべて断るという判断基準も明確になっている。そんな勝手気ままでやっていけるの?という懸念を抱く人も多いと思う。ダメかもしれない。仮にやっていけなかったとしても、いまの自分は幸せで楽しいのだからそれでいいんじゃないかと思う。無理をしていまがしんどくても将来がよくなる保証なんてどこにもない。

牛島さんはマザーテレサとインドで実際に会って10日間ほど一緒に過ごしてその体験がその後の人生を大きく変えたように話されていた。マザーテレサに「社員を大事にしていますか?」と聞かれたときに「しています。」と答え、その後に「社員全員の名前を覚えていますか?」と聞かれたという。当時の牛島さんの会社の社員は300人以上いて全員は覚えていなかった。それで「愛情の反対は無関心なのですよ。」とマザーテレサに指摘されて大きな衝撃を受けたという。その後、帰国してから300人以上の社員全員の名前を覚え、日々の業務で社員の行動などに気を配ってすべての社員に声をかけたりするようになったという。このエピソードもなかなか私には効く話しで、私は他人にかなりのレベルで関心がない。もし自分の会社で社員を雇うことになったら待遇がどうとか以前に、その人そのものに関心をもつという姿勢を覚えておこうと思う。

メモリリークに遭遇

23時に寝て何度か起きて5時に起きてからだらだらネットしながら記事を読んだりしていて7時に起き上がった。

agent アプリケーションのメモリリーク調査

qa テストの一環として先月からテスト環境で毎分 agent アプリケーションにリクエストを投げる長時間稼働テストを実行している。なんとなく気になるところがあったからやったわけではあるけれど、長時間稼働テストによってメモリリークを検出できてしまった。自分を過信せずちゃんと検証しないといけないなと思えた。top コマンドの実メモリー (RES) を1ヶ月前と比較して増えているからメモリリークだと気付いたところ。これからメモリプロファイリングをしながら原因を追求していく。私が書いた (レビューした) go のコードでメモリリークはないだろうと高をくくっていただけにちょっとショックではあった。

go は標準ライブラリに pprof というプロファイラがあるので簡単にデバッグできる。プロファイラで昨日から調査していたところ、go-zeromq/zmq4 の処理でメモリリークしていることはわかった。それがライブラリの使い方が誤っているのか、潜在的な不具合なのかはまだこれから調査するところ。

ライブラリ側の問題を調査するので厄介ではあるけど、私が書いた (レビューした) go のコードでメモリリークしているわけじゃないことがわかって少しほっとした。

go の generics 勉強会

先日準備した資料 を使って勉強会を開催した。

この勉強会はある意味、うちのチームのメンバーが理解しておくべき内容なので go のプログラミングをやっていないメンバーが聞いてもあまり関心をもてない内容となっている。そういうお断りもした上で最悪2-3人ぐらいの参加者になるかと思ったもののプログラミングに関心がある人たちは参加してくれて5-6人ぐらいの規模にはなった。一方で内容も難しいし、私の説明がどれだけわかりやすかったか、私自身にはわからないのでなんとも言えない。質問も一切なかったので喋りきって疲れたという疲労感と、伝わったのか伝わらなかったのか分からない消化不良感と、金曜日だから今日はもういいや感でどっと疲れたというのが率直な感想になる。

とはいえ、私もずっと generics の仕様をちゃんと追いかけたいと思いながら先送りしていたものではあるので私の中では自分が go の generics の理解度をあげて実際の開発の中で使い分けるだけの判断基準をもてたことが収穫だったと言える。

縁の下のマネージャー

20時にホテルに戻ってきてのんびりしながら気付いたら22時ぐらいになって、少しテレビをみて0時に寝て4時ぐらいから起きてその後はあまり眠れなかった。それでも7時過ぎまでだらだらしていた。

7月後半に実装予定の新機能の設計

9月までに実装する新機能のうち、唯一、私の頭の中で設計の見通しをもっていなかった機能の設計を行うことにした。

ざっくりした機能概要から私がふわっと想定していたものはずっと複雑なものだったのだけど、プロダクトオーナーに要件をヒアリングしているうちにそんな高度なものは求められていないことに気付いた。逆にその高度な機能の仕組みを提供しても、実際に運用の現場で使うにあたって手間暇だけかかってそんなものを求めていないと言われそうな気がした。そこで私が作りたいなと思っていた設計のアイディアは封印することにした。既存の先行プロダクトがもっている機能とほぼ同様のものを、うちらの開発しているプロダクトで実現するだけでよさそうにみえた。そのシンプルな機能の設計を軽くやっておいた。詳細を詰めるのは次のマイルストーンで私ではないメンバーに実装してもらうことになるけれど、なんとなく当初の想定よりも早くできそうに思えた。

ログ出力のリファクタリング

id 連携の処理で複雑なリソースを map 型で扱うときデバッグ用途でリソースを丸ごと dump したい。しかし、パスワードのような機密情報が含まれる場合はそれらはログに出力したくない。この処理をいまは連携種別ごとに実装していて、本質じゃないところで個別実装の手間があるのと機密情報の出力というセキュリティに関するところを毎回プログラマーが手で実装するのもどうかな?という気がして汎用のログユーティリティとしてロガーのライブラリ側で提供することにした。インフラやプラットフォーム的な機能に私は積極的に開発に介入している。

やり方の1つとしてオリジナルのリソースをコピーして機密情報だけ削除した一時的なリソースコピーを dump してログ出力する。go 1.21 で標準ライブラリに追加される maps パッケージを使うと map の操作が簡単にできる。コピー関数もある。しかし、この機能は shallow copy なので map の値にネストした map が含まれる場合はオリジナルの値を書き換えてしまう。ネストした map を調べてそれらもクローンしていく処理を実装した。excludeKeys に除外したい任意のキーを渡し、map の値を再帰的にチェックして取り除く。最終的には次のようなコピーユーティリティになった。

func copyWithoutExcludeKeys(
	fields map[string]any, excludeKeys []string,
) map[string]any {
	cloned := maps.Clone(fields)
	for k, v := range cloned {
		switch t := v.(type) {
		case map[string]string:
			strMapCloned := maps.Clone(t)
			for _, sk := range maps.Keys(strMapCloned) {
				if slices.Contains(excludeKeys, sk) {
					delete(strMapCloned, sk)
				}
			}
			cloned[k] = strMapCloned
		case map[string]any:
			cloned[k] = copyWithoutExcludeKeys(t, excludeKeys)
		case []map[string]any:
			for i, v := range t {
				t[i] = copyWithoutExcludeKeys(v, excludeKeys)
			}
		default:
			if slices.Contains(excludeKeys, k) {
				delete(cloned, k)
			}
		}
	}
	return cloned
}

七夕と願い

23時に寝て2時に起きて6時に起きた。旅行から帰ってきてから最近はこのパターンになってきた。

google のロゴが Tanabata 2023 になっていて七夕だと気付いた。もう私にとって願いというのは健康を祈るぐらいしかない。残された寿命を使い切る前にいまやっていることをやり切りたい、もしくはその結果をみたいと思っていて、そのために必要なことは健康ぐらいかなと。

隔週の雑談

顧問のはらさんと隔週の打ち合わせ。今日の議題はこれら。

他社の社員旅行へ同行してみての所感として学ぶことは多々あった。

  • 強制参加にはしない (断ってもよい)
  • 仕事だけではない人間関係の構築という価値観を大事にしている
  • 上下関係がフラットなので参加者が自由に行動したり話したりできる
  • 経営陣や上司に忖度しないメンバーがいることでフラットな関係性を共有できる
  • チーム単位で行動できるので組織の全体行動を強制される感覚が緩和される

野中郁二郎先生は業務外での暗黙知を共有する「場」づくりが大事だと説いている。会社が危機のときやしんどいお仕事をこなすとき、最後は経営者やリーダーの人生観や価値観がモノを言うという考え方がある。そんなときにこういった価値観の共有は役に立つのかもしれない。「社員旅行」という単語自体が古い価値観をイメージしてネガティブに聞こえる。いまだったらワーケーションと呼ぶ方がよいかもしれない。

過去にスタートアップで働いていたとき、会社が M&A で売却して、私にとってはあまりメリットがなかったので即断で辞めると伝えた。即断できたのは経営者に理念がなかったからというのも大きな要因の1つだといまになって思える。時期の差はあれど、私以外の主要メンバーもその後に全員辞めた。要はそういうこと。

go の generics 勉強会の準備

水曜日から資料を作っている。昨日はほぼまる一日コードレビューをやっていた。午前中の半日を費やしてようやく完成した。この資料は一般の go 勉強会でも使えるなと思ったのでお手伝い先のプロダクト開発に関するところを取り除いた資料を別途公開した。資料の中でその内容を検証するサンプルコードも次のリポジトリで公開している。

go の generics 勉強会へ向けての準備

0時に寝て6時に起きて7時に起きた。週明けから忙しくて余裕ない。それでもよく眠れていることが幸い。

go の generics 勉強会の準備

今週末の金曜日に勉強会をする想定で作り始めた。generics は難しいのでなかなか本腰を入れて取り組めていなかった。基本的には tenntenn さんの プログラミング言語Go完全入門 15章ジェネリクス(型パラメタ) の資料をベースに、自分で理解できるように調査したり、サンプルコードを書いたり、自分で理解した内容を補足したりして資料を作り始めた。go 1.18 のジェネリクスで導入された概念は次になる。これらのキーワードに関するところをそれぞれ調べることにした。

  • 型パラメーター
  • 型引数
  • インターフェースによる制約 (Type constraint)
  • 型セット (Type sets)

scim 調査に着手

22時に寝て24時に起きて4時に起きて6時に起きた。実家だとやることないので寝るのも早くなる。早く起きているので始業も7時半ぐらいになる。早起きは三文の徳。

リモートワークのタグを新設

神戸のオフィスに行かなかった日は day off というタグを付けている。名前の通り、お休みしたということを表す。この定義に従うと、実家に帰ってリモートワークをしたときもお休みになってしまうため、それを区別するように remote work というタグを作った。

scim 調査

id 連携の文脈で System for Cross-domain Identity Management (頭文字をとって SCIM、すきーむと呼ばれている) という標準がある。基本的には rest api とスキーマを扱うように仕様が決められていて、それに準拠したサービス間で id 連携を標準化する狙いがある。id 連携と同じ用途を表す用語として id プロビジョニングという用語もあるが、多くのクラウドサービスでは id プロビジョニングのために scim 対応していたりする。

たまたまサイボウズさんが okta と scim 連携に対応しているプレスリリースをみかけた。

その延長で調査していたところ、go の scim ツールを提供していることに気付いた。しかもこれを作っているのが Maki さん。これはソースを読んでおこうと思った次第。Maki さんはメルカリに所属していたと思うのでこれは副業でやっているのかな?

scim-server は scim ライブラリを実際に使うときの参照実装としてアプリケーションの開発者に開発の雰囲気を伝えるための実装になっている。これ自体をプロダクトのサーバーとして使うわけではない。sqlite を使ってユーザー/グループの crud な操作と検索機能を提供している。

scim ライブラリのソースコードも軽くざっと読んでみた。github.com/lestrrat-go/sketch という go でスキーマを記述してコード生成する Maki さん製のツールがある。これを起点に scim のプロトコルやリソースの仕様にしたがって go のコードでスキーマを定義し、リソースに関する go のコードと scim スキーマを自動生成している。sketch というツールに関連して他にも Maki 製のメタプログラミングライブラリを多用していて、scim の標準化されている部分のエンドポイントやリソースのインターフェース部分をすべてコード生成している。

go generate やコード生成の実際の応用例として非常に参考になる。このライブラリは scim のプロトコル仕様に関する開発者と、そのエンドポイントの実際の処理 (バックエンド) の開発者を明確に分離するという開発体制を期待している。scim に関するところは Maki さんが独りでコード生成を多用してオープンなプロトコル仕様の開発を担当し、そのバックエンドをサイボウズさんの開発者が実装するという分業体制を想定しているようにみえる。

scim 対応のアプリケーション開発のプロトコル部分を外部に委譲するといった設計になっているが、scim が十分に安定していてプロトコルの仕様が変わらないのであれば理に適っているとも考えられる。バックエンドの開発者はいくらか sketch の学習コストを強いることになる。そのため、アプリケーションはその学習コストを支払ってもコード生成のメリットが上回るだけの規模や特性を要求する。おそらく scim はそれだけの価値があると判断されたのだと推測する。

私はメタプログラミングが好きな方なのでこういうやり方もあるんだなと設計の参考になった。またコード生成の要件があったときにソースを参考にしようと思う。

トイレにうんこ

0時に寝て4時に起きてドラクエタクトやりながらだらだらしているうちに少し寝て7時に起きた。

トイレにうんこを詰まらせた

いや。正確にはトイレが詰まってうんこを浮かべた。朝トイレへ行ったら洋式トイレにトイレットペーパーが漂っていた。前に使った人が流していないのかな?と考えて気持ち悪いのですぐ流した。これまでも過去にそういうことがたまにあった。あとから考えると、誰かのいたずらでなにかしらトイレに詰まるものがトイレットペーパーの下に隠されていた可能性もある。この時点で次に水が流れるかどうかのチェックをするべきと洞察できていなかった。

それから、うんこして流したらトイレが詰まったようで流れない。微妙に便器から水が溢れてきた。ぎりぎり溢れ返ることにはならなかったのでトイレの床にうんこが散乱する最悪の状況にはならなかった。しかし、トイレにうんこがぷかぷか浮かんでいる状態になった。べつに私が悪いわけではないと思うのだけど、トイレにうんこが浮かんでいる状態にしてしまったことにとても罪悪感を感じた。

幸い朝8時からシェアオフィスにいるのは私ぐらいで、多くの利用者は10時前後にならないと出社してこない。いまトイレに誰かが入ってきて犯人扱いされることはなさそう。なんか行き当たりで人を殺めてしまった殺人犯みたいな心境になった。運営会社のサポートは9時から。1階へ降りていって掃除のおばちゃんに尋ねてみたけど、うんこが浮かんだトイレの階は自分たちの管轄じゃないと断られてしまった。(´・ω・`) 仕方なく、時間を待って9時ぴったりにサポートに電話して聞いてみる。サポートにも断られたらどうしよう?不安と緊張が走る。サポートのお姉さんは (当然ではあると思うけれども) 全然平気ですよーと快く応じてくれて安心した。まぁ、電話しているお姉さんが対応するわけじゃないしね。

電話で一報を終えて、その後、トイレ業者さんが来るまで自分のうんこを浮かべておいていいのかどうか、すごく悩んだ。かといってうんこを取り出す勇気もなく結果的にそのまま放置した。人間がしょぼい。40年以上も生きてきて自分のうんこの処理もできないのかと思うと本当に情けなくなった。「入るな、危険」ぐらいの張り紙しといてもよかった。本当の犯人だったらここでとんでもないトリックを思いついて実行するところだけど、一報したことでそこまでの切羽詰まった状況でもなくなっていた。もし警察がやってきてもサポートのお姉さんが犯人じゃないと証言してくれるだろう。

9時から打ち合わせがあって、1時間半後、恐る恐るトイレを見に行ったらすでに詰まりは解消していてうんこもなくなっていた。平和な日常が戻ってきてよかった。

平安時代とか、都はうんこまみれだったという記事を昔読んだのを思い出した。

隔週の雑談

顧問のはらさんと隔週の打ち合わせ。今日の議題はこれら。

最初の30分でサイトデザインをみながら、はらさんのレビューの視点や背景を教えてもらっていくつか気付きを得た。後半は来月の雑談会へ向けて、課題管理の資料のレビューを始めて、いつもは1時間で打ち合わせを終えるのだけれど、つい課題管理の話しでテンションあがって話し過ぎてしまって30分オーバーした。打ち合わせのような時間を決めている会議で議論に熱くなるのはよくない。失敗したなーと反省した。

パスワードの表現

go でパスワードを扱うときに平文をハッシュ化して保持するためのユーザー定義の構造体を作りたい。構造体にハッシュ化した値をもつとしても、プログラマーが誤って任意の値を設定できないように制御したい。ここで go はオブジェクト指向言語ではないのでコンストラクタという概念がない。私が知っているもっともシンプルな方法は interface と private な構造体を組み合わせてコンストラクタに近いものを実装する。コードレビューしていてメンバーにパスワードがハッシュ化されていることを保証する仕組みをお題として指摘してみた。

今日のところは解決できなくて月曜日に持ち越しになった。私の想定する模範解答は次のようなものだけど、ちゃんと自分で考えて実装できるかなぁ。

type Password interface {
	Authenticate(s string) error
	Get() []byte
	String() string
}

type passwd struct {
	hashed []byte
}

func (p *passwd) Authenticate(s string) error {
	return bcrypt.CompareHashAndPassword(p.hashed, []byte(s))
}

func (p *passwd) Get() []byte {
	return p.hashed
}

func (p *passwd) String() string {
	return string(p.hashed)
}

func NewPassword(s string) (Password, error) {
	h, err := bcrypt.GenerateFromPassword([]byte(s), bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}
	return &passwd{hashed: h}, nil
}

go の channel 制御の学び

0時に寝て2時に起きて5時に起きて6時に起きた。久しぶりに夢をみたような気がする。

go の channel とクローズ制御

rabbitmq/amqp091-go を使った pubsub の consumer の実装で次のような for ループでメッセージを取得していた。この場合 deliveries の channel が閉じられると内側の for ループが終了して、外側の for ループの接続処理へ遷移する。

for {
    // コネクションの接続処理

    for d := range deliveries {
        // メッセージ処理
    }
}

この処理を context を使ってキャンセルできるよう、次に書き換えた。channel の Receive operator のドキュメントによると、channel は2値を返すことができて、戻り値の2番目の ok の値を調べることでその channel がクローズされているかどうかを判定できる。この仕組みを知っていれば select で ok を調べてエラー処理を実装できる。そうしないと deliveries の channel が閉じられれたときに select では常にゼロ値のメッセージが返るようになって意図したメッセージ処理とならない。

for {
    // コネクションの接続処理

    for {
        select {
        case <-ctx.Done():
            // context がキャンセルされたら終了処理
            if err := s.ch.Cancel(cid, false); err != nil {
                return fmt.Errorf("failed to cancel channel: %w", err)
            }
            return nil
        case d, ok := <-deliveries:
            if ok {
                // メッセージ処理
            } else {
                // エラー処理
                break
            }
        }

        // コネクションが閉じていればループを抜けて再接続
        if s.conn.IsClosed() || s.ch.IsClosed() {
            log.Info("the session was closed, try to reconnect", nil)
            break
        }
    }
}

同じ channel からメッセージを取り出すループ処理でも用途によって使い分けがあるなぁと今更ながら学んだ。というか、自分でバグを埋め込んで自分で直した (´・ω・`)

マージまで約1ヶ月

先日送った amqp091-go の pr が最終的にはほぼそのままマージされた。約1ヶ月ぐらいの議論やレビューがあって取り込まれた。新しいリリースバージョン (次は 1.9.0?) が出たらうちのアプリケーションでもこの新しいメソッドを使うようにして実績を積ませる。この pr は「あったら便利」程度の機能なのでそれほど重要ではない。

この成功体験をもって次は本命の go-ldap の pr のマージに向けて勢いをつける。こっちの pr は業務に直結しているので本気でやり取りしている。

エラーのラップと型階層

0時に寝て何度か起きて7時に起きた。署名・押印を完了した相続の書類を朝一で郵便局へ言って送付した。これで後は弁護士さんや司法書士さんが残りの手続きをやっておいてくれるのかな?少し気が楽になった。

ラップしたエラーのチェック

java でいうところの Chained Exceptions を go では Wrap という概念で表現する。Unwrap する interface を提供することで事実上の Chained Exceptions と同じようにオリジナルのエラーを辿ることができる。go はオブジェクト指向言語ではない と先日の勉強会でも念押し確認してエラーの型階層という概念はないが、Wrap をみていると型階層の方が自然じゃない?と考えられなくもない。言語の設計を考えるよいお題だと思えた。

エラーチェックについては次の記事がわかりやすかった。

カスタムのエラーを定義する。

type MyError struct {
	message string
	err     error
}

func (e *MyError) Error() string {
	return e.message + ": " + e.err.Error()
}

func (e *MyError) Unwrap() error {
	return e.err
}

このチェックのために errors パッケージに次の2つの関数がある。

  • errors.Is: エラーのインスタンスが同じかどうか
  • errors.As: エラーの型に代入可能かどうか (事実上はインスタンスの型が同じかどうか?)

たしかにこれでもすぐに実装できた。型階層なんかなくてもこれで十分でしょというのが go の意見かな。

隔週の雑談

顧問のはらさんと隔週の打ち合わせ。今日の議題はこれら。

週末は勉強会と実家に帰るので余裕がなかったのであまりネタがなかった。能の話しをしていて、子どものときに関心がなかったものを大人になって受け取り方が変わるものがあるのはなぜか?という話題で雑談した。はらさんも落語がわかるようになったという話しをされていた。この話しはストレッチのトレーナーさんとも盛り上がった。

子どもだともっている情報が少な過ぎて情報を理解できないのではないか?

情報や知識を蓄積することで対象への解像度があがるにつれて、みる視点が変わったり、興味が変わったりすることはあるかもしれないなと聞いていて思えた。課題管理の話しをしても、多くの開発者は無関心だったり共感を得られなかったりするが、そこにも通じるものがあるのかもしれないとなにかしらの取っ掛かりになるかもしれないと思えた。