一度にひとつのことを:マルチタスクに関する誤解との戦い
一般的なソフトウェア開発チームにおいて、多くのことが一度におこなわれていることに気づくでしょう。壁には進行中の作業(WIP)を表すストーリーカードが溢れています。開発者やテスターは、さまざまな会議に奔走するなか、時おり自分のデスクで椅子を回転させて質問したり質問に答えたりしています。プログラマーは無数の機能を実装するために、たくさんのコードを書いています。また、機能動作を検証するために、自動化テストを作成している人々もいます。
忙しくざわざわした雰囲気のせいで、開発チームは物事を成し遂げているように見えます。どうやら私たちはマルチタスクは良いことだと思っているようです。そしてさらに悪いことに、マルチタスクは効果的だと思い込んでいます。
時間管理プログラム “The 90 Day Year” の創始者である Todd Herman は、「人間はマルチタスクするようにできていない」と言います 。彼は、「2 つのタスクを切り替えなければならないときに、時間の 20 パーセントを失う可能性がある」という米国心理学会の主張にも言及しています。
ソフトウェア開発では、タスクが複雑になればなるほど時間を失うことになるので、さらに時間を浪費する危険性があります。Gerald Weinberg の著書 「Quality Software Management: Systems Thinking」の中でよく引用されているグラフによると、5 つのプロジェクト間でタスクを切り替えた場合、実質的に時間の約 25% が浪費されます。
コンテキストの切り替えによって生産性が低下する理由として、Todd Herman はフロー状態 ( “完全に集中した状態” という概念) に関連していると述べています。Todd Herman の試算によると、一度他のことに気を取られてしまうと、フロー状態に戻るのに十数分かかります。したがって、鍵となるのは「一度にひとつのことだけ」に集中することです。失われた生産性を取り戻すために、「一度にひとつのことだけ」を適用できる例をいくつか見てみましょう。
「一度にひとつのことだけ」のテスト
私たちは、同じことをやっていると思っている場合でも、ひとつの概念を他と混同してしまいがちです。たくさんのことを検証しようとする自動テストはよく見かけます。
銀行口座テスト:
A の預金口座を作成する
50ドルをA の口座に入金
Aの残高が50ドルであることを確認する
A から 8ドルの引き落としを要求
Aの残高が42ドルであることを確認
Aから 48ドルの引き落としを要求
システムがエラー メッセージを表示していることを確認
Aの残高が42ドルであることを確認
このようにひとつの長いテストを作成して実行する方が一見簡単に見えます。問題は、ひとつの要素が失敗したときに、後続の検証がなぜ失敗するのかを突き止めるのに時間がかかることです。
長いテストは、多くのことを実証して検証します。テストが長くなればなるほど、その意図は不明瞭になります。このようなテストには、「銀行口座テスト」のような漠然とした名前しかつけられません。
「一度にひとつのことだけ」はテストにも適用されます。ひとつの長いテストを複数のテストに分割し、個々のテストがひとつの有用な動作を検証します。各テストには、検証する内容を簡潔に要約した名前を付けることができます。
- 預金が口座残高を増やす
- 出金で口座残高が減少する
- 残高を超える引き出しはエラーを発生させる
このようにして、より分かりやすいテストを作成します。これらの単発テストで失敗となった場合、多目的テストに比べて少ない労力で問題を発見できます。
「一度にひとつのことだけ」のテスト駆動型開発
テスト駆動型開発の「テスト – コード – リファクタリング」のサイクルは、開発者が一度に短いサイクルのひとつの要素に集中することを奨励します。新しいテストを作成し、失敗するのを確認します。そのテストに成功するコードを作成し、新しいテストと既存のすべてのテストが引き続き成功するようにします。そして、リファクタリングでコードをクリーンアップし、すべてのテストが成功するようにします。
しかし、多くの開発者は、テストを成功させることを優先しようとして、ある種の誘惑にそそのかされます。「このコードは分かりにくいから、少しクリーンアップさせて。」
この作業の後、彼らは苦境に陥ることになります。テストは依然として失敗しているにも関わらず、多くの新しいコードが追加されており、また、変更されたコードを新しいコードから分離することが難しくなっています。彼らは多くの時間を浪費することになります。
泥沼に陥った場合にもっとも良い解決策は、新しいコードとリファクタリングされたコードを破棄して「元の状態」に戻すことです。クリーンな状態から、「最初にリファクタリングを行い、次にコードを書く」、またはその逆をおこなうのが良いやり方です。小さな個別のステップの方が、ほとんどの場合に効果的です。
リファクタリングと新しいコードの追加を同時に行なってはいけません。あくまで「一度にひとつのことを」です !
「一度にひとつのことだけ」の推進
ストーリーカードで一杯の壁は、一度に多くの作業に取り組みすぎたことを意味します。リーン生産方式によって分かったことですが、複数のタスクを処理していると納品までの時間が長くなり、実際にはコストが増加します。大量の WIP (進行中の作業) によって生まれる前述のコンテキスト切り替えのコストに加えて、WIPレベルが高いと、調整がさらに複雑になり、リソースが拘束され、問題が放置される時間が伸びる可能性があります。
おそらく、WIP が多すぎることの最悪な点は、顧客に価値を提供するという主要な目標から私たちを遠ざけてしまうことです。その結果、継続的に顧客に価値を提供するための良い方法を学ぶことができなくなってしまうのです。
私はしばしばペアプログラミング(※1)を奨励してきました。ペアプログラミングは 2 人の開発者が隣同士の席で積極的にソフトウェア製品を作成するコラボレーション モデルです。開発者は積極的にコードをレビューしながら作業を進めるため、結果としてより高品質なソフトウェアを生み出すことができます。
また、ペアプログラミングのパートナーを頻繁に(少なくとも1日に1回)チェンジすることをお勧めします。まだ完了していないタスクに新しいメンバーが加わることで、これまでに作成されたソフトウェアの第三者レビューが可能になります。多くの場合、ペアがタスクを完成させてソース リポジトリに統合する時点では、品質の問題を修正するのには遅すぎます。第三者レビューは不良ソフトウェアの防止に役立ちます。
残念なことに、ペアの切り替えはコンテキストの切り替えを意味し、そのために作業のスピードが若干低下します。私たちは、「コンテキスト切り替えによる減速」のコストが「孤立したペアが作成する低品質のコード」のコストよりも少ないことに賭けるしかありません。
最近、私はペアプログラミングよりもモブプログラミング(※2)を推奨しています。同じ部屋にいる全員が同時に同じものに取り組んでいるので、コンテキストの切り替えに時間を奪われることがありません。そして、念のために言っておきますが、全員が一度にひとつのことに取り組んでいます。モブ プログラミング チームの効果的な WIP は、一般的にひとつの項目です。コンテキスト切り替えによる生産性の低下は経験していません。絶対に「一度にひとつのことを」です!
※1.ペアプログラミング(pair programming)は、2人のエンジニアが1台のマシンを使用して、共同でプログラミングをおこなうソフトウェア開発の手法。
※2.モブプログラミング(mob programming)は、3人以上のエンジニアが1台のマシンを使用して、共同でプログラミングをおこなうソフトウェア開発の手法。ペアプログラミングの発展型。
作者について:
Jeff Langrは、35年のキャリアの半分以上にわたって、アジャイルの手法と手法を用いたソフトウェアの構築と提供に成功しています。また、彼の会社であるLangr Software Solutions Inc.を通じて、数えきれないほどの開発チームを支援してきました。
Pragmatic Bookshelf のテクニカル アドバイザリ ボードにも参加しています。ボブおじさんの本 Clean Code の寄稿者であることに加え、ソフトウェア開発に関する5冊の本(Modern C Programming With Test-Driven Development, Pragmatic Unit Testing, Agile in a Flash (with Tim Ottinger), Agile Java, Essential Java Style)の著者でもあります。
(この記事は、開発元 Ranorex 社 Blog 「One Thing at a Time: Fighting the Fallacy of Multitasking」2019年2月18日の翻訳記事です。)