いきいきと働くためのスクラム+GTDライクなタスク管理とorg-mode (Emacs) による実装


はじめに

大学での研究生活〜企業での研究開発業務を通して自分なりに工夫してきたタスク管理術とその実装をご紹介します。これまで私が置かれた環境は次のような特徴がありました:個人プレーが多く、作業内容や時間管理に裁量があり、ただしそれなりに打ち合わせや依頼などの割り込みが発生する。このような、理系大学の研究室や企業の研究職では比較的一般的と思われる環境にいる方が、本記事の主な対象者です。ある程度プロセス管理が洗練されているような環境にいる、例えばプロジェクト管理システムを利用しているエンジニアの方には不要でしょう。なお、Emacsおよびorg-modeの概要や基礎については先人の素晴らしい記事を参照してください。

基本的な考え方

  • ひとつのことに集中する:マルチタスクはパフォーマンスを容易に低下させます。特に、決断(意思決定)は、些細なことに対するものでも人間の精神を消耗させます。したがって、何をやるか考えながら手を動かす、すなわち計画と実行を同時にやってしまうと大幅にパフォーマンスが落ちてしまうため、これらを分離して行うことが重要です。
  • 予定に追われるのではなく、予定を追う:次々と湧いてくるタスクを前に、何時に帰れるのか分からなくなっていませんか?このような予定に追われている状態は精神衛生上良くありません。時間の見積もりを立てる(そしてその精度を上げる)ことと、クローズドリスト(固定されたタスクリスト)を維持することで、予定を追う感覚で仕事をしましょう。

Emacsの設定例

設定ファイル

use-packageを使用しています(最近使い始めたので、よりエレガントな書き方があるかもしれません)。

(use-package org
  :commands org-agenda
  :mode (("\\.org\\'" . org-mode))
  :init
  (setq org-directory "~/org/")
  (setq org-default-notes-file (concat org-directory "main.org"))
  (setq org-agenda-files (list org-directory))
  (defun my:org-goto-inbox ()
    (interactive)
    (find-file org-default-notes-file))
  :config
  (setq system-time-locale "C")  ;; to avoid Japanese in the time stamp
  (setq org-hide-leading-stars t)
  (setq org-startup-folded nil)
  ;; org-capture and enrty
  (setq org-todo-keywords
        '((sequence "TASK(t)" "WAIT(w)" "|" "DONE(d)" "ABORT(a)" "SOMEDAY(s)")))
  (setq org-tag-alist '(("PROJECT" . ?p) ("MEMO" . ?m) ("PETIT" . ?t)))
  (setq org-capture-templates
        '(("t" "Task" entry (file+headline org-default-notes-file "inbox")
           "** TASK %?\n   CREATED: %U\n")
          ("i" "Idea" entry (file+headline org-default-notes-file "idea")
           "** %?\n   CREATED: %U\n")))
  (setq org-refile-targets '((org-agenda-files :maxlevel . 1)))
  ;; org-clock
  (setq org-log-done 'time)  ;; add a time stamp to the task when done
  (setq org-clock-clocked-in-display 'frame-title)
  :bind
  (("C-c a" . org-agenda)
   ("C-c c" . org-capture)
   ("C-c g" . org-clock-goto)
   ("C-c i" . my:org-goto-inbox)
   :map org-mode-map
   ("C-m" . org-return-indent)
   ("M-n" . org-forward-same-level)
   ("M-p" . org-backward-same-level)
   ("C-c h" . helm-org-in-buffer-headings)))

(use-package org-agenda
  :commands org-agenda
  :config
  (setq org-agenda-custom-commands
        '(("x" "Unscheduled Tasks" tags-todo
           "-SCHEDULED>=\"<today>\"-DEADLINE>=\"<today>\"" nil)
          ("d" "Daily Tasks" agenda ""
           ((org-agenda-span 1)))))
  (setq org-agenda-skip-scheduled-if-done t)
  (setq org-return-follows-link t)  ;; RET to follow link
  (setq org-agenda-columns-add-appointments-to-effort-sum t)
  (setq org-agenda-time-grid
        '((daily today require-timed)
          (0900 1200 1300 1800) "......" "----------------"))
  (setq org-columns-default-format
        "%68ITEM(Task) %6Effort(Effort){:} %6CLOCKSUM(Clock){:}")
  (defadvice org-agenda-switch-to (after org-agenda-close)
    "Close a org-agenda window when RET is hit on the window."
    (progn (delete-other-windows)
           (recenter-top-bottom)))
  (ad-activate 'org-agenda-switch-to)
  :bind
  (:map org-agenda-mode-map
        ("s" . org-agenda-schedule)
        ("S" . org-save-all-org-buffers)))

orgファイル構成例

ホームディレクトリにorgディレクトリを作成し、未計画のタスクやアイデアを集積するmain.orgを用意するほか、プロジェクト(案件)ごとにorgファイルを配置します。ファイルの行数が多いのが好きではないのでこのようにしていますが、単一のファイルにまとめても構いません。

実際のフロー

以下3つから構成されます。

  • 登録:思いついたら随時
  • 計画:週ごと&日ごと
  • 実行:毎日。計画されたタスクリストに従う

タスクの登録

まずは思いつくままにタスクを書き出します。優先順位や作業日時は後ほど決めるので、このタイミングでは考えないようにしましょう。

任意のバッファでC-c cをタイプすると (org-capture)、タスクの内容を記入するためのバッファが表示されます。バッファに内容を書いたあと、C-c C-cをタイプします。メインファイル (main.org) 内の見出し"inbox"の下にエントリが作成されます。または、C-c C-wをタイプすると、どのファイル・どの見出しの下に作成するのかを選択できます。

もしくは、orgファイルに直書きでも構いません。その場合は、M-RET (org-meta-return) でエントリを追加し、C-c C-t (org-todo) でTASKタグ(未完了のタスクを表すタグ)を付けると効率的です。

タスクの情報

タスクに必要な情報は以下のとおりです。

  • 成果物または完了条件
  • 見出し:書き方は自由ですが、私はできる限り「○○を〜する」というフォーマットに統一しています。成果物や完了条件と等価か、または関連する情報を含むと良いでしょう。
  • 締め切りの日時:設定されている場合。C-c C-d (org-deadline) で設定できます。
  • 予定された時間:打ち合わせなど、実行する時間が決まっているタスクの場合に記入します。C-c C-s (org-schedule) で設定できます。
  • 見積もり時間:分解能は30分または1時間くらいでいいでしょう。C-c C-x e (org-set-effort) で設定できます。

よくある誤りは、タスクの成果物や完了条件をはっきりさせないことです。特に、アルゴリズムの検討や資料の作成など、成果物の合格クオリティが明確になりにくい作業は要注意です。このような作業の場合は、作る(成果物:資料やファイルの実体)、レビューする(成果物:修正点のリスト)、修正する(成果物:修正された資料やファイルの実体)というように、作業内容に即して分割しましょう。さらに、可能であれば、過去の実績を参照して、要求されるクオリティを満足するために必要なレビューと修正のサイクル数を把握し、その分だけタスクを複製しておきましょう。

また、見積もり時間が長すぎる場合は、複数のサブタスクに分割しましょう。原則として、タスクは一度開始したら完了するまで中断しません。したがって、集中力の持続の観点から、2〜3時間を越えるタスクは分割すべきです。

計画

ここでは、タスクが実行する日時が未定であることを "スケジュールされていない" と記述します。同様に、タスクを実行する日時を設定することをタスクを "スケジュールする" と記述します。

週ごとの計画 (weekly planning)

金曜日の夕方に行います。目的は、翌週に処理するタスクを決めることです。

  1. スケジュールされていないタスクを列挙します。列挙はC-c a (org-agenda) xでできます。その後、列挙されたタスクそれぞれをsまたは C-c C-s (org-schedule) で翌週の月曜日にスケジュールします。この時点では時間帯を設定しません。
  2. 見積もり時間をもとに、各日にタスクを割り振ります。アジェンダでは"f"や"b"で翌日・前日へ移動できます。翌週の月曜日のアジェンダへ移動し、C-c C-x C-c (org-agenda-columns) でカラムビューに移行し、見積もり時間 (Effort) の合計を確認します。タスクの見積もり時間の合計が所定の労働時間を下回るまで、タスクを翌日にスケジュールします。価値があると思うものをなるべく残すようにしてください。その後、火曜日のアジェンダへ移動し、同様にします。これを、水、木、金と繰り返します。
  3. 余ったタスクについて、本当にする価値があるのか考えます。価値が低いと思ったら、C-c C-t (org-todo) でタスクの状態をABORT(中止)やSOMEDAY(いつかやる)に変更します。価値がありそうなら、翌々週の月曜日にスケジュールします。

日ごとの計画 (daily planning)

毎日の夕方に行います。目的は、翌日のタスクに関して、作業する時間帯を決めることです。

  1. 各タスクを実行する時間帯を決めます。C-c a d (org-agenda) で翌日のアジェンダへ行き、その日にスケジュールされたタスクそれぞれについて、作業する時間帯をsまたはC-c C-s (org-schedule) で設定します。
  2. 所定の労働時間内では実行できないタスクがあれば、そのタスクを翌日にスケジュールします。

前日の時点で、タスクリストをクローズドにする、すなわちこれ以上タスクを増やせないようにしておくことが重要です。

実行

出社してEmacsを起動したら、C-c a (org-agenda) dで当日のタスクリストを確認します。スケジュールした時間に従って、タスクを実行していきましょう。間違ってもタスクリストを変更してはいけません。クローズドリストを維持するのです!

タスクの開始

タスクを開始するときは、C-c C-x C-iをタイプします (org-clock-in)。アジェンダでは単に"I"でも同様です。すると、タスクの見出しと経過時間がウィンドウタイトルに表示されます(なお、設定によって、モードラインに表示することもできます)。

作業ログの記録

タスクのエントリ内には、作業中の思考内容やプログラムの実行結果などをどんどん書き込んでいきましょう。org-modeの記法のほか、設定によってはreStructuredTextやMarkdownの記法が利用できます。ちなみに、orgのエントリはHTMLやMarkdownなどの他フォーマットへ容易に出力できます(例えば、M-x org-html-export-to-html)。任意のファイルや、ファイル内の行に対してリンクを貼ることもできます。また、orgファイルはテキスト形式なので、過去のログやノウハウをgrepやoccurで検索することも容易です。

タスクの中断

休憩や割り込みでタスクを中断するときは、C-c C-x C-oをタイプします (org-clock-out)。再開する場合は、タスクの開始と同様にします。

何かを思い出したり、思いついたりしたら(いつでも)

タスクが発生したり、アイデアを思いついたりしたら、すぐに内容を書き出して、頭の外に追いやってしまいましょう。タスクの発生とは、例えば、おもむろに他の人から頼まれごとをされた、とか、作業しているうちに追加のタスクが明らかになった、などが当てはまります。C-c c (org-capture) で記録用のバッファを開き、内容を書き出します。くれぐれも、いま発生した新たなタスクをいつやるか、なんて考えないでください。 気が済んだらC-c C-cをタイプします。さあ、もとの作業に戻りましょう。

タスクの完了

タスクが完了したら、C-c C-t (org-todo) で状態をDONEに変更します。お疲れさまでした!

その他

  • 計画やメール処理も立派なタスクです。これらの時間も考慮に入れないと、一日の予定が定時をオーバーしてしまいます。ちなみに、私の場合は、週ごとの計画に30分、日ごとの計画に10分、メール処理に1時間の見積もりをしています。
  • メールやメッセージはプル式に処理しましょう。メーラーやコミュニケーションツールは常時立ち上げないようにしましょう。プッシュ式のコミュニケーションはコンテキストスイッチ(頭の切り替え)を増やし、作業効率を低下させます。自分が望んだ時間帯にまとめて処理するのです(「予定を追う」の応用)。
  • 突発的な打ち合わせや依頼などの割り込みが多いなら、日ごとの計画の際にバッファを設けます。例えば、1日8時間の労働時間に対し2時間の空き時間を作る、など。
  • タスクリストでlをタイプすると、Log modeがオンになり、その日の作業記録を見ることができます。また、任意の見出しでC-c C-x C-r (org-clock-report) をタイプすると、作業時間のサマリを表示できます。カラムビューと併せて、定期的に作業見積もりの精度を評価・改善しましょう。

おわりに

タスク管理について少しでも参考になれば幸いです。VSCodeをはじめとするモダンなエディタやIDEの登場により、活躍の機会が少なくなりつつあるEmacsですが、org-modeがある限りは長い付き合いになりそうです。