昨日は開発が進捗したからお仕事も早めに終えたし、気分もよかったものの、今日から新たな issue でテストデータの生成ツールを作り直そうと再設計していた。過去にある程度の機能を作り込んだ知見があるから、すぐできるだろうという見通しで着手したものの、あーでもない、こーでもないと試行錯誤していて、うまくいかない。まる一日調査もしながら考えていたのに、これといった手応えはなくて、久しぶりにこのツールをどう作ってよいかノーアイディアのような雰囲気になってしまった。サーバーサイドやインフラのツールをいろいろ作ってきた過去の経験や蓄積があるから、あまりこういう状況になることはない。なまじ1度作った機能を改良するため、うまくいかないところや難しい課題もある程度わかっていて、それらの改善案が出てこないといったこともあったのかもしれない。プログラミングって、行き詰まったときの孤独感や焦燥感との戦いもあるなと開発の勘どころのようなものを思い出してきた。興に乗らなくて夜のコーディングは行わずに普通にお仕事を終えた。
Posts for: #Programming
プロジェクトのボトルネック解消
今日は開発の設計に関する打ち合わせが2つ入っていて、どちらも私はメインではないものの、メンバーが要件ヒアリングしやすいよう、ハドルで話しを聞きながらチャットにコメントしたり質問したりしてサポートしていた。その合間に ldap サーバーのグループメンバー管理のための api を実装していた。いま ldap client はライブラリとして作っている。docker-openldap というコンテナを使って dockertest で単体テストを実装している。openldap サーバーに対する ldap プロトコルの操作を容易にテストできるので開発がやりやすい。新規にグループメンバーを操作するための api をライブラリとしての ldap client に実装し、その後に web api としての機能を提供した。だいたい1日で完了した。この2週間ほど取り組んでいた、開発フェーズにおける私のボトルネックをこれで解消できた。ここからは私がやりたい開発ができるボーナスステージへと移行していく。これで少しストレスやプレッシャーが減っていくはず。
バドミントンという健康的な趣味
昨日、大きな仕様変更を入れた内容の、API ドキュメントを書き直していた。大きな変更をしたのでドキュメントの修正量も大きくて半日以上かかった。こういった効率化しにくい、地道にコツコツやらないといけない作業が忙しいときに降りかかるのがつらい。誰でもそうだとは思うけど。元来、私は積み重ねをしていく地道な作業は得意な方だと考えている。しかし、いまはリーダーとして他のメンバーを引っ張っていく立場にあるため、時間のかかる作業をしていると足踏みしているような罪悪感を感じてしまう。一方でそういった実務をちゃんとやることをメンバーにみせることも大事かなと思って、面倒な作業を自分でやるときもある。ケースバイケース。
体育館でバドミントン
前回の所感 。19時からバドミントンへ行ってきた。19時の時点では3人しかいなかったものの、後半にながいさんも来られて、最終的な参加者数は4人だった。ここ1-2週間は椅子にすわってデスクワークばかりやっていて、ほとんど運動できていないのでカラダを動かすのにちょうどよい機会になった。今回も line のオープンチャット 経由で加古川から初参加で来てくれた方がいた。三宮は職場の通勤途中になるらしく、それもあって立ち寄ってくれたようだ。その方も私と同じ世代で初心者からバドミントンを始めて1年ほどの経験らしい。毎週、地元の体育館で練習していると話されていた。うちらに比べればずっと上手だった。うちらはみんな初心者だから適当にやってきたのだけど、(うちらと比べて) 熟練者が来てくれたのでバドミントンの練習方法もいろいろ教えてもらった。その方は次の動画をみて勉強していると話されていた。私も後でみてみようと思う。
バドミントン経験1年の方の振る舞いをみていて、バドミントンは趣味でずっと続けていくのによいスポーツだなと思えた。運動にもなるし、カラダを痛めるといった健康を害することもなさそうだし、お金もかからないし、老若男女、初心者誰でもできるコミュニティ向けのスポーツでもある。教える方のスキルが高いほど、初心者の練習相手として、初めてイベントに来られた方がバドミントンに関心をもつ手助けもできそうに思えた。いまのお仕事の開発が一区切りつけば、有料のバドミントン教室へ通ってみて基礎を教えてもらいに行こうかなと思い始めた。
プロジェクトのボトルネック解消への壁
週末は休んでいたので今日は調子よかった。週末にある程度やっておこうと思っていた実装作業が手つかずだったものの、午前中の定例会議でメンバーに設計内容の最終確認をした。それから集中してコードを書いていたら日付が変わるぐらいの時間まではやっていたけれど、大きな仕様変更を完了した。
連休の週末に時間があったにも関わらず、なにもやらなかったのはこの仕様変更のための作業に私自身が本当の意味で関心をもっていないのではないかという仮説をたてた。仕事でやらなければいけない、面倒でやや規模の大きな作業を、個人の時間で取り組むほどのモチベーションをもっていない。そして無意識的に脳が業務時間だけでできると判断してしまっている。実際にそれで完了することも多い。開発の前倒しはできないが。
今週は開発者として実装に集中していた
久しぶりに実装に集中した金曜日
既存の web api のある機能を再設計する。既存機能のエンドポイントの見直しも含むのでテストコードなども移行しないといけない。ひとまずエンドポイントの移行と機能分割はできた。最低限の進捗。まだこれから仕様変更や拡張を追加していく。似て非なる機能を分割しているので名前の付け方をわかりやすくしないといけない。用途と名前空間をうまく組み合わせてわかりやすくしたいが、こういう作業は深夜よりも朝の方がうまくいく気がするのでまた明日にする。朝起きれるかなぁ。
オプトラン中間決算
先週の金曜日にオプトランの株価が1500-1600円台まで落ちれば 割安で狙い目ではないかと書いた。実際に月曜日に歴史的な暴落があって寄りと引けで購入していて、それぞれ 1,490 と 1,466 だった。過去5年の最安値が 1,420 なので割安だろうと考えた。昨日、中間決算があって 2024年12月期 第2四半期 決算説明資料 をみていた。通期での業績は変更していないものの、直近の四半期の業績はよくなかった。前四半期がかなりよかったため、半期の累計としてみたら通期目標に対する進捗はよいと言える。しかし、直近の四半期の業績はよくないから、この空気は売り込まれるやつだと昨日の夜の時点では予想していた。経営陣もそれを見越してなのか 7.72% の自社株買い を発表している。月曜日に割安と考えた見立ては失敗だったかなと諦めつつ、今朝の時点では、大きく売り込まれたらまた買い増ししようとも考えていた。結果的に今日の株価は 1,640 で始まって 1,697 で終わった。自社株買いのおかげ?私のこれまでのオプトランの観察眼では、大きく売り込まれるはずだったのが、なにもなく過ぎ去った。また定期的に少しずつ買い集めていって2024年12月期の決算が終わったときに覚えていたらふりかえってみたい。
寝不足でバテた
久しぶりに実装に集中した翌々日
火・水と連日で遅くまでコードを書いていてバテた。晩ごはんをオフィスで食べて帰って20時頃からそのまま寝てた。区切りがよかったのもあって今日は休むことにした。疲れが溜まっていたからすぐ眠れた。2時頃に一度起きたものの、わりとぐっすり眠れた。深夜までコードを書いていたから単純に寝不足だったように思う。私がボトルネックに成りうる大きな課題の1つを解消した。よいペース。今週中にもう1つの大きな課題を fix したい。
一開発者としてコードを書く日々
久しぶりに実装に集中した翌日
昨日に引き続き、日中コードを書いて、晩ごはんを食べた後にまたコードを書き始めて、翌1時半ぐらいまで書いていた。昼間はどうしても他メンバーの進捗をみたり、質問を受けたりするから割り込みで作業を中断されがち。夜は割り込みが入らないことがわかっているからコードを書くことに集中さえできれば区切りのよいところまで一気に書ける。いままで夜に運動していた時間をしばらくはコードを書くことに割く。いま私がボトルネックになりそうな課題を抱えているのでそこを早めに解消しておきたい。
一開発者としてコードを書く
久しぶりに実装に集中
8時半から20時半までコードを書いて、気分転換に買いものへ行ってきて、22時から仕様変更した内容に関するドキュメントを書いて24時までお仕事をしていた。プロジェクトマネージャーを移行 して開発者に戻ったことにより、心理的にコードを書くことに集中しやすくなった。1年半ほど開発者から離れていたことの、勘どころのようなものも徐々に取り戻していく。運動と一緒でコードを集中して書いていると嫌なことを忘れられてよい。コードを書くことも私にとっては瞑想に近いものになっている。
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 にも上がっているのでいずれはメンバー属性を解決できるようになるのだろうと推測する。
税理士さんの選定
1時に寝て3時頃に吐き気で起きて1時間ぐらい苦しんでた。久しぶりにやばかった。その後なんとか寝て7時半に起きた。
税理士さんとの打ち合わせ1
うちの会社のイベントとして毎年ワーケーション (開発合宿) をやろうかと考えている。コワーキングやコミュニティの延長上でワーケーションを行うわけだが、いくらかうちの会社の持ち出しで費用負担してよいと考えている。しかし、そのときの支出はどういった建付けで経費として扱えるのかどうか、私は税理士ではないのでよくわかっていない。そういったことを相談するために税理士さんに顧問になってもらおうと考えている。うちから税理士さんへの要件としては freee のデータを正として扱ってくれればそれでいいかな。
また2021年度は赤字決算になったので2022年度に 法人税の欠損金の繰り戻し還付 を行った。このお金を2022年度に計上していないため、その分の金額が資産のマイナスとして2023年度の決算に残ってしまっている。法人税の支払いは正しいのだが、還付金を2023年度に雑収入として登録するか、2022年度に遡って未計上の金額を登録するかのどちらかで訂正しないといけない。過去の法人決算の訂正自体も行う仕組みはあるので手続きするだけだが、それも手間暇がかかるのでついでに税理士さんにやってもらうと考えている。
会計システムに freee を使っているので freee さんの税理士紹介サービスを使って選定する。3事務所ピックアップしてくれたので順番に打ち合わせしていく。今日はその最初の税理事務所の方と打ち合わせした。話した感覚でうちの会社の考え方や規模にあった税理士さんだったのでこの方でいいんじゃないかとも思っているけれど、せっかく他の事務所もピックアップしてくれたので他の税理士さんの話も来週また聞いてみる。
コードレビュー
まる一日コードレビューをしていた。私もマージリクエストを投げていてレビューしてもらいつつ、メンバーのコードレビューも順番にやっていった。その中で smtp の仕様を把握しておく必要があっていくつかシニアエンジニアの方からもアドバイスをもらって、私もそうだったんだと勉強していた。メールヘッダーのエンコーディング、昔は覚えていたけど、ずっとメールを送るコードを書いてなかったので私も忘れてしまっていた。こういうことをさらっと指摘できるのがシニアエンジニアのすごいところ。
go だと標準ライブラリに mime パッケージがある。mime パッケージを使って件名を utf-8 でエンコーディングされた文字列で指定すると次のようになる。q エンコーディングと b エンコーディングの2種類がある。b エンコーディングの方がデータ量が減ってよさそう。
fmt.Println("Subject: " + mime.QEncoding.Encode("utf-8", "テスト"))
fmt.Println("Subject: " + mime.BEncoding.Encode("utf-8", "テスト"))
Subject: =?utf-8?q?=E3=83=86=E3=82=B9=E3=83=88?=
Subject: =?UTF-8?b?44OG44K544OI?=
go のジェネリクスと型の集合
0時に寝て何度か起きて7時に起きた。22時頃に素麺を食べたら夜に吐き気がして食べるんじゃなかった。
ストレッチ
今週はいつも通りの普通の1週間を過ごした感じ。休養していたわけでもなく負荷が高かったわけでもない。私の感覚的には右太もも後ろの筋と右腰の張りが強かった。トレーナーさん的には腰は大丈夫そうに言っていて、股関節全体の硬さは常態化しているものだけど、すねの筋もやや張りがあったように話していた。私の感覚とトレーナーさんの感覚がちょっとズレていた。今日の開脚幅は開始前154cmで、ストレッチ後158cmだった。一時期の3-4月の疲弊した状態ではないので一番悪い時期は脱したようにもみえる。
go の学び直し
Gopher塾 #5 - ジェネリクスが書けるようになろう に参加した。
すでにうちのプロダクトはジェネリクスを使った開発を行ってはいるけれど、私自身まだ曖昧なところがあったり、どういった設計がよいのかの手探り状態である。go はオブジェクト指向言語ではない (それ自体は構わない) ところが java のジェネリクスとは異なっていて、なにがその根本的な違いになっているのかを、私の中ではまだ理解できていなかった。その答えがこの勉強会に出てわかった気がする。もう少し独学して理論的に理解する必要はあるが、私に足りなかった知識が参加前よりも明確になったのでこの後の学習は容易に思える。
イベントではワークシートに自分で理解したメモや課題の回答を書き出すよう tenntenn さんが促していた。私はメモを自社の課題管理システムに書いていたのでワークシートには書いていないが、自分の理解を書き出すことの重要性は同意できる。tenntenn さんは次のように説明していた。
概念や理解したことを自分の言葉で表現できるか?を確認するために書くことは大事。
もし書いた内容が間違っていても、間違ったことを認識できることにも意味がある。
つまり、学んだことを書くことは正しくても間違っていても得られるものがある。
この考え方は私が提唱する課題管理にも通じている。なぜ書くかの理由の1つは自分の理解を整理するためでもある。そして、その文章を外部から監視できることで上長が助言できる。私にとっては習慣として身に付いた事柄ではあるけれど、改めてこういうことをチームのメンバーに啓蒙したり、開発ガイドに書いておくとよいように思えた。go の勉強会に参加して課題管理で学ぶことがあるとは思わなかった。よいこと尽くめだ。
閑話休題。本題のジェネリクスについて3割ぐらい知らないことがあった。私が java のジェネリクスと比べて go のジェネリクスを完全に理解できていなかったところの要因は 型の集合 (Type sets) の概念を理解できていなかったところに起因する。go ではジェネリクスを導入するにあたってインターフェースに型の集合という概念を導入した。それまでのインターフェースはメソッドの集合を管理するだけだったが、型の集合も管理できるようになった。また go には Underlying types という概念が当初から存在したが、それを意識してプログラミングすることはなかった。これを日本語にすると「基底型」となるが、オブジェクト指向言語で言うところの基底型とはまったく異なる。なにせ継承できないのだから。インターフェースに型の集合として次の記述ができるようになった。Underlying types はこれまで概念としてしか存在していなかったのがチルダを用いた文法で表現できるようになったため、その理解も強いられるようになった。
Go の “Type Sets” proposal を読む によると、現時点での型の集合とは次の2つを指す。
- ~T approximation element (近似要素)
- T | U union element (合併要素)
union 型のようなものは他言語でもある概念なのでイメージしやすいが、Underlying types をチルダを使って指定するのは go 独自?の概念なので新たに学び直す必要がある。