- 多くのプロジェクトでは QA施策 が後回しにされ、リリース直前の大規模なQAスプリントに頼った末、次のサイクルでも同じ混乱を繰り返している
- コンピュータサイエンス教育はアルゴリズムや言語、プロジェクト管理には時間を割く一方で、ソフトウェア品質保証 を実務レベルで扱わないことが多い
- 会社では予算不足、開発遅延、スコープ拡大が起きるとQAが真っ先に削られ、最低限の非構造的テストしか経ていない 脆弱なソフトウェア が配布される
- QAを説得するには、「より安定する」といった抽象的な表現よりも、実施しなかった場合のコスト を開発コスト増加やリリース安定化期間の増加として語るべきである
- すべての品質体制を一度に作るより、顧客価値に直結する 中核機能 から守り、新機能は実装時点でテストを一緒に書くほうが現実的である
リリース直前へ追いやられるQA
- 多くのプロジェクトでは重要な 品質保証施策 が欠けたまま開発が進む
- 必要性を理解していても、実際の実行はリリース直前の大きなQAスプリントに集中しがちである
- このやり方はストレスを増大させ、ソフトウェアをかろうじて動く水準に合わせるだけで終わる
- 次のリリースサイクルでも同じ混乱が繰り返され、構造的な改善につながりにくい
教育と実務のあいだにある品質の空白
- コンピュータサイエンスの課程は主に アルゴリズム、コンピュータの動作原理、言語の歴史や概念に集中している
- プロジェクト管理の手法やScrumを学ぶ学期があっても、QAは完全に抜け落ちることがある
- 卒業生の90%以上は企業という文脈で働くため、限られた時間の中でバグのないソフトウェアを届ける能力が必要である
- 教育においてQAを軽視することは、実際の業務要件と一致していない
会社でQAが真っ先に削られる構造
- プロジェクトで予算問題が起きると、QA標準と施策 が真っ先に除外されることが多い
- QAはプロジェクト終盤に配置されることが多く、開発が長引いたりスコープが広がったりすると、品質確保に使える時間が不足する
- その結果、最低限の非構造的テストだけを実施した後、脆弱な構造のソフトウェアをリリースすることになる
- 一部のチームにはQA標準があるが、たいていはシニアメンバーが他の構成員にそれを徹底させる形である
- 標準があっても、チームがプロジェクト管理指標を満たすためにテストを書いているなら、十分な品質保証にはつながりにくい
繰り返される品質問題を断ち切る第一歩
- QA施策が欠けていると指摘するには、経験と自信が必要である
- リリース前のクランチ、障害が起きる本番システム、欠落したモニタリングは、チーム全体の負担として跳ね返ってくる
- リファクタリングのように管理者から直接見えない改善も説得が難しく、QAはきちんとやった経験がなければさらに手がかりを持ちにくい
- 繰り返し問題を伝え、議論を再び持ち出してこそ、第一歩を作ることができる
QAをお金の言葉で説明する
- 「ソフトウェアがより安定する」「保守がしやすくなる」といった言葉は、コードベースで働いていない人には具体性が伝わりにくい
- 開発者は QAをしないコスト を語るべきである
- 例として次のように表現できる
- 今やらなければ、4か月後に開発工数とコストが15%増加する
- すべての機能に単体テストを入れなければ、リリース安定化フェーズが毎回長引く
- 新機能が増えるほど副作用を毎回手動でテストしなければならず、リリースごとの進捗が落ちていく
- このような伝え方は、ビジネスや管理者に届きやすい言語である
- QA施策は最終的に、開発者と管理者の双方の仕事をより良くできる
最小有効量から始める
- QAを大きな先行投資として過剰に設計すると、プロジェクトの進行を妨げ、ステークホルダーの合意も得にくい
- 現実的な出発点は、アプリケーションの中で最も重要な部分を見つけることだ
- 通常は、アプリケーション全体が依存する特定のユースケース、機能、コア動作がある
- 顧客に価値を提供するには必ず正しく動かなければならない 中核機能 からテストすべきである
- 最小有効量(MED)は、望む結果を生み出す最小の量を意味する
- QAにおけるMEDは次のいずれかになりうる
- 手動テスト計画
- パイプライン内の自動テスト
- そのほか中核動作を保証する施策
- 中核機能を保証した後、段階的に安定性の範囲を広げていける
- 新機能ごとに単体テストを追加し、外部APIやユーザー入力のように制御できない情報も検証しなければならない
- QAも反復的かつ漸進的に改善すべきである
新しいプロジェクトで確認すべきQAの問い
- 新しいプロジェクトを始める、または参加する際には、小さな形でも QAの考え方 があるか確認すべきである
- チームは次の問いを考える必要がある
- 何をリリースするのか
- 何が必ず動かなければならないのか
- それをどう保証するのか
- どの施策を意図的に行わず、その理由は何か
- こうした内容を文書として残し、テスト計画を加えれば、ソフトウェアが前進していくための良い基盤になる
- 選んだアプローチは定期的に、たとえば四半期ごとに見直すのが望ましい
テストは実装と一緒に書く
- TDDを使わないとしても、ソフトウェアを書いている間にテストも一緒に書くことが推奨される
- 機能を実装するタイミングは、テストを書くのに適したタイミング でもある
- 実装と同時にテストを書くことで、コードが実際にテスト可能な構造になるよう強制できる
- 既存ソフトウェアに後からテストを付け足すと、コードが過度に相互依存していたり、単一責任の原則に違反していたりすることが露わになる場合が多い
- テストは、望む動作を理解し、それが期待どおりに動くことを確認したという説明になり、コードドキュメントの一形態としても機能する
プロジェクトと個人にもたらされる効果
- 品質についての議論を持ち出し、実行可能な解決策を提案すれば、プロジェクトを気にかけていることが周囲に伝わる
- 品質に関する議論は、開発者としての影響範囲を広げることにもつながる
- 開発者と管理者の生活の質も高められる可能性がある
- プロジェクトはQA施策があるとき、健全な速度で成長できる
- 全員がQAの伝道者になる必要はないが、小さなMEDから始めて、チームの中でより良い方法を示すことはできる
1件のコメント
Hacker Newsのコメント
こうした内容は教えられている。ただし、中核のコンピュータサイエンス科目ではなく、ソフトウェア工学のような選択科目にある
CMUにはソフトウェア工学の修士課程と博士課程もあり、ブログ記事が述べている内容やそれ以上を扱っている。CSとSEの間には大きな断絶があるが、「高品質なソフトウェアの作り方を誰も教えない」というほどではない
皮肉なことに、学生時代はソフトウェア工学の科目がいちばん嫌いだった。UMLを厳格に守るデザインパターンの授業は古臭く見えたし、JavaエコシステムのTDDやツールを学ぶQAの授業も退屈だった。数年後、セキュリティ要件の高いソフトウェアのテストワークフローとツールを構築するチームに加わったとき、やるべきことをすでに分かっていたので同僚たちが驚いていた
たとえ教えていても、たいていは古かったり、Webアプリケーションを書くことのような非常に字義通りの内容に偏っている。実装、チームワーク、複雑なシステム構築に集中する授業があったなら、ぜひ受けたかった
こうした内容を選択科目や修士課程に置いておくのではなく、学部のソフトウェア工学プログラムが必要で、CS学生の90%はそちらに移るべきだ
コードベースはウイルス/マルウェアスキャンを提供する単純なサービスで、スキャナーとシグネチャを含め、常に追加作業が発生するよう設計していた。15年以上前のアイデアだったが、継続していく素晴らしい授業になれたはずで、学科を説得できなかったのが残念だ
学部時代を決定づけた授業とまではいかなくてもかなりそれに近く、システムを設計する人の大半がこの内容を知らないという事実には、怒りと実存的恐怖を同時に覚える
CSの学位を持つ人たちと働きやすいのは、良いアルゴリズムの必要性や、パーサや暗号を自前で実装すべきでない点を説得する必要が少ないからだ
一方でソフトウェア工学の側には、品質、チーム作業、他チームとの協業に関する素朴さが同様に磨かれていると信じられるような資格がない。ひどい未検証コードを素早く書き、問題が爆発する前に去る経験で鍛えられた人たちが生まれ、経営陣はそういう人たちを好み、後に残って残骸を片付ける人たちを見下す
明確な区切りのある文字列ベースのプロトコルはたいてい非常に簡単にパースでき、ユースケースによっては一部だけ扱えばよい。もちろんテストと機能要件は考慮すべきだ。言語を作る場合なら助言は変わるかもしれない
初心者は自前で作り、中級開発者と中規模プロジェクトはパーサジェネレータを使い、最も洗練されたパーサを保守している人たちも自前実装を好む。GCCも昔はbisonパーサを使っていたが、より良いエラーメッセージのために手書きの再帰下降パーサへ切り替え、Clangも再帰下降を使っている
個人的に知っている例外はjqだけで、そのためjqの実装では有用な構文エラーメッセージを作るのが難しい
パーサ作成は課題一つに収まるほど単純なこともあり、手書きパーサのコードは結局LL文法に近くなる。パースはコンパイラや言語ツール作成で最も簡単な部分なので、手書きパーサがチームにとって高すぎるハードルなら、プロジェクト全体が疑わしいかもしれない。パーサジェネレータを絶対に使うなと言いたいわけではないが、追加ツールでビルドを複雑にしたり、Bison・ANTLRのような古いツールを使ったりするプロジェクトより、十分にテストされた手書きパーサがあるプロジェクトで働きたい
それでも全体的な基準は20年前より高くなったように思う。たとえばソース管理、単体テスト、CI/CDはもはや議論の的ではない
「バグのないソフトウェアを期限どおりに提供すべきだ」という前提は、品質の高いソフトウェアについての文章を書き始めるにはかなり悪い出発点である。
バグのないコードをデプロイできると信じているなら、転職したほうがいい。
単体テスト、統合テスト、ユーザー受け入れテストをすべて行っても、コード変更1つはすなわち新たなバグの可能性である。開発者が「自分はバグのあるコードを絶対にデプロイしない」と言うなら、その意味をさらに問いただしたくなる。
「関数を書いた」「関数をテストした」「ネットワーク越しに呼ばれる関数までテストした」を越えると、境界条件をどれだけ適切に押さえ、QAをどれほど徹底しても、特定の設定、特定のハードウェア、特定のカーネルでは常に0-dayの未定義動作が残るのだと気づく。テスト、人の目、レビューを通過したので、ほぼバグがないと保証できると言うことはあっても、結局は指を組んで祈るしかない。
修正に1週間かかるが、ごく少数のユーザーしか、しかも非常にまれな状況でしか遭遇しないバグなら、直さなくてもよいかもしれない。
コンピュータサイエンスのプログラムもあり、インターンシップや実習を重視する大学もある。しかし多くの大学のCS学科は数学科に由来し、理論中心である。
化学が化学工学ではないのと同じで、これも問題ないと思う。大学は単なる職業訓練校ではなく、ほぼすべての学位の趣旨は思考力を鍛え、複雑な内容を身につける能力を示すことにある。
現実で役に立つかを考慮しない純粋な大学教育は教育に有害だが、理解なしにやり方だけを教える純粋な職業教育も有用ではない。ただし、実際の職業訓練校も完全にそうというわけではなく、難しい部分は飛ばすにしても、重要な事柄については深い理解を与えるほうである。
それでもプロのソフトウェアの世界を垣間見るにはよい。
こういうことは優れた開発組織で学ぶ。10〜15年前ならおおむねFAANGがそうで、今ならTailscaleのようなところがその例である。
無意味なマイクロサービスや何層ものDocker、JSONのシリアライズ/デシリアライズ層、カバレッジのためだけの単体テストを大量に置いてQuickCheck・Hypothesis・ファジングを無視するようなことをしないで済む。スタック型の変更セット、コードを書くチームのオンコールローテーション、動的リンクと強制されない依存関係エラーの最小化、マネージド言語ランタイムに合わせた設計、言語の読みやすい句読法的文法を「可読性」として要求することまで、すべて可能である。繰り返し退けられてはいるが、品質の高いソフトウェアをデプロイする方法は公開知識である。
品質の高いソフトウェアについて考えはあるのかもしれないが、このコメントは理解しづらい。
何を見ればよいのか、勧められる本や講義があるのかも知りたい。
「今やらなければ4か月後に開発の労力とコストが15%増える」といった主張を裏づけられるだけの有効な測定値に到達するのは難しい。
スタートアップで、創業者2人が「単体テストを書くな」と言ったことがあった。議論はしなかったし、その言葉の本当の意味が、遅すぎるからできるだけ早く出荷しろということだと理解していた。素早く出荷し、品質も維持し、単体テストも書いた。彼らは知る必要はなく、必要なのは結果だけだった。この議論の隠れた核心は、たいていのソフトウェア組織が速く、しかも品質を保って出荷する方法を知らないということだ。魔法の公式はなく、個人の職人芸が必要であり、同時にチームスポーツでもある。状況は場所ごとに異なるので、軽量なプロセスが一部では機能しても効果は限定的である。結局のところ、経験と正しい価値観、価値提供に集中する知恵を持つ良いチームが必要である。
大学が業界でソフトウェアを作る方法を教えるという前提は、かなり大胆な主張である。
また、この記事はCDやフロッピーディスクでソフトウェアを配布していた90年代の文章のようにも見える。今日では継続的デプロイのパイプラインによって「リリース」という概念が曖昧になることが多く、それが良い慣行と見なされている。この状況で、QA部門がリリースにバグがないと手動で保証するというのは、かなり古臭く見える。
アップグレードが容易でない装置に載せて出荷されるコードを作っている人たちもいる。
誰かの承認が必要なら、その人にそれがなぜ良い考えなのか説明しなければならない。
「より安定する」や「保守しやすくなる」という言葉は、コードベースで直接作業していない人には響かない。開発者はQAをしなかった場合のコスト、つまり金の言葉で語る必要がある。「でもこれが正しいやり方でしょう!」が反論不可能な論拠のように感じられても、承認する人はその正しさに関心がないかもしれない。この原則は、ソフトウェアを正しく直すことだけでなく、職場のほぼあらゆることに当てはまる。
品質がなぜ重要かを説明しなければならないなら、彼らは少なくとも自分と同じくらい、あるいはそれ以上に無知な状態である。そういう組織は自らの運命を受け入れるべきだ。その代わり、成熟した会社ではより早く、より多く報われ、ビジネスがどう回るべきかについての感覚もより早く育てられる。もちろん、注ぐ時間が実際の改善につながるという約束は自分で証明しなければならず、アマチュアのドン・キホーテ的衝動であってはならない。
品質、短い時間、低いコミュニケーションの複雑さ、少ない資金のうち、おおよそ3つしか得られず、ここで時間は従属変数に近い
人々は、チームスポーツであり工学分野でもあるソフトウェアに、工場式のプロセスと構造を適用しようとする。バスケットボールチームを攻撃の段階ごとの手順やチェックボックスに分けて教えたり作ったりしないのと同じように、コミュニケーションを最小限にし、チームが一体となって動けるようにしなければならない。これはプロセスを構築することではなく、チームと個人を作ることだ。計画は立てるべきだが、モルトケの言葉どおり、敵と最初に接触した後も確実に維持される作戦計画はない。ところがビジネス的な考え方では、計画が予想どおりに進まなかったのだから、さらに多くのプロセスを追加すべきだと信じ、次に失敗したとき管理者が個人を責められるようにしてしまう。プロセスには、法的・道徳的な枠組みの中で物事が起こるようにし、テスト中にヘッジファンド資金を誤って全額賭けてしまうような最悪の事態を減らす役割がある。しかし、ほとんどのスタートアップや企業では、チームを中心に置かない形で使われている
伝統的な建築家に、いつ終わるのかと怒鳴ったりはしない。たいていは顧客が満足するか、意思決定を下したときに終わる。多くの開発もこれに似ている
品質という属性をうまく教えている人間活動があるのか疑問だ
経験上、質の高い何かを生み出す能力は、ひたすら練習、練習、練習によってのみ得られる
逆に言えば、このタイトルはプログラミングが産業的実践ではないという意味にすぎない。注意してきた人には自明なはずだが、一部の人は最後まで見ようとしない
文章を書くことだけを見ても、多くの人が品質を高める方法を学ぶ。何を書いてみるべきかを示し、さらに重要なのは、たった今書いた文章の質をどう振り返り、どう改善するかを示すことだ
練習は常に役立つが、品質もまた多くの人が学び身につける
飛行を学ぶときには標準を学ぶが、時間がたつにつれて許容範囲を狭めるように学ぶ。たとえば急旋回で高度基準が±100フィートなら、それは最低ラインであり、50フィート、20フィート、さらには針が動かないレベルを目標にする。目標は「より良く、常により良く、何をもっと良くできるか?」であり、飛行では全体平均ではなく、すべての項目で満たして初めて合格になる。文化的に「満足」は終点ではなく出発点だ
こうした態度は、はるかに協力的なモデルを作ると感じる。飛行では誰もが本気で全員の成功を望み、誰かが失敗すれば自分にもある程度の責任がある。ミスをしたら、将来のミスの可能性を減らす方法を探さなければならないという文化があり、航空会社では飛行運航品質保証(FOQA)も大きな役割を果たす。小規模な僻地運航の組織ではもっと非公式だったが、たいていは「無過失」文化に近く、核心は「どうすればもっと良くできるか?」だった
品質、意思決定、「正しいことをすること」は航空文化の中核だった。評判の良い運航会社なら、天候が悪すぎて安全にできないという判断は、そのまま運航中止につながり、仕事を終わらせようとして無理に出発したりしない。新しく入った技術業界は、その逆のように感じられる。MVPという概念自体が問題を示している。「minimum viable」ではなく、「出発点として受け入れ可能な最低品質の製品」であるべきだ。最低を目標にしてはならず、最低は出発点にすぎない
ゴミを作る練習ばかりしていれば、ゴミをうまく作ることに熟達するだけだ。品質に関心のない人も実際にいるので、そういう場合はあらゆる前提が崩れてしまう