集中開発の1ヶ月間

プロジェクトの進捗報告

出張したときの月例報告の19回目。前回の進捗報告はこちら 。この開発フェーズは私が経営陣へ進捗報告するものの、引き継いだマネージャーにも同席してもらって、こんな打ち合わせをしているというのを知ってもらう機会にしている。この1ヶ月間の進捗やこの開発フェーズでやろうとしていることを一通り説明して、あとはざっくばらんに経営陣と雑談するといった機会にもなった。最低限、開発のボトルネックになりそうなところは私が集中開発して解消したので見た目上はよいペースで進捗している。

進捗報告して雑談しているうちに、もうこれ以上は私がお手伝い先へ提供できる新たな価値はなさそうに思えてきた。ここからは課題管理できている issue を優先度順にひたすら fix していく、よくないところはリファクタリングする、開発の負債やボトルネックを解消していくといった、より実践的な実務が求められる。課題管理を含むプロジェクトマネジメントやチームの情報共有を改善することで開発をうまくまわしていくフェーズは十分にメンバーが実践できるようになったと思える。自身の引き出しの中身を払い出してしまって、なにも残っていないような寂しさを感じるようになった。

いまマルチブラウザ/デバイスのテストの自動化のために BrowserStack というプラットフォームを評価している。まだ評価中なので採用の可否はこれから判断するところだが、採用したらコストがかかるのでその話題も経営陣に伝えてその場で議論したりしていた。おそらくこのサービスは Selenium Grid を使っているのではないか?と推測される。うちのプロジェクトだけでなく、社内インフラとして全社共通のテスト基盤を作るという施策もあるかもしれないと話しが発散したりもした。開発においてプラットフォーム的な投資も大事だと考えられている。うちのプロダクトで作る課題管理のメトリクスに、プラットフォーム投資のための見える化ができる機能もあるとよいのかもしれないと思ったりしていた。

実際に動くようになってからわかること

目次

東京出張しての、隔週の定例会議にて、ある仕様について話しをした。これまでもずっとそういう仕様ではあったが、実際の本番運用が近づいてきて、実運用を考えているうちにある要件が出てきた。しかし、現状のシステムの構成上、その要件は満たせないことがわかった。1年半にわたって開発してきて初めてこの要件は現状のシステムの制約でできないと発言した。出来ないものは出来ないで仕方ない。それでも今更そんな要件が出てくるところに課題管理として出来ていなかった反省もあるし、気付きが足りなかった。私は20年も開発してきたからたいていの要件への対応は出来るだろうと、自身の経験から過信してしまっているところもあったなと思えた。やはりお仕事になるエンタープライズの要件はなかなか難しい。難しいからお客さんはお金を払って si 的なお仕事になるとも言える。自分への情けなさとそれでもできる範囲でやっていかないといけないという現実とを実感したひとときだった。

親からの依頼

前泊移動

親からの依頼 16時半移動の19時半から友だちと東京で飲み会予定になっていた。昨日リリース作業があったそうでお仕事の影響で行けないという話しになったので新幹線の移動時間も19時52分〜に変更しての前泊になった。スマートEX は新幹線の予約変更を直前までできる。こういう予定が曖昧なときに便利なのを実感した。朝にスーツケースを準備してオフィスに持ち込んで16時から移動できるような段取りは組んでいたものの、なんか16時から移動というのも違和感があったのでキャンセルになっていつも通りのスケジュールで1日を過ごせたことはよかったと思う。

城崎温泉のアテンド

親が親戚と一緒に城崎温泉へ行きたいというので11月の下旬に旅館の予約をとった。サイトで条件を入れて検索したら、きのいえ のすぐ前にあった 緑風閣 がヒットしたので (前を通って) 知っている旅館なのでここでいいなと4人一部屋で予約した。私が車で運転して連れていって案内したりすることになりそう。うちはもともと旅行したりする家族ではなかったし、親がどこかへ行きたいということもあまりないのでこういった機会はなるべく要望に応えるようにはしている。過去2回うちの会社の合宿として城崎温泉へ行った話しを親にしているうちに関心をもったようだ。別に狙った意図ではなかったが、親が楽しむ機会になるならそれはそれでよかったなと思える。

夏休み4

目次

今日はバテてお休みしていた。

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
		}
	})
    ...
}

生活のリズムづくりの1ヶ月

歯科検診

17時から歯科検診へ行ってきた。スタッフに「痩せてませんか?」と尋ねられて3ヶ月ぶりならそれほど変わらないんじゃないかと返したが、そのスタッフが私の担当をするのは2月以来だったらしく、それならかなり変わりましたと話していた。たまにしか行かないのに、首まわりが全然違うと言われて、半年前の体型を覚えているんやなと思ってこっちが驚いた。たまに会う人向けのお断りとして「癌ではありません」と説明しといた。

生活のリズムづくり

ここ1ヶ月ほど開発者へ戻るための取り組みをしてきた。昼間にお仕事でコードを書いて、晩ごはんを食べてから、夜にコードを書くのが習慣的になってきた。概ね1日の作業時間が10-12時間になってきている。夜に開発できている日はだいたい20-21時頃から24時頃までコードを書いている。夜は割り込みが入らないので集中できる。今日も晩ごはんを食べて22時前から翌2時半ぐらいまでコーディングしていた。ファイルのアップロード/ダウンロードを扱う汎用 api を実装した。

いまの開発フェーズでは 過去の残課題 が多い。それはこれまでの私のマネジメント不備でもあるし、知見を得たことでアーキテクチャの不備や再設計のリファクタリングができるようになった課題も多い。技術的負債が溜まっているとみなせる。いずれにしても、実運用を間近に控えて直せるところをできるだけ直しておきたい。当初は私が改善する issue が仕様変更になるためにプロジェクト全体のボトルネックになってしまっていた。なるべく初期の開発で ボトルネックを解消 してからもペースを落とすことなく、集中して開発作業を継続できている。スケジュールの前倒しとまではいかないが、後手にまわっている印象はなく迅速に対応できている。個人的にもよいリズムと集中力が出てきたと感じている。その視点からみると、いま開発に向いている集中力をこれまでは体脂肪コントロールや運動に費やしてきたこともわかる。だから短期間に大きな成果が出た。人の可処分時間は決まっている。継続的になにかに取り組むと1ヶ月も経てば実感できるぐらいの成果がでる。もしかしたら私がフルタイムの開発者として作業できるのはあと3ヶ月になるかもしれない。悔いの残らないよう、できるだけ集中して取り組もうと思う。

ファイルアップロードのインターフェース

今日も昼間は普通にお仕事で開発して、お仕事を終えて晩ごはんを買い出しへ行ってきて、オフィスで晩ごはんを食べてから夜のコーディングに戻るといった一日になった。昼間は会議や問い合わせ対応、他のメンバーの進捗をチェックしたりなど、ちょくちょく割り込みが入る。夜はそれらがないことがわかっているので3-4時間集中してコーディングできる。

echo のファイルアップロードのサンプル

メンバーがファイルを受け渡しする web api のインターフェースがよくわからないということで私がサンプルを作ってみることにした。echo には File Upload のサンプルも紹介されているからすぐにできる。歴史的にブラウザからのファイルアップロードを前提にすると、ファイルを扱うときは次の Content-Type を使う。

Content-Type: multipart/form-data

これを echo のコードで書くと次のようなインターフェースとなる。

type MyRequest struct {
	Type      string    `form:"type" validate:"required"`
	Operation string    `form:"operation" validate:"required"`
}

func handle(c echo.Context) error {
	req := MyRequest{}
	if err := c.Bind(&req); err != nil {
		return err
	}
	if err := c.Validate(&req); err != nil {
		return err
	}
	file, err := c.FormFile("file")
	if err != nil {
		if errors.Is(err, http.ErrMissingFile) {
			return echo.NewHTTPError(http.StatusBadRequest, "file is required")
		}
		return err
	}
    ...

ファイル情報を MyRequest で管理できるとリクエストパラメーターを一元管理できて望ましいが、次の issue によると現時点ではそれはできないらしい。

curl コマンドでリクエストするには次のような cli になる。

$ curl -i -X POST -F type=misc -F operation=add -F file="@myfile.data" ...

寝ている間に再設計

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

マネージャーとの 1on1

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

CPAP の中断

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

ツールの再設計

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

うまく進捗した翌日に詰まる

目次

昨日は開発が進捗したからお仕事も早めに終えたし、気分もよかったものの、今日から新たな issue でテストデータの生成ツールを作り直そうと再設計していた。過去にある程度の機能を作り込んだ知見があるから、すぐできるだろうという見通しで着手したものの、あーでもない、こーでもないと試行錯誤していて、うまくいかない。まる一日調査もしながら考えていたのに、これといった手応えはなくて、久しぶりにこのツールをどう作ってよいかノーアイディアのような雰囲気になってしまった。サーバーサイドやインフラのツールをいろいろ作ってきた過去の経験や蓄積があるから、あまりこういう状況になることはない。なまじ1度作った機能を改良するため、うまくいかないところや難しい課題もある程度わかっていて、それらの改善案が出てこないといったこともあったのかもしれない。プログラミングって、行き詰まったときの孤独感や焦燥感との戦いもあるなと開発の勘どころのようなものを思い出してきた。興に乗らなくて夜のコーディングは行わずに普通にお仕事を終えた。

小雨が降る中のパンク修理

目次

先週末に pr を送っていたから午前中にそのマージ作業をやって、他にもいくつか開発が順調に進捗したにもあって早めにお仕事を終えて自転車のパンク修理へ出掛けた。夕方から雨が降ったりやんだりで微妙な天候だったものの、大きく雨には降られなかったのでそれはそれでラッキーだった。

一番近い自転車屋さんへパンク修理にもっていくと、パッチ対応はしていなくてチューブ交換になってしまう。たまにしかないことではあるけど、チューブ交換で5,500円もかかる。ちょっと高い。他を探す時間もないから仕方ない。自転車を預けて1時間ほど待ち時間があり、その間にスーパーへ行って買いものして家に戻り、すぐにまた自転車屋さんに受け取りに行くといった感じで2時間ほどかかった。

軽く雨降りの中、傘をさして行ったり来たりしたのもあって疲れて夜のコーディングは行わずに早くに休んだ。

空き時間の草刈り

目次

田んぼの状態がよければトラクターで耕したり畝づくりをしたりするところを、それはまた雨が降った後に持ち越すことにした。また近いうちに実家へ帰る。せっかく帰ってきた機会でもあるから別の田んぼの草刈りをすることにした。どうやら親は土日月とパートに出掛けているらしく、今日もいないので代わりにやっておく。7時半ぐらいから草刈り機の刃を古いものから新しいものへ交換した。だいたい実家へ帰ると7時ぐらいから田んぼ仕事になる。家にある草刈り機の燃料 (混合ガソリン) がなくなるまでと親と話していたものの、実際に作業してみたら8時半にはなくなってしまい、それから神戸へ戻ってもよかったが、せっかく帰ってきたのにあまりにも作業しないと罪悪感を感じてしまった。

近所の 農業屋 へ行って混合ガソリンを購入してきてバテるまでやろうと燃料を入れ替えながら草刈りを何往復かした。暑くなって体力的にバテたらやめようと思っていたものの、休憩しながら、結局は12時前までやっていた。暑さにも慣れたのかな?たぶん体脂肪コントロールのための運動で体力がついたせいか、これまでよりも草刈りを長く続けられるようになっている気がする。それでもすべて刈り込むことはできなかったが、8割ぐらいの草を刈ったので次回また帰ったときに容易に終わらせられるだろう。普通の草刈り機は若干シャフトが短くて私にとっては腰をかがめないといけないのがしんどい。調べてみたら ロングシャフトの草刈り機 もあるらしい。記事を読んでいて草刈り機は2サイクルエンジンだとばかり思っていたら4サイクルもあって、エンジン部が大きい分の重量のデメリットに対して、燃費やトルクのメリットもあるらしい。うちには2サイクルエンジンの草刈り機があるから4サイクルも試してみたくなった。

お昼から戻ってきて14時過ぎには神戸へ着いた。それからオフィスへ行ってもよかったが、家でくつろいでいるうちに疲れもあって気付いたら夕方まで寝ていたのでそのまま休んだ。