まあまあ複雑なシステムを少人数で開発するときにやったほうがいいと思うこと

はじめに

例えば、友達 2 人でアプリを作るとか、副業やフリーランスに手伝ってもらいつつ社内で数人が集められただけの新規プロジェクトとかを想像してもらいたい。

このアプリやらプロジェクトが、大して複雑でないなら集まった個々人の能力や気合で乗り切れるだろうし、複雑であるとわかっているなら十分な準備と体制で望むだろう。 問題はまあまあ複雑な場合である。本当はまあまあ複雑なのに、業務要件や類似アプリやシステムの不十分な理解のせいで見た目の単純さに引きづられてこのプロジェクトは楽にすぐに終わると錯覚するケースを過去にいくつか、近くからも遠くからも見てきた。 これは ダニング=クルーガー効果 のようなものである。

ダニング=クルーガー効果(ダニング=クルーガーこうか、英: Dunning–Kruger effect)とは、能力の低い人物が自らの容姿や発言・行動などについて、実際よりも高い評価を行ってしまう優越の錯覚(英語版)を生み出す認知バイアス。この現象は、人間が自分自身の不適格性を認識すること(メタ認知)ができないことによって生じる

まあまあ複雑なシステムというのはだいたい次のような特徴を持っていたりする。

  • 1 人では企画も開発も完結しないので複数人で話し合って決めたり協同での作業が必要不可欠
  • 外部のシステムもけっこう使う。例えばクラウドサービスや CI サービスや GitHub, Apple Developer Account などはデプロイ上必須
  • スケジュールは中長期に及ぶ。開発期間もそれなりに長いし、場合によっては運用もすることになる。けっして短期間で終わらない
  • スケジュールの関係もあって当然人の出入りが想定される
  • 予算は潤沢には確保されない
  • とはいえ大規模で複雑ということでもないので、準備やら体制に大仰に取り組みたいとは誰も思ってないし、スピード感は出したい
  • そして少人数だからこそモチベーションは高く保ちたい。平たく言えば、楽しくやりたい

上記のような特徴を持つプロジェクトを、複雑ではないと見間違えると開発効率が悪くなったり最悪頓挫したりする。逆に複雑で大規模だとみなすと開発着手までの時間がかかりすぎる。

ここでは、「まあまあ複雑な」プロジェクトに出会ったときに、自分の経験則をもとに、こうすると穏当でかつ効率も良いのではということを紹介する。

DISCLAIMER

過去・現在を問わず、特定の所属組織を対象とはしていない。どちらかというと、将来自分が新しく何かをはじめるときに参照するためのメモ、または IT 系スタートアップのプラクティスを知りたいという業界外の友人・知人に説明するための資料である。

編集履歴

  • 2018.10.05: 「用語集を作る」を追記

目指すところ

細かいことを列挙していく前に「まあまあ複雑な」プロジェクトで大事だと思うことを考えてみる。

まず、情報格差は作らないようにした方がいい。知りたいときにすぐにアクセスできる状態を作っておけば、協同作業するときにも摩擦が少なく非同期で進められてとても効率が良い。 次に、過去の意思決定や経緯をちゃんと記録して整理したほうがいい。開発期間は短くないし、運用までするとなれば長期になるのだから関わっている当人ですらたいして覚えていない。まして人は出入りするのだから、そういうものは残しておかないといけない。 最後に、進捗感を出していったほうがいい。これくらいの規模感だと、参加者のモチベーションは意外と吹けば消えるようなものだったりするし、関係する決済者の温度感も低かったりする。少人数でまあまあ複雑だと、計画的にやらないと外から見たときに進捗が全く見えないことがある。こういうのは周りのモチベーションも下げて悪循環を招きやすいので避けたいところだろう。

情報については、知っている人に聞けばいいと主張して文書に残さない人がいるのは常に課題になりやすい。開発の効率という面でいうと同期的なやり取りが毎回必要になるのは避けた方がいいだろう。情報のアクセスやコミュニケーションを非同期で可能にするには文章に残さないといけないし、そのためのツールにも配慮しなくてはいけない。このあと紹介するツールなどは非同期で済むようにするということを大事な要件としている。

最終的にはこれらは開発期間の短縮不具合の減少に効果があると思っている。必要な情報を得るのに時間がかかったりそもそも得られないで調べないといけないとなると、時間がかかる。ほかの人の進捗が見えないとそれに依存するタスクにも影響が出て、遠慮し合ったりする結果、交通渋滞のような現象が発生する。一人のブレーキが後続に連鎖的に作用して渋滞を引き起こすようなイメージである。そして、ほかの人の達成内容や過去の意思決定・経緯への不十分な理解は不具合やミス・障害の主要な原因である。これは間接的に開発の遅延につながる。

こうした場所では、先頭のクルマが下り勾配から上り勾配に変化したことで知らず知らずのうちに速度低下してしまいます。その影響で後続のクルマとの車間距離が縮まり、後続のクルマは連鎖的にブレーキを踏んでしまいます。その結果、渋滞が発生してしまうのです。

これらのことは、関わるメンバーに関して性善説に立つことを要求している。性善説に立たないと効率が悪いので、これは前提条件になっている。 性善説を維持できるよう信頼できるメンバー以外を入り口で弾くのは、そういう意味でやったほうがいいことの筆頭である。下記のブログも参考になる。

「本当に働いてる?」と疑っていたり、不安になって細かく管理しようとするとまさに地獄のループに入るような気がします。管理しようとする→現実は管理できない→不安になる→なんとか管理しようとする…。
優秀な人を採用して、あとは信じて任せる。

プロジェクトの地図を作る

プロジェクトの地図とは、プロジェクトに後から入った人でもそれを読めば必要な情報にアクセスできるようにするためのガイドラインのことである。 これがないと、何をするにも人に聞かないといけなくなって効率が悪いし、知っている人と知らない人の間に上下関係を作りやすい。

フォーマットとしては Wiki に書くのが適していて、自分は GitHub Wiki を使っている。GitHub アカウントを関係者全員が持つのはハードルが高いという場合は、後述する Kibela を使うこともある。 例えば以下のような見出しを Wiki のトップページに作る。それぞれの項目はリンクになっていて、リンク先には利用方法やアカウント管理について詳細を書いておく。

f:id:yoheimuta:20180927214038p:plain

自分で作業していても忘れることは多いので新しい人が入ってこないとしてもこういうものは作っておくと自分自身にとっても将来的に役立つはずである。 ある程度の規模の会社になると用意されることが多いが、ここでのポイントは 2 ~ 3 人規模でも用意しておいた方がいいということである。

用語集を作る

用語とは、システムやサービスを構成する大小様々な概念を一意に表す名前のことである。 一意であることを強調するのが普通とは違うところかもしれない。 ここでいう概念のことを慣例的にエンティティと呼んだりする。

ある程度複雑なシステムで用語集がないと、同じエンティティを人によって別の名前で呼んでいたり、別のエンティティを同じ名前で呼ぶということが起きる。 これは全くめずらしいことではなく、用語を統一して中央集権的に管理しようとしなければ、確実に発生することである。

例えば、靴と帽子とバッグを扱うオークションサイト(実際にこういうサイトはある。ex. StockX)を考えてみる。 このサイトでは、ユーザーは NIKEAir Max シリーズの Air Max 1 Parra など靴の出品ページから自分が持っている中古品を出品できる。 この何気ない基本機能をもとに開発が始まると、まず商品という用語が頻発する。この機能を要約すると、「ユーザーは商品の出品ページから自分が持っている商品を出品できる」と呼ぶことになる。 これは商品が多義的に使われている例で、「商業流通している品物」と「個人がこのサイトに出品した品物」が区別できていない。 この場合は例えば前者を製品命名することができる。そうすれば、「ユーザーは製品の出品ページから自分が持っている商品を出品できる」となって正しい。

正式名 英語 NOT 意味 補足
製品 Product 商品 商業流通している品物。商品の名寄せ先。 Air Max1 Parra など
メーカー Maker - 製品を製造している会社名 Nike など
ブランド Brand ライン 製品のシリーズ名 Air Max など。扱っている製品が明らかに靴だけであればラインを使ってもいい
商品 Item 出品物 出品されているもの自体 -

これは些細な問題だろうか。日常生活では全く支障ないことだが、システムの開発とサービスの運用上は大きな問題だと思う。 「商業流通している品物」を商品だと思いこんでいる開発者は本来商品に対して行うべき変更を製品に対して行う可能性は少なくない。一方でプランナーはマーケティングメールでは正しく製品と呼称するかもしれない。だが、デザイナーは製品スペック紹介のページタイトルに「商品のスペック」と命名するかもしれない。そして、カスタマーサポートは製品と商品の乱用の結果、混乱したユーザーからの問い合わせに余分な工数を必要とすることになる。

この用語集は固定的なものではないし一度に全部を作れるものでもないwiki などで管理して常に修正しながら精度を高めていくものである。 この考え方の前提にはチームは開発・運用しながら、よりそのシステムの理解を深めていくものであってそれに合わせて用語も洗練させていくべきという開発上の理論(具体的には DDD)がある。

そういう考えに従うと、製品という呼称は UI 上分かりづらいというフィードバックが別のメンバーから寄せられるかもしれない。 実際、上記で製品としたところをアイテムとか商品と呼ぶほうがしっくり来るという意見には一理ある。 メーカーは、アイテムを製品という意味でカジュアルに使うことがよくあるからだ。 また、このオークションサイトではあえて出品したもの単体をユーザーに明示的に伝える場面は少ないかもしれない。 そうであれば、そもそも区別する必要はこのシステム上ではないということもある。 そこで、このシステムで必要な範囲の解像度で用語を整理し直してみる。

正式名 英語 NOT 意味 補足
商品 Item 製品 商業流通している品物。 Air Max1 Parra など。場面によってアイテムと使い分けていい
出品した商品 Asking - 文字通りの意味。 -
販売した商品 Selling - 文字通りの意味。 -
入札した商品 Bidding - 文字通りの意味。 -
購入した商品 Buyging - 文字通りの意味。 -

ひとつひとつの用語の一意性と境界を意識して整理と統一を行うことで、用語集はメンバー全員のシステム理解を一定水準に引き上げる効果が期待できる。 このことは、開発速度と開発品質の双方に大きく貢献するはずである。

まずは用語集を書くページだけ作っておいて、都度用語の不一致に出会ったら追記していくのが少人数のチームでは現実的である。

ちなみに、用語集に英語を含めているのはプログラミング言語の変数は英単語を使うことが多いので、一緒に統一しておくべきという考えからである。 ここから分かる通り、自分は用語は UI - プログラミング - データスキーマ定義 - 仕様書 - ミーティングすべての領域に渡って完全に一致させるべき(少なくともローンチ時点では)という、人によっては過激と呼ばれる考えを持っている。 これはプロジェクトの過程で用語が変わったらそれに合わせて UI - プログラミング - データスキーマ定義を全部変えないといけないということを意味する。 自分はそれは必要なコストだと思っている。

メールアドレスとカレンダーを確保する

G Suite を契約する。費用は ¥600/月/1ユーザー。Gmail, Googleカレンダーは多くの人が使ったことがあるので導入の手間は少ないだろう。

f:id:yoheimuta:20180928085844p:plain

メールアドレスを各メンバーに発行するのは大事で、この後外部のシステムに登録するときにもこのアドレスを使ってもらうことが可能になる。 ここでプライベートなものを登録されると人の出入りがあったときに大変だし、セキュリティ上よろしくない。 将来的に管理画面などの認証でも会社単位で Google 認証をそのまま使えるのは便利だ。 また、BigQuery など GCP を使う機会は突然降ってきたりするものなので、そのときにもドメイン単位で権限を管理できる。 アカウント単位でメール転送を設定できるので開発用共有メールアドレスや問い合わせ用メールアドレスを作ってグループ単位で運用することも容易だ。

カレンダーも使えると便利だ。「まあまあ複雑なシステム開発」では意外と人と打ち合わせするので、最初から揃えておいたほうが良い。 後述する Slack と連携もできるのでしておくといい。

チャットツールを導入する

Slack を使う。普段の業務連絡はここでやる。ビデオチャットも使える。

ただし、Direct Message と Private Channel は原則禁止。これはけっこう耳にするルールで、情報格差を作るし、全体にとって記録にも整理にもならない。 業務に関係ないことだけにするのがいい。

また、使いすぎには注意で、チャットツールは前述した 同期的なコミュニケーション の典型例であり 記録としての参照性も低い ので、ほかのツールのニッチを埋めるために使うのが良いと思う。

プロジェクト専用のクレジットカードを作成する

  • 外部のシステムもけっこう使う。例えばクラウドサービスや CI サービスや GitHub, Apple Developer Account などはデプロイ上必須

1 枚専用のクレジットカードがあると大変便利。意外と色々なところでクレジットカードを入力しないといけない場面が出てくる。 お金を管理する人がエンジニアなどの実務作業者でない場合は特に効率に寄与する。

バージョン管理システムを使って仕様を書く

GitHub Wikiプログラマーもそうでない人も書けるので自分は使っている。ほかにも Redmine とか色々ツールはある。

大事なことは次の要件を満たすこと。

  • 追記・更新が簡単でサボらない(一番大事)
  • 情報が散らばらない
  • 情報が本の見出しのように整理されている
  • 誰でもすぐにアクセスできる
  • キーワードで検索できる
  • 変更意図やその経緯が記録されて遡れる
  • 一部分を指してリンクできる(つまり特定の部分仕様をURL として共有できる)

議事録を残す

Kibela はおすすめ。5 人以内なら無料で使える。ほかのツールとしては Qiita Team もある。どちらも Slack と連携できるのでしておくといい。

https://cdn.kibe.la/assets/landing/ja/eyecatch-988426655460a5d46754dab1aeba9de897d2e17de66a9859e118ffa643e38fc2.png

議事録は大事で、口頭でやり取りしたことを残すようにしないと、情報共有も経緯の記録も絵に描いた餅になりかねない。 けっこう面倒だし、このプロジェクトを「複雑でない」とみなしているうちはやる気が起きないと思う。でも、「まあまあ複雑」であると思ったなら取った方がいい。

仕様以外のニッチな思考を共有する

ここでも Kibela がおすすめ。

共有しておくと円滑なプロジェクト進行に役立つけれどソースコードでも仕様書でもないというテーマは、プロジェクトをはじめると意外と出てくる。 例えば、仕様に至るまでの考えやタスク管理の方針、またはプロジェクトに対するポエムである。こういうのは仕様やタスクのベースとなるところで、その意思決定や経緯を理解するのにとても役立つ。 メンバー間でそういうベースのところの共有が済んでいると、開発効率も上がるし、理解不足から来るミスも減る。

タスク管理ツールを導入する

Trello などが有名だが GitHub を使っているなら GitHub IssueZenHub を組み合わせるのがおすすめ。どちらも Slack と連携できるのでしておくといい。

https://d2k1ftgv7pobq7.cloudfront.net/meta/p/res/images/fb4de993e22034b76539da073ea8d35c/home-hero.png

https://camo.qiitausercontent.com/2a8b6b03dd42e4297e92ba4fbd9c294969f422cd/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f313231382f32343933322f36666331616535642d653736612d633031642d643737322d3464356331636234376632622e706e67

最後に、進捗感を出していったほうがいい。これくらいの規模感だと意外と吹けば消えるような温度感だったりもする。少人数でまあまあ複雑だと、計画的にやらないと外から見たときに進捗が全く見えないことがある。こういうのは周りのモチベーションも下げるので避けたほうがいい。

タスク管理ツールは進捗感を出すためにとても大切だと思ってる。こういうものがないと、詳しくない他の人から見たときにその人の成果が全く見えないことだってあり得るわけである。 1 つのタスクは最大でも 2 ~ 3 日以内で終わる粒度にしておくといい。2 ~ 3 日ごとに必ず進捗が出るので、プロジェクトのモチベーション的にも良い効果がある。 実際のところ、ここのタスクの粒度が大きすぎるまま進める傾向がある人は成果が出にくい(頓挫したりも含めて)印象を持っている。 ほかの人にも意味があって基本的に絶対に手戻りしない粒度のタスクを、一歩一歩ちょっとずつ前進させる(デプロイする)というのを自然にできるのがタスク管理ツールの良いところだと思う。

  • 余談。「一歩一歩ちょっとずつ前進させる」というのは自分の中では、なぜか家に置いてある(学生時代に買ったのかな)「ビジョナリカンパニー4」の「20マイル行進」をイメージしている。この本の著者であるジム・コリンズは登山家でもあるので登山の例が多くて自分はそこしか読まないのだけど、タスク管理ツールとの関係でいえば、まずゴールに向けたタスクを洗い出しきったら、後はそのタスクを黙々と一定のペースでこなしていけば達成できるという、まあ単純な話が説明されている。大事なのは一定のペースでやっていくということで、その点タスク管理ツールはそういうリズムを作る一助になる。より実利的に考えると、チームのタスク消化スピードの予測もしやすくなるし、他の人もペースを合わせやすいとか全体としても個人としても気分の浮き沈みが少ないというのが挙げられるだろう。
まず、コリンズらは狂信的規律の例として、「二十マイル行進」をあげます。これは、アメリカ大陸の西海岸であるカリフォルニア州サンディエゴから東海岸のメーン州まで、三千マイルに及ぶ徒歩横断を成功させる秘訣です。暑い日も快適な日も雪の日も、きっちり二十マイル歩き、それ以上は歩かない、その「規律」こそが直面する様々な想定外に対応できる力を与えてくれるのです。

快適な日は飛ばし、そうでない時は休むほうがよさそうですが、それは結局環境に翻弄されることにもつながり、自らが自らのペース(あるいは運命)をコントロールしていることにはつながりません。成功しないとは限りませんが、長い道のりで悪天候が続けば焦りも生まれ、いつの間にか無理をし、それが大きなマイナスにつながることもあるでしょう。そして、それと同じことが企業経営にもあてはまるのだと指摘しています。

ちなみに大きすぎて 2 ~ 3 日以内で終わらないタスクがあると主張する声をたまに聞く。そういう場合はそれは親タスクにして、数の子タスクに分解すればいい。 これができないケースは今までに見たことがないので可能だと思う。結局暗黙的にはこれをやっているはずなのだから、面倒臭がらずにやったほうが利益を享受できて良いと思う。

  • 1 人では企画も開発も完結しないので複数人で話し合って決めたり協同での作業が必要不可欠

タスク管理ツールは必然的に Task とか Issue とかチケットと呼ばれるものを作成しなければいけないわけで、これは協同作業でもとても効果を発揮する。 なぜなら、途中から協力を依頼された人はそのチケットを読めば経緯や事情がわかるので、すぐに精度高く関われるからである。これがないと、同期的なコミュニケーションが必要になりやすく開発効率を下げることになる。

次に、過去の意思決定や経緯をちゃんと記録して整理したほうがいい。

ここにも寄与する。タスク単位で意思決定と経緯を記録するのは現実的で検索性が高い。

注意しないといけないのは、これが機能するようにするためにはチケットに正確な情報を常に反映するように努めないと意味がないということである。 何を完了したらクローズできるのかという意味での、タスク内容の記載がまず必要になる。次に、タスクについて途中で変更があればその変更の詳細も追記する。このとき口頭でやり取りしたこともちゃんと追記するのを忘れないようにすること。

f:id:yoheimuta:20180927182400p:plain

タスクを Kanban 方式で管理する

タスク管理ツールを導入すれば、リリースなどのゴールに必要なタスクの洗い出しは終わっているはずである。この段階でタスクの優先度も割り振れているかもしれない。 ただこれだけでは、その時点の静的な状態を可視化しただけで、タスクの優先度・進捗を全体のスケジュールと合わせて運用していくことはできない。

Kanban 方式は手軽でプロジェクトごとにアレンジする余地もあるので導入がしやすい。 簡単にどういうものか説明すると、それぞれのタスクをキューと呼ぶものに詰める。キューは簡単にいえば、これからやるやっているやったみたいなタスクの状態を表す。このキューの間に矢印をつけると、これからやる->やっている->やったというフローができてこのフローがプロジェクトのライフサイクルと一致する。このフローでタスクをこなしていくことを大雑把に Kanban 方式とここでは呼んでいる。

実際にやるときにはもう少し精緻にやったほうが良いと思っていて、例えばキューは以下の画像キャプチャにあるように細分化すると良い。それぞれの用語の意味はリンク先を参照。これは例えば隔週で開催するスプリントプランニングミーティングと組み合わせると効果的で、ミーティング前までに各自がタスクを作って New に入れておく。そして、ミーティングではそのタスクの優先度を話し合って Icebox / Backlog のどちらかに入れる。また、Done に入っているタスクを共有してクローズする。ミーティングが終わったら次のミーティングまでに各自は Backlog にあるタスクを Done に持っていくように作業する。これを繰り返す。

https://camo.qiitausercontent.com/fbd3c4129c866921f5710fc9a8a39ddc2afe53e6/68747470733a2f2f636c6f75642e67697468756275736572636f6e74656e742e636f6d2f6173736574732f313232333236382f373438363334342f64653966626264612d663364652d313165342d393731622d6239636531656234646163352e706e67

このような取り組みをはじめると、タスクの消化にリズムが生まれてくる。そうするとチームにおける開発速度もなんとなく見えてくるので、スケジュールのブレも減ってくることが実感できるのではと思う。 それ以外のメリットとして隔週ベースでこまめにタスクの調整と共有が行われることで、スプリントプランニングミーティング以外での割り込みが減るというのは作業者には良いことだと思う。

Kanban 方式は運用時に特に効果的とされているが、リリース目的でも使える。その場合は上記の Backlog と In Progress の間に SprintN(N は任意の番号)キューを挟んで、リリースまでのスプリント(例えば 2 週間)期間分のタスクをそこに放り込めばいい。

定期的なチームミーティングと 1on1

どちらかだけしかないケースというのはよくあるが、定期的なチームミーティングと 1on1 は両方やるのが効果を最大化すると思う。 チームミーティングしかやらないのは社内の少人数開発ではめずらしくなく、1on1 しかやらないのは副業やフリーランスを中心とする場合にはめずらしくない。

ここまで非同期なやり取りに重きを置いてきたが、そうはいっても口頭で話すのは要件が固まっていなくても、というかむしろそういうときにはなおさら円滑な業務には大事なことで、時間的な制約からそれを全員が一度にできるチームミーティングは必要だ。話す分量が各人である程度同じくらいだと健全で、かなり偏りがあると後述する 1on1 の効果は高いと思う。

一方で 1on1 は決済者やマネージャー(など環境を変える力のある人)とその他メンバーが、チームミーティングで満たされない課題を解決するためにある。ここでは評価とかそういう会社っぽいことはいったん置いておいて、開発的な意味では本音を聞くために必要だと思う。本音は別に愚痴とか辞めたいとかだけではなく、普通に早く言えばいいのにという至極まっとうな正論まで様々である。正論でもチームミーティングで言わない人はけっこう多いと思う。チームミーティングで本音を言う人はめずらしく、プロジェクトよりも人間関係の方が大事である人は少なくないと思う。正直なところ、メンバーは人間関係に傷が入る方がプロジェクトが失敗するよりも嫌だと思っているし、実際人生の損得を考えればそちらの方が正しいこともある。ただ、本音には価値が詰まっていることもあるので 1on1 はそういうために使うといい。以下のブログにあるほどかっちりとする必要はケースバイケースだが、少人数でも「まあまあ複雑な」プロジェクトなら、ランチとか飲みでも良いので軽いものからやっていったほうがいいと思う。

また、マネージャーにとっても自分以外の視点で会社や組織の課題を拾えるきっかけになり、自分自身の成長に繋がるフィードバックを受け取ることができる。

まとめ

まあまあ複雑なシステムには、その複雑さに相当する程度には準備と体制が必要だという話をした。実践例として、自分が経験してきて上手くいった例をいくつか紹介した。 タスク管理周りは体験したことがないとなかなか理解するのが難しいと思ったので、多少くどく厚めに説明することにした。