あぼぼーぼ・ぼーぼぼ

のんびり生きたい

書籍『リーン開発の現場 カンバンによる大規模プロジェクトの運営』を読んだ

社内で今度輪読会をするので先回りして読みました。

10年前の書籍ですが今でも全然タメになる話ばっかりでした。物理カンバンボード推しの本書ですが、当時から物理カンバンの補助としてオンラインツールを検討しているという話があったり、リモートワーク化が進んだ今も別にホワイトボードのように使えるオンラインツールが増えてきたので特に時代遅れという感じでもないですしね。

多くの章でWIP制限が解決策として出てくるため、試したくなる人も多そうです。11章「WIPをマネジメントする」を読んでいて、自分が想起するWIP制限と兼務って相性悪いんだろうなぁと思い、なぜかを考えると多分タスクが個人に紐づいている状況が原因の一つっぽいなぁと思ったり。

他には、プロダクトの完成に必要な技術的な課題を技術課題と呼んで、機能開発の付箋とは別に枠を設けているあたりの話は参考になりました。

ストーリーポイントの分布が一定であれば、完了したストーリーポイントではなく完了した機能数でベロシティを測っても精度は変わらない、みたいな話は目から鱗でした。こういうのも囚われだよなぁ。

18章で紹介されていたテスト自動化のステップは実践で結構参考になるかもと思いました。イシューを進めるうえで言語化する一助として使えそうです。

20章でシステム思考が出てきてウォ〜となったり、あと16章の内容が全部最高でした。

Amazon: https://www.amazon.co.jp/dp/427406932X

書籍『人が増えても速くならない 〜変化を抱擁せよ〜』を読んだ

ソフトウェア開発の特徴を、ソフトウェア開発に携わるエンジニアではない人に簡潔に伝えるための本、といった感じでしたが、エンジニアが読んでもチームを俯瞰して見る際に役立つような再認識することがあるんじゃないかと思いました。

見積もりと約束が受発注の関係を作ってしまうという話とか。機能ありきで期間を見積もるのではなく、期間ありきで機能を見積もると。できる範囲で小さい動くものを作っていく、動くものからフィードバックを得て、また小さい動くものを作っていくと。大きいプロジェクトほど不確実性が高いので、小さいプロジェクトに分割して小さく挑戦し続けると。そうして近いほど具体的で遠いほど曖昧なロードマップを常に見直して更新し続けると。

あとは最後の方、プログラムは最も低い品質に引っ張られるという文脈で、若いエンジニアをチームに追加しても単にリソースの足し算にはならないという話。t_wadaさんの発表資料『質とスピード(2022春版、質疑応答用資料付き)』に出てきた、「質」と「スピード」トレードオフではない、ならば「質とスピード」は何とトレードオフなのか、に対する答えとして「教育」を挙げていたのを思い出しました。

Amazon: https://www.amazon.co.jp/dp/4297135655

書籍『STAFF ENGINEER』を読んだ

Amazon: https://www.amazon.co.jp/gp/product/429607055X

マネジメント責務を持たないという意味ではIC (Individual Contributor)だと思うんですが、本書でアーキタイプと呼んでいる4つの典型的な役割はぼくが想像していた以上に多様でした。

より難易度の高い問題を自身の力で解決するというイメージを持っていましたが、「難易度の高い問題こそ他の人にさせる」という話や「個人ではなく組織としての成果」みたいな話が出てきたりもして、影響を与える範囲が広くなっていくイメージに変わりました。

重要なことに力を注ぐ、という話の中で出てくる「つまみ食い」「おめかし」「幽霊追い」などは「やめること(やらないこと)」として意識しふるまおうと思いました。

あとは文章をちゃんと書く、書き続けるのも共通する要素なんだなぁと思ったり。

普段あまりキャリアのことを考えないので、良い刺激になる本でした!

書籍『Clean Craftsmanship』を読んだ

Craftsmanshipの規律、基準、倫理について書かれた本書。楽しかったし刺激受けました。

規律の一つであり要であるテスト駆動開発の説明には具体的なコードが書かれてあり、追体験できました。ボウリングのスコア計算の例を初めて見るなら、本の続きを読み進める前に自分で実装してみると楽しいです。その後読み進めると、スペア、ストライクの実装ができた段階で10ゲーム目のテストケースも通る、ここが秀逸でした。

ワードラップの例も楽しかったです。これも自分で実装してみましたが、最終的に以下のようになりました。本書の実装とは違う方針であり、テスト駆動開発には分岐点がある、という話を体験することになりました。

package main

import "strings"

func Wrap(s string, n int) string {
    if n == 0 {
        return s
    }

    result := ""
    row := ""
    words := strings.Split(s, " ")
    for i := 0; i < len(words); i++ {
        if i == 0 {
            row += words[i]
            result += words[i]
        } else {
            appendix := " " + words[i]
            if len(row+appendix) > n {
                row = words[i]
                result += "\n" + words[i]
            } else {
                row += appendix
                result += appendix
            }
        }
    }
    return result
}

テストダブルの説明も具体例が交えてあって分かりやすく嬉しかったです。xUnit Test Patternsを読むのはハードルを感じるので。

リファクタリングを特別扱いしない。常にやる、継続的にやる。リファクタリングはスケジュールや計画には決して表れない。時間を確保する必要はない。許可を得る必要もない。トイレに行ったら手を洗うのと同じ。常識的な配慮として常に行うべきもの。

常にそのときのベストを尽くすこと、そのために継続的挑戦的学習者であろうと思いました。

書籍『ゾンビスクラムサバイバルガイド』を読んだ

https://www.amazon.co.jp/dp/B0BH3XSNKB

普段自分のチームでスクラムは使ってないですが、ゾンビスクラムっていう言い方が面白くて読みました。スクラムに焦点が当たっているものの、スクラムに限らず比喩としてのゾンビに立ち向かう際のヒントもいくつか手に入りそうです。

ゾンビスクラムとは表面的にはスクラムに似ているけど、ステークホルダーが求めるものを作る、速く出荷する、継続的に改善する、自己組織化するといったことがなされていないもの。1部ではこのゾンビスクラムスクラムについて説明し、2部以降はゾンビスクラムで見られる症状と原因、そして前進するための具体的な実験が書かれています。2部以降の書き方が実践的で結構好きで、症状の考察と、具体的で試してみたくなる実験がたくさんあって、ゾンビに立ち向かう人にとっては嬉しいんじゃないかな〜と思いました。

公式サイト https://zombiescrum.org/ ではゾンビ度合いの診断とかできるみたいです。応急措置キットを見ると、自分がどう振る舞うといいかイメージがつくかも。

ゾンビスクラムと向き合ううえで根本のスクラムの目的に立ち返ることは大事そうです。「なんでスクラムを使ってるんですか?」「スクラムに何を期待していますか?」みたいなのが根本に迫る質問になるんでしょうか。あとは、「起こらないかもしれない未来について、リスクの高い過程にもとづいた意思決定を行うのではなく、これまでに検出したシグナルにもとづいて行う。これが経験主義である。p38」というのも好き。

書籍『Go言語プログラミングエッセンス』を読んだ

https://www.amazon.co.jp/dp/B0BVZCJQ4F

知っていることは復習がてらfmfmと読めて、知らないこともたくさんあって楽しかったです。つどつど見返すGoの本がまた増えましたね。

以下、メモの中からかいつまんで。

1章はGoの特徴に触れながらなぜGoが選ばれているのかという話。レビューのしやすさ、周辺ツールの充実感はたしかに感じます。

3章は基本的な文法について。Clockwise Spiral Ruleは初めて知りました。あとはvar _ I = (*foo)(nil) のようにブランク変数を使うことで、型がインタフェースを実装していなければコンパイルエラーで(なんならその前にIDEが検知して)気づけるというテクニック便利だなと。

4章は基本とベストプラクティス。recoverはまだ使ったことないですが、手札として持っておきたい。その後のコラムが面白かったです。発生しうるエラーを明示的に伝えるコード例は他の言語の人からするとギョっとするかもですね。あとは、ビルドタグにignoreを指定すると、サンプルコードとしてmain関数書かれたコードも共存できるのは便利そうでした。

5章はWebアプリケーション関連、普段触れている業務の世界に近いのもあって復習がてら。色々な書籍を読んだつもりでしたが、html/templateパッケージについてざっと触れられたのはこれが初めてだったかもしれません。

6章は速いプログラムのためのテクニックということで、個人的に最も関心のある領域。特に最初に書かれてあった、I/Oが絡む処理など並行処理を行う部分の見極めが重要、というのは煎じて飲みたいくらい意識したいと思いました。あとはCとの比較検証も面白かったです。

7章はテストまわり。t.Shortは知らなかったのですが、例えば統合テストをビルドタグで分けるような使い方はイメージしていましたが、t.Shortを使いたい場面ってどんなのがありますかね。テスト関数単位でスキップできるので、時間のかかるベンチマークを普段はスキップするとかに使えそうかな。

8章はベンチマーク。業務でも計測しつつチューニングしているのでかなり興味ある領域。ベンチマークの比較について、昔なにかで見たことあるなと思ったらmattnさん(著者)のブログでした golang でパフォーマンスチューニングする際に気を付けるべきこと | Big Sky

9章はCLIアプリケーションで、実際にお題を元に作っていくので、ハンズオンっぽく読めます。データベース操作はここで初めて出てきますが、この後12章でしっかり説明されますね。CLIは標準ライブラリだけで作るより潔くcobraなどのパッケージを使ったほうが色々ラクですね。

10章はWebアプリケーションのハンズオンのような内容で、9章もそうでしたが、TODOアプリ、リマインダー送信アプリのように分けてそれぞれ作るように書かれているところが好きでした。

11章はGitHubを使ってパッケージを公開する一連の流れが分かります。この章だけ見ても、1章に書かれていた「パッケージ公開の簡単さ」を感じられるはずです。「当然ですがテストを書きましょう p278」いいですね。

12章はデータベースについて。要件に適したパッケージ使うのがいいですね。

13章はクラウドサービス関連で、どのクラウド使うにせよ簡単にデプロイできるなぁと改めて思いました。あとバイナリサイズを小さくするコラムは役立ちそう。

Go 1.19.3 and 1.18.8 security fix の内容を読んだ

今更ながら Go 1.93 及び 1.8.8 のマイナーリリース、security fix の内容について。

リリース内容はこちら

groups.google.com

どういう問題があったか

github.com

Windowsにおいて、環境変数をサブプロセスに渡す際にヌル文字(NUL)が含まれていると別の環境変数を設定できてしまう。例えば “A=B\x00C=D” という文字列を解釈すると環境変数として A=B, C=D と設定できるということ。

修正内容

github.com

diff の上から見ていくと、まず env_test.go は今回の脆弱性がテストケースとして分かりやすく表現されていて良い。

次に os/exec/exec.go が修正されているが、コミットメッセージを見ると、一応冗長なチェックを追加しといた(「Add a redundant check to os/exec as extra insurance.」)と書いてあるため、一旦スルー。

本丸は syscall/exec_windows.go の修正で、createEnvBlock 関数に変更が加わっている。

中身を見る前に、syscall パッケージについておさらいすると、syscall パッケージは OS のシステムコールを担当するパッケージで、syscall パッケージ内にある各 OS 専用のファイルでシステムコールの実装が管理されている。例えば、syscall パッケージの StartProcess 関数の GoDoc には「StartProcess wraps ForkExec for package os.」と書いてある。これは Windows なら exec_windows.go の処理が呼ばれ、UNIX なら exec_unix.go の処理が呼ばれるように、実行環境に合わせた形でビルドされる。ちなみに、Go 1.4 からは syscall パッケージは基本フリーズされ、OS 固有の実装は golang.org/x/sys で管理されている(参考:https://go.googlesource.com/proposal/+/refs/heads/master/design/freeze-syscall.md)。

createdEnvBlock 関数に戻ると、この関数はざっくり言うと環境変数を受け取って、その後の処理に必要な形に変換している。今回の修正では、error を返すようになった。どういうときに error を返すかというと、if bytealg.IndexByteString(s, 0) != -1 { のときに error を返すようになった。

この bytealg パッケージの IndexByteString 関数が何をやってるか調べる。まず bytealg パッケージは internal なパッケージだった。IndexByteString 関数は、pkg.go.dev を見ても特にコメントが無かったため、実装を見にいく。

pkg.go.dev

bytealg.IndexByteString 関数の実装は多分こちら。

go.dev

実装を見ると、文字列とバイトを受け取って、文字列を一文字ずつ for で回してバイトと同じ要素が見つかったらそのインデックスを返し、見つからなかったら -1 を返すということをしている。

(internal パッケージなのでコピペして) playground で動かしてみると、実際にヌル文字がインデックス3つ目にあることを検知できた。

package main

import "fmt"

func main() {
    fmt.Println(IndexByteString("A=B\x00C=D", 0)) // 3
}

func IndexByteString(s string, c byte) int {
    for i := 0; i < len(s); i++ {
        if s[i] == c {
            return i
        }
    }
    return -1
}

よって、Windows において環境変数の文字列を解釈する処理中に、ヌル文字を見つけて error を返すような変更が加わったということが確認できた。