秋休み3

目次

昨日はいろいろ活動して疲れてしまったのと、雨降りもあってだらだらしていた。

よい土曜日

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

みなとのもりの運動

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

ラケット選び

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

ストレッチ

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

カフーツさん訪問

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

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

最低限のリファクタリングを終えた

昨日のリソース管理のリファクタリングでもっとも煩雑なところの作り直しは終えたので今日は別の機能拡張を実装していた。夕方に散髪へ行ってきた。気付いたら前に散髪してから3ヶ月以上たっていた。生活に余裕が戻ってきた。

fitbit 故障?

水曜日あたりに急にバッテリー切れになった。だいたい3-4日はもつのであれ?と思いながら充電していたものの、丸一日放置しても電源が入らない。fitbit のサポートは電話対応しかしていない。9時まで待って電話したらつながって、サポートの担当者とトラブルシューティングをしていたものの解決しない。購入して1年間は保証期間なので交換対応もしてくれるという。その手続きのためのメールをもらいつつ、充電ケーブルに接続した状態で夜まで放置していたら急に電源が復旧した。復旧した、bluetooth のペアリングをやり直して、ファームウェアをアップデートした。よかったと思えたのも束の間、腕につけていると2時間ほどでバッテリーが50%を切っている。歩いていないのに歩数もすごいことになっていてデバイスが異常な状態になっているようにみえる。

75,000 歩を達成して妖霊(ジン)の靴バッジを獲得しました!

バドミントンの練習場所の確保

毎月1-2回バドミントンを始めて半年ぐらいたった。やっていると楽しくなってきて趣味の1つとして継続的に取り組もうと考えている。募集のタイミングをみてバドミントン教室にも通ってみようと思うし、どこか練習させてくれるコミュニティがあれば出稽古へ行ってもよい。そこで練習をしたい。個人的には体育館でなくても構わないけれど、バドミントンを練習するには練習相手が必要になる。練習相手をみつけるために練習場所を確保する必要がある。したがって体育館を安定的、且つ定期的に予約できるのが望ましい。磯上体育館はおそらく月に1-2回が限度だと思う。

たまたまながいさんと話していて ICTを活用した中学校体育館の夜間開放 を教えてもらった。三宮.dev の仲のよいメンバーを構成員として団体登録の利用申請を出した。アカウント登録に10日ほどかかるという。このサイトに料金は書いていないので無料なのかな?磯上体育館の抽選の過密さ (土曜日の昼間時間帯は申込みが100を超える) から考えると、他の団体も知っていて中学校体育館も予約や抽選でなかなか当選しないといった予感もしている。

pipe による関心の分離

目次

go の Pipe は go 言語プログラミングのよいところをいくつか同時に実感できる、実用度の高いユーティリティだと思う。go 言語は writer や reader をインターフェースとして定義している。細かいメソッドの違いでいくつかの writer/reader インターフェースを区別していたりもするが、基本的には write/read のメソッドをもっていればよい。

type Writer interface {
	Write(p []byte) (n int, err error)
}

type Reader interface {
	Read(p []byte) (n int, err error)
}

この汎用的な writer/reader のインターフェースに従っていれば、さまざまな要件に対して抽象化ができる。オンメモリでデータを扱うこともあるし、OS のファイルシステム上のファイルとして扱うこともあるし、オブジェクトストレージ上のオブジェクトとして扱うこともある。そういった具象オブジェクトの如何によらず writer/reader のインターフェースに従うことでデータ処理とリソース管理を分離できる。これはプログラミングパラダイムにおける 関心の分離 と呼ばれていることを実現する。

バッチ処理において複数データを読み込みながら処理を行い、処理中にエラーが発生したら、そのエラーデータを特定のファイルに書き込みしたい。エラーが発生したときだけ特定ファイルを生成する。そういった要件は次のように実装できる。

func write(w io.WriteCloser) {
	defer w.Close()
	/*
		if true {
			return
		}
	*/

	records := [][]string{
		{"first_name", "last_name", "username"},
		{"Rob", "Pike", "rob"},
		{"Ken", "Thompson", "ken"},
		{"Robert", "Griesemer", "gri"},
	}

	cw := csv.NewWriter(w)
	for _, record := range records {
		if err := cw.Write(record); err != nil {
			log.Fatalln("error writing record to csv:", err)
		}
	}
	cw.Flush()
	if err := cw.Error(); err != nil {
		log.Fatal(err)
	}
}

func read(r io.ReadCloser) {
	rr := bufio.NewReader(r)
	line, _, err := rr.ReadLine()
	if err == io.EOF {
		return
	}
	/*
		writer, err := os.Create("./test.txt")
		if err != nil {
			log.Fatal(err)
		}
		defer writer.Close()
	*/
	writer := os.Stdout
	if _, err := writer.Write(append(line, []byte{'\n'}...)); err != nil {
		log.Fatal(err)
	}
	if _, err = io.Copy(writer, rr); err != nil {
		log.Fatal(err)
	}
}

func main() {
	r, w := io.Pipe()
	go write(w)
	read(r)
}

Pipe を使うことで読み込みの処理と書き込みの処理を分離できる。ここでいう読み込みはバッチ処理、書き込みはエラーデータの保存処理に相当する。普通に実装すると、バッチ処理中にエラーデータの保存処理も記述することになる。業務のコードだと本質ではないリソース管理が煩雑になってしまう。2つの処理に分割するため、どちらか一方は非同期で実行する必要がある。ここで goroutine のシンプルさが際立つ。さらに pipe を使えば、reader 側は writer が Close するまでブロックするから終了処理の同期も自然なコードで実現してくれる。

非同期/並行処理の難しいところを go のインターフェースによる抽象化、簡潔な goroutine 記法、pipe に隠蔽された自然な同期処理の3つで簡潔に表現している。複雑さに対してこれほど簡潔なコードはそうそうないと思う。このコードを他の言語で実装しようとしたらもっと複雑になるはず。このサンプルコードとともに若いメンバーにリソース管理のリファクタリングをコードレビューで指摘したものの、そのメンバーには理解できなくて実装できなかった。そして、その処理を私が作り直すことになったというのが、今日のお仕事だった。本当は難しい非同期/並行処理をいくら簡潔にしても、その経験がないと人間には理解できない。まさに本質的複雑さを表しているように思える。

プログラミングとバドミントン

よく働き、よく遊ぶみたいな一日だった。

リファクタリングの最後の集中力

昨日から集中力を維持してずっとリファクタリングしている。やや複雑な機能をリファクタリングしているため、今週いっぱいはかかる見通し。本当は私が一から書き直した方が早い。しかし、若いメンバーに指導する意図もあるため、既存のコードを読んで誤りを訂正したり、仕様を確認したりしながら手直ししていく。射撃しつつ前進 の成果は着実にみえてきて、しんどいけど、コードの品質はどんどん改善している。マネージャーと 1on1 でリファクタリングの状況も伝えながら開発のイテレーションをもう1つ増やした方がスケジュール的にはよさそうかなぁみたいな共有もしていた。

体育館でバドミントン

前回の所感 。17時でお仕事を終えて最初で最後?の しみん福祉スポーツセンター の体育館を借りてバドミントンをしてきた。18時から21時の3時間枠で料金は3,000円。磯上体育館が2時間で700円なのと比べると割高になる。しかも、磯上体育館の方が駅に近いため、他地域から来られる方も参加しやすい。今後はこのスポーツセンターの体育館を借りるのはやめようと考えている。体育館予約にはリスクがあって3ヶ月前に予約しないといけないため、予約しても本当に参加者が来るかどうかわからない。一番悲惨なのは予約したけれど、誰も来なかったというパターン。いまのところ、そういう状況は発生していない。

閑話休題。今日は新しい人も2人きて全部で5人参加した。初めて行ったスポーツセンターの体育館は広くて設備そのものはとてもよかった。

前回来られた方に教えてもらった KALIDIAバドミントンチャンネル の動画を ipad にダウンロードしてもっていった。体育館で参加者と一緒にみながら次の練習をやってみた。動画をみたら簡単そうにみえるけど、実際にやってみると、狙ったところに打てないことに気付く。こういう地道な練習をしないとスキルが上達しない。もっと練習のパターンを増やしていきたい。

初めて来られた若い方がテニスをずっとされていたらしく、バドミントンも上手だった。前回もうまい人が来てくれて練習方法を教えてくれた。うまい人のプレーをみていると、あんな風にできたら楽しそうとか、思い通りにラケットやシャトルの操作ができなくて悔しいとか、感情的にモチベーションがあがってきた。あと久しぶりに運動して汗をかいてよい気分転換になった。

業務としてのリファクタリングへの集中力

目次

今週からメンバーが開発した、少し大きめの機能の品質改善のためにリファクタリングをしていく。本当は週末に進めておこうと思っていたものの、どうにもやる気がなくてまったく手をつけられていなかった。不思議なもので休日は朝起きられなかったりオフィスへ行ってもまったくコードを書けなかったのに、平日なら普通に朝8時までに起きてオフィスへ行って集中して作業できた。2日休んでいるので体力を回復していたというのはある。それでも休日と平日の業務としてのプログラミングへの集中力の違いは何なんだろう?とやぎさんに相談したら 反脆弱性[上] という本にその答えが書いてあったと教えてもらった。この本を読まないとその答えは得られない。しかし、いまの私は本を読む元気がない。誰か読んだ人がいたら私にわかりやすく教えてほしい。

私が書いたコードに対する不備や欠陥は責任感からリファクタリングをする一定のモチベーションになる。しかし、他人が書いたコードのリファクタリングはそのモチベーションがいくらかレベルダウンするのではないか?という仮説もある。他人のコードを読んで理解するのはコストがかかるし、本質的には他人のコードを読むことはできても理解することはできない。コードの出典に起因するストレスもあるのかもしれない。

秋休み2

目次

昨日に引き続き、やる気が出なくてなにもせずお休みしていた。

秋休み1

目次

お昼はだらだらしていて夜にオフィスへ行ったものの、全然やる気が出なくてとくに作業は進められなかった。

連休の初日

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

ストレッチ

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

責任を扱うコミュニケーションの在り方

水曜日から継続していたメンバーのコードレビューをお昼頃に完了して、それからは自分の時間に集中して開発に取り組めた。途中、晩ご飯休憩もしながら翌2時頃までコードを書いていて issue を2つ fix した。

隔週の雑談

顧問のはらさんと隔週の打ち合わせ。ここ1-2ヶ月はあまり議題がなくて近況について雑談した。いまの開発フェーズが終わらないと、私が開発以外にリソースを割いていないので他のことに取り組む余裕はないかもしれない。開発プロジェクトにおける、議題の1つで次のインタビュー記事の内容について雑談した。

責任をすぐに相手に投げてしまわないこと。責任をこちらで負えるように日頃から信頼貯金を貯めていくことが大事です。責任を負うこと自体はたいへんだけど、仕事は楽になるんです。

でも、人は責任を負いたくないと考えてしまうんですね。気持ちは分かりますよ、責任を負うのには胆力が必要ですから。そして責任を負いたくないから「いつまでですか?」と聞いてしまう。その途端、スケジュールを決めるのは相手の裁量になる。責任から降りて、自分から立場を下にして、受発注の関係にしてしまっています。

何が事業貢献なのか分からなくなっていた伊藤直也さんが再認識したユーザーエクスペリエンスへのコミット

私自身、このインタビュー記事を読むまで相手に仕様や納期を決めてもらうことを、相手に責任を負わせるという視点をもっていないかった。しかし、その通りでもあると新たな気付きを得た記事でもあった。うちらはプログラマーという、システムを作る専門家なのでビジネス課題や解決したい業務課題について、その課題意識をもっている人 (ビジネスオーナー) から教えてもらうのを至極当然のように考えてしまう。そして、それ自体はいまの業務の在り方としてそうならざるを得ないところもある。

システム開発はそれぞれの専門職が分業によって行う。とくに規模が大きくなればそうなる。この構造そのものは一般的といえる。しかし、一緒にプロジェクトをやっていく働き方や考え方によってはその責任を分散させられるというのがこの記事に書いてあることだとわかる。そして、私自身これまで意識せずにそういった行動をいくらか取ってきているところもあり、それは「気付き」のレベルによって起こるものだとずっと考えていた。気付くからより多くの、より本質的な、より優れた改善のための行動ができる。そして、私の考え方も間違ってはいないと思うが、私は他人よりリスクを取りがちな性格があるから責任をこちらで負うという意識をあまりもっていなかった。つまり、私は自分の価値観でこうしたいと思って勝手にやっていたことを、別の見方では相手から責任を受け取って進めているという解釈もできる。

ちょうど 兵庫県知事の百条委員会の答弁 もみていて感じたことだが、私はこういったコミュニケーションを本質的に好んでいない。自分の責任ではないという議論をしても、モノゴトは前に進まない。世間では百条委員会の後も知事の説明は十分ではなかったとみられている。その所以である。誰かが責任をもってモノゴトに取り組む必要がある。その責任の所在を明確にすることも大事ではあるが、自身の責任ではないという主張だけでは物足りなさを感じる。普段の業務においてもそういう姿勢やコミュニケーションを取る人が少なからずいる。はらさんの経験でもその点においては同意していた。よくある状況だと思える。自身に責任を負うことをためらわないコミュニケーションを取る人とそうではない人の2通りがあるのだと気付いた。そして、私は後者の人とコミュニケーションを続けていると疲弊したり苛々したりすることがある。それゆえに私自身も結果に対して潔くあろうと努めるし、潔い人たちとウマがあうのだろうともわかってきた。

課題管理の文脈においては、コミュニケーションのやり取りから責任の綱引きがどのような場所でどのぐらい起きるのか。人間であれば読み取れるが、ai はその意図を解釈できるか。そういった業務の責任という概念を見える化することに意味はあるかもしれない。責任の押し付け合い、または責任分散、本質的にどうあるべきだったかをなんらかの指標をもって数値化できればおもしろいのではないかと思えた。

go における簡単な式の評価

テスト自動化のツールを作っていて、テストデータでちょっとした式の評価をやりたくて調べたらまさに次の記事で解決した。

この記事では go/types パッケージに定数や式の評価を行う機能がその使い方が紹介されている。簡単に使える。ふとサードパーティのパッケージならどうなるんだろう?とインターネットを検索したものの、自分ではみつけられなかった。chatgpt に問い合わせたら次のようなコードを紹介してくれた。そして、たしかにほとんどは正しくて意図したように動いた。次のコードでは http フレームワークの echo の定数を参照している。types.Package を生成するためのモジュールの読み込み方法について標準ライブラリはそのためのユーティリティが用意されているが、サードパーティのパッケージは用意されていなかった。

import (
    "fmt"
    "go/token"
    "go/types"
    "golang.org/x/tools/go/packages"
)

func eval(expr string) (types.TypeAndValue, error) {
	cfg := &packages.Config{
		Mode: packages.NeedTypes | packages.NeedImports,
		Fset: token.NewFileSet(),
	}
	pkgs, err := packages.Load(cfg, "github.com/labstack/echo/v4")
	if err != nil {
		return types.TypeAndValue{}, err
	}
	if len(pkgs) == 0 || pkgs[0].Types == nil {
		return types.TypeAndValue{}, fmt.Errorf("failed to load echo package")
	}
	mainPkg := types.NewPackage("main", "main")
	mainPkg.Scope().Insert(types.NewPkgName(token.NoPos, mainPkg, "echo", pkgs[0].Types))
	return types.Eval(
		cfg.Fset,
		mainPkg,
		token.NoPos,
		expr,
	)
}

このコードで expr に次のように echo の定数を指定するとその値を参照できる。

echo.MIMEApplicationJSON

動的型付けのノリで関数も実行できたりするのかな?と試してみたら (当たり前だが) できなかった。chatgpt になぜ関数実行できないかを尋ねたら次であるとのこと。静的型付けのコードを実行するには、本来コンパイルしないといけないのだから式の評価よりもずっとやることがある。

packages.Load を使用してサードパーティパッケージをインポートできているにもかかわらず、expr からそのパッケージの関数を呼び出しても結果が取得できない原因は、go/types パッケージがサポートしているのは、型や定数のチェック、構文解析、式の評価であって、関数の実行そのものはサポートされていないためです。

go/types の Eval 関数はあくまでコンパイル時の型検査や式の評価を行うもので 関数の実行や実行時の評価 (ランタイムの処理) は行いません。これは、Eval が式を評価して型と値を返すだけであり、動的な関数の実行などはできないためです。

つなぎの雑多な一日

目次

昨日の続きでメンバーのコードレビューをしながら、openldap スキーマの validator のバグ修正をしつつ、チーム勉強会で雑多な仕様や設計の議論をしていたらそれにも時間を取られて、1日としてはまあり開発を進捗させられなかった。コードを書くことに集中できる時間を2-3時間連続で確保できないとモチベーションにも影響が出てくる。それだけ取り組んでいる課題が複雑だったり煩雑だったりしているのもある。