Julio Biason 氏の『30年のソフトウェア開発で苦労して学んだこと』が面白い。

私が普段の仕事で意識して心がけていることをまとめる。 すべてを常に実践できているわけではなく自戒を込めて。 普段考えているのは個人としてチームとしていかに生産性を高めるか。 理想は携わったプロジェクトはすべて技術的に成功させることである。 実際は技術的に成功してもビジネス上成功しないとお金が入ってこないのだが、 あいにく語れることは何もない。

プロジェクトマネージメントやチームワーク系で一番好きな本は トム・デマルコとティモシー・リスターの『ピープルウェア』である。 読む必要はなく、その副題がすべてである。 「ヤル気こそプロジェクト成功の鍵」 これ本当。 ヤル気を挫く原因となるものは排除しよう。

ソフトウェア開発とひと括りにして話をすると起こりがちなことは ソフトウェア技術者同士のバックグラウンドの違いにより話が噛み合わないことである。 The Joel on Software の5つの世界である。 共感できなかったら異なる世界の話なのであろう。

プランニングでの心がけ

ソフトウェア開発は開発者が思っているよりも莫大なコストがかかる。 大抵は開発者の見積もりの3倍は工数が掛かる。 開発せずにすむならば、しないのが最善である。 作る必要もないのに始めてしまっているプロジェクトをいくつか思いつくのではないだろうか。

基本設計やフレームワーク選定など 開発の方向性の間違いは他の生産性向上の努力が軽く吹っ飛んでしまうほどに、時間を無駄にしてしまう。

プロジェクト開発当初にチームの技術者全員が合意した開発の方向性が その後間違いであることが徐々に判明した場合は仕方がない。 当時の人類の知識ではその判断が最善であり、 そのことに気づくために時間が必要であったと諦め、新しい方針で作り直すしかない。

しかし、失敗する方向性は開始時点ですらチーム内で意見が分かれることもよくある。 技術者同士の意見の対立は各自がよりプロジェクトを成功させるために考えた結果起きる。 頭ごなしに一方的に決めてしまうと、 不本意な方針を選ばされた側はやる気が損なわれる。 また、プロジェクトが失敗すれば自分の正しさが証明されたことにもなるため、やる気が起きない。

各技術者が成功すると信じる方針で開発するのが望ましい。 20%ルールのように各自の自由な方針で開発する。 まとまった時間を確保してプロトタイプする。 チーム内で意見の別れたグループ同士でコンペする。

プロトタイプで起きる失敗は 結局商品品質を達成できるかが分からないことである。 プロトタイプを作って動いているので行けるだろうと判断すると、 完成間近の QA で商品品質を達成できないことが起こりがちである。 製品実績のある技術を使うのが無難である。

新しい技術を学びたいだけの理由でそれを新規プロジェクトで採用しようとする人がいる。 技術者が自分のキャリアをよくしたい気持ちは理解できるし、 時代遅れの技術だと採用面で不利になる。 しかし、失敗できないプロジェクトで流行りの技術に飛びつくのは諌める。

チームワークでの心がけ

ソフトウェア開発でチームワークというとソフトウェア開発者同士のチームの話になりがちだが、 人事や経理、デザイナー、テスターなど10くらいの小さな会社ならば他職種も同じひとつのチームと認識できただろう。 ソフトウェア開発者がソフトウェア開発に専念できるのはチームワークのお陰である。 そう考えるとチームというのは本当にありがたいものである。

しかしながら、ある程度大きな会社で働くソフトウェアエンジニアにとってチームと言えば、30人以下のソフトウェア開発者の集団である。 ここではその話である。

当然だが個人よりもチームの生産性を上げることが重要である。 必要なときは個人の成果を犠牲にしてチームの生産性を優先する。

ビルドシステムが不安定だったり低速だったりするとチームの生産性に影響する。 個人的な経験上、やりたがる人が少ないためにビルドシステムは放置されがちである。

ビルドブレイクやクラッシュバグを混入させるとチームの生産性に影響する。 即座に対応する。 自分の変更ではなくても、状況次第では自分の作業を後回しにして対処する。

帰宅前や有給休暇前にはリポジトリに変更をコミットしない。 コミットしたい気持ちを抑えるのが難しいのはよく分かる。 なぜなら、今すぐコミットしないと、後日に最新をマージするためにコンフリクト解決して、テストし直しになるから。 しかし、ぐっと我慢する。

チームの生産性向上のためのツール作成などは専属チームが望ましい。 しかし、大抵の現場は開発者が片手間でやっているだろう。

チームの士気が低く、何もかもがボロボロのプロジェクトに運悪く配属されることもある。 貴重な人生の時間を無駄にしないためプロジェクトから脱出するのも懸命な判断である。 しかし、逃げ出せない事情があったり、あえてそのプロジェクトを成功に導く道を選ぶこともある。 そのような場合、まるで賽の河原の石積みのような気分になるため、モチベーションを維持することが不可欠である。 そのためには開発の土台から立て直す必要がある。 ビルドシステム、自動ビルド、自動テストなどから順番に立て直していく。 まとまった時間が確保できない場合でも、一日一時間だけでも確保して徐々に進捗させる。

プログラミングでの心がけ

元記事の “Data flows beat patterns” には大いに同意する。 データの流れを把握することで コードの全体像を掴むことができる。

もうひとつ大事なことがレイヤーを理解すること。 移植レイヤー以外で OS の API を呼んだり、 上のレイヤーが直に下のレイヤーの API を呼んだりすることは layer violation と言われるやってはいけないことである。

元記事の ‘Keep a list of “Things I Don’t Know”’ にも同意。 ソフトウェア開発スキルを高める上で勉強は欠かせない。 ソフトウェア開発の技術力は知識量と論理的思考力である。 わかないことを百個、千個と潰していくと技術力が向上する。

論理的思考力が重要であるが、残念ながら向上する方法はないように思う。 当たり前のことをじっくりと考える。 限界的練習で向上できるのかもしれない。

元記事の “Code style: Follow it” も同意。 コードスタイルは「まわりのコードに従う」。 本来ならばこれだけで十分なのだ。 コードをみただけで複数人で開発した形成が残ることや、 ましてや誰が書いたか分かってしまうようなことは恥ずかしいことである。

バグが見つかるので dogfooding する。

デバッグ中にそのバグが混入した変更のチケットを見ても知りたい情報がなかったり、 自分の変更に数年後にバグが発覚したがなぜそのようなコードを書いたか全然思い出せなかった経験はだれしもあるだろう。 記憶はすっかり消えてしまうため、 ドキュメントやバグトラッカーに情報を残す。 立ち話で議論した内容も忘れないうちに文字に起こしてバグトラッカーに情報を残す。

デバッグでは仮説を立てて検証することの繰り返しとなるのが望ましい。 元記事ではデバッガーに懐疑的だが、検証するときにはデバッガーを使ったほうが断然早い。 よくないデバッグのやり方は漫然とステップ実行し続ける状態である。 皆目検討がついていないときはにはやってしまいがちではあるが。

ドキュメントはソースコードのそばに置く。 コードと同じディレクトリ置いて、コードを変更したときに必要ならば同時にドキュメントも変更しレビューを受ける。

ジョエル・テストは今でも有益である。 マイクロソフトがワードのデスマーチから学んだ教訓である 特に5番目の『新しいコードを書くまえにバグを修正するか?』に同意する。

大いに賛同する他の記事を挙げておく。

API デザインでの心がけ

元記事での “Don’t use Booleans as parameters” と “Be explicit with what you use; sleepForSecs and sleepForMs” が API デザインについてである。

boolean の件は Qt の API Design Principles にも同じ話がある。

これらは根源は同じで、 API を使う側をどのようなコードにしたいかを意識して API を設計することである。

元記事の “Beware of interface changes” で インターフェイスの変更を意識する話はプロとしては当然意識すべきである。 API 互換には2つのあって、ソースコードレベルでの API 互換とバイナリレベルでの API 互換である。 オープンソースライブラリのAPI 互換を監視している abi-laboratory.pro では

ABI = API + Compiler ABI

と定義している。 バイナリレベルでの API が ABI で、ソースコードレベルでの API が API である。

たとえば、enum の順番を変えたり、struct の途中にメンバを追加するのはソースコードレベルでの API互換は維持されるが、 バイナリレベルの API 互換は壊れる。 一方で enum の名前を変えたり、メンバの名前を変えるとソースコードレベルでの API 互換は壊れるが、 バイナリレベルの API 互換は維持される。

ファイルにデータを保存する際もデータのフォーマットは API 互換と同様に注意が必要である。

コードレビューでの心がけ

既に元の開発者がチームを去ってしまったなどに理由により 理解していないコードをレビューすることになることもある。 実は理解してもいないのに LGTM したパッチがバグを引き起こしてバツの悪い思いしたことがある。 わからないことはすべて質問する。 思いつきも書き記しておく。 理解してもいないのに LGTM しない。 そうすることで記録が残る。 くだらない質問であってもパッチ作成者は質問に答えることで自分の間違いに気づくこともある。