ストーリー
渡辺マネージャーが表情を曇らせた。
マルチタスクの幻想
人間の脳はシングルスレッド
人間の脳は、本質的に1つのタスクにしか集中できません。「マルチタスク」に見える行動は、実際にはタスク間の高速な切り替え(コンテキストスイッチ)です。
gantt
title 「マルチタスク」の実態
dateFormat X
axisFormat %s
section タスクA
実作業 :a1, 0, 4
実作業 :a2, 12, 16
実作業 :a3, 22, 26
section タスクB
実作業 :b1, 4, 8
実作業 :b2, 16, 20
実作業 :b3, 26, 30
section タスクC
実作業 :c1, 8, 12
実作業 :c2, 30, 34
section ロス
切替ロス :crit, l1, 4, 8
切替ロス :crit, l2, 12, 14
切替ロス :crit, l3, 20, 22
切替ロス :crit, l4, 26, 28
各切り替えで15~30分のロスが発生
コンテキストスイッチのコスト
| 並行タスク数 | 1タスクあたりの実稼働時間 | 切替ロス |
|---|---|---|
| 1つ | 100% | 0% |
| 2つ | 40% | 20% |
| 3つ | 20% | 40% |
| 4つ | 10% | 60% |
| 5つ | 5% | 75% |
2つのタスクを並行するだけで、20%の時間がロスになります。
エンジニアに特に影響が大きい理由
プログラミングの「フロー状態」
プログラミングには深い集中状態(フロー状態)が必要です。フロー状態に入るまでには約15〜30分かかります。
graph LR
A["0分<br/>作業開始"] --> B["15分<br/>集中度上昇"]
B --> C["30分<br/>フロー状態突入"]
C --> D["45分<br/>フロー状態"]
INT["割り込み!"] -.->|"集中リセット"| A
classDef low fill:#f8d7da,stroke:#dc3545,color:#000
classDef mid fill:#fff3cd,stroke:#856404,color:#000
classDef flow fill:#d4edda,stroke:#28a745,color:#000
classDef interrupt fill:#f8d7da,stroke:#dc3545,color:#000
class A low
class B mid
class C,D flow
class INT interrupt
割り込み後: また0分からやり直し。フロー状態に入るまで15~30分かかる。
コンテキストスイッチで失われるもの
| 失われるもの | 具体例 |
|---|---|
| 作業の文脈 | 「どのファイルの何行目を編集中だったか」 |
| 思考の流れ | 「このバグの原因仮説は何だったか」 |
| 短期記憶 | 「変数名、API仕様の細部」 |
| モチベーション | 「いい感じに進んでいたのに」 |
マルチタスクが発生するパターンと対策
パターン1: 割り込み型
状況: コーディング中にSlackで質問が来る
悪い対応:
コーディング → Slack返信 → コーディングに戻る(文脈を失う)
良い対応:
コーディング → 通知を確認(2秒) → 緊急でなければメモだけして後回し
→ ポモドーロ終了後にまとめて返信
対策: 集中時間にはSlack通知をオフにし、バッチ処理で対応
パターン2: 待ち時間型
状況: PRレビュー待ちの間に別のタスクを始める
悪い対応:
タスクA(実装) → PR待ち → タスクB開始 → レビュー指摘 → タスクA修正
→ タスクBの文脈を失う → タスクB再開......(以下繰り返し)
良い対応:
タスクA(実装) → PR待ち → タスクB開始(ただしAの修正に備えて記録を残す)
→ レビュー指摘 → Bのキリの良い所まで進めてからAに切り替え
対策: 切り替え時に「現在の状態メモ」を残す
パターン3: 上司の依頼型
状況: タスクAに取り組んでいる時に「Bもやって」と言われる
悪い対応:
「はい」→ AとBを行き来する → どちらも遅延
良い対応:
「わかりました。今タスクAに取り組んでいて、あと2時間で完了予定です。
Bは午後から着手でよいですか?
もしBの方が優先なら、Aを中断してBから始めますが、
その場合Aは明日の完了になります」
対策: 優先順位をマネージャーと合意する。トレードオフを明示する
WIP(仕掛り作業)制限
カンバン方式では、同時に進行するタスク数(WIP: Work In Progress)に上限を設けます。
WIP制限の効果
gantt
title WIP制限の効果比較
dateFormat X
axisFormat %s日目
section WIP制限なし
タスクA (完了:30日目) :a1, 0, 30
タスクB (完了:30日目) :b1, 0, 30
タスクC (完了:30日目) :c1, 0, 30
section WIP制限=1
タスクA (完了:10日目) :done, a2, 0, 10
タスクB (完了:20日目) :done, b2, 10, 20
タスクC (完了:30日目) :done, c2, 20, 30
WIP制限=1の場合、Aは10日目、Bは20日目に完了。早く価値を届けられる。
個人のWIP制限の目安
| レベル | 推奨WIP | 備考 |
|---|---|---|
| 新人(L1前半) | 1〜2 | 1つのタスクに集中 |
| 中堅(L1後半) | 2〜3 | メインタスク1 + サブタスク1〜2 |
| シニア | 3〜4 | ただし1つに深く集中する時間を確保 |
WIP制限の実践
graph LR
subgraph TODO ["To Do"]
D["タスクD"]
E["タスクE"]
F["タスクF"]
end
subgraph DOING ["Doing (WIP: 2)"]
A["タスクA ★<br/>メイン"]
B["タスクB"]
end
subgraph DONE ["Done"]
X["タスクX"]
Y["タスクY"]
Z["タスクZ"]
end
TODO --> DOING --> DONE
classDef todo fill:#fff3cd,stroke:#856404,color:#000
classDef doing fill:#cce5ff,stroke:#004085,color:#000
classDef done fill:#d4edda,stroke:#28a745,color:#000
class D,E,F todo
class A,B doing
class X,Y,Z done
シングルタスクのテクニック
1. 「今日のメインタスク」を1つ決める
朝に「今日これだけは完了する」というタスクを1つ決めます。
今日のメインタスク: ユーザー認証APIの実装
- 9:15〜12:00: 実装に集中(ポモドーロ4回)
- 13:00〜15:00: テスト作成
- 15:00〜16:00: PR作成・レビュー依頼
サブタスク(空き時間・切り替え時に):
- PRレビュー2件
- Slack返信
2. 「Done」を定義してから始める
タスクの完了条件を明確にしてから着手します。
タスク: 検索機能の実装
Done の定義:
✓ 検索APIが仕様通りに動作する
✓ ユニットテストがパスする
✓ PRが作成されている
← これ以上は次のタスクで
3. 切り替え時の「状態保存」
やむを得ずタスクを切り替える時は、現在の状態を記録します。
## 中断メモ(タスクA: 認証API)
- 現在地: src/auth/handler.ts の validateToken 関数
- 次にやること: JWTの有効期限チェックのテストを書く
- 考えていたこと: リフレッシュトークンのローテーション方式を検討中
- 参考リンク: https://xxx.example.com/jwt-best-practices
まとめ
| ポイント | 内容 |
|---|---|
| マルチタスクの罠 | 切替コストで20〜75%の時間がロスになる |
| フロー状態 | 集中に15〜30分かかるが、割り込みで0に戻る |
| WIP制限 | 同時進行タスクに上限を設ける(新人は1〜2) |
| シングルタスク | メインタスクを1つ決め、集中して完了させる |
| 切り替え時 | 状態保存メモを残して、復帰コストを下げる |
チェックリスト
- マルチタスクがなぜ非効率かを説明できる
- コンテキストスイッチのコストを数値で理解した
- WIP制限の考え方と目安を知っている
- 割り込みへの対処パターンを3つ挙げられる
次のステップへ
次のセクションでは、「委任と依頼の技術」を学びます。自分だけで全てを抱え込まず、適切に人に任せるスキルを身につけましょう。
推定読了時間: 30分