2021 年振り返り

今年も一年の振り返りを簡単にまとめました。

私生活

  • 体調管理
    • 1 日も風邪をひくことなく元気に過ごせました
    • 仮にコロナにかかると、子どもが濃厚接触者になります。その間仕事は休まないといけなくなるので、市中感染が多いときは積極的に在宅するようにしてました。
  • お手伝い
    • 12/31 にコミックマーケット99(通称、冬コミ)の手伝いに行きました。二年ぶりでオペレーションを忘れているかと緊張しながらスペース設営に望みましたが、だんだんと勘を取り戻せて無事一年を締めくくれました。入場者数に制限がかかっていたため、常に怒号が鳴り響くこともなく、また、間違って人流に逆らった瞬間命の危険を感じることもなく、例年に比べると随分と落ち着いたイベントでした。

f:id:yoheimuta:20211231072515j:plain
サークル入場開始直後の東ホール

  • NFTs and a Thousand True Fans[1] で引用されている a Thousand True Fans はすでに自分にとっては身近な世界の話でもあるので、それを加速させる可能性を持つとアンドリーセン・ホロウィッツ(著名VC)が主張する NFT にも興味を持ちはじめました。OpenSea や Rarible、HABET で NFT を出品したり購入すると、通貨としてのイーサリアムだけでなく、ブロックチェーン技術の活用法にも気付かされます。

[1] を意訳する。2008 年に Kevin は 1000 True Fans というエッセーを発表した。この中で、Kevin はインターネットの登場によってクリエイターが成功するには数百万人のファンがいる必要はなくなったと主張した。1000 人の熱狂的なファン、そのクリエイターが作るものは何でも買うという本物のファンが 1000 人いればビジネスが成立するようになると予見した。インターネットはこれを後押しする方向に進化してきたが、中央集権的な巨大プラットフォームがクリエイターとファンをつなぐ主要な手段になってしまった現状は、再びインターネット以前の中間者が活躍する舞台になり始めている。その中にあって、NFT はブロックチェーンを基礎にクリエイターがファンに直接販売できる機会を与える。これは今後も盛り上がりをみせるクリエイターエコノミーの主流になりうる。理由は3つあって(以下、略)

理由の詳細は長いので原文にあたってもらうとして、それでも最初少し捉えどころがない印象を受けると思うので補足しておく。この記事はビットコインイーサリアムという、人類がはじめて獲得した高信頼の分散型プラットフォーム上でスタートアップがビジネスをはじめる経済合理性が生まれ始めているということを3つの角度から論じてる。1つ目はこのプラットフォームは誰でも参加できる分散型という特徴を持っていることから中間者の介入は限定的で、end-to-end での取引にかかるマージンは確実に下がるはずである。したがって、売り手と買い手 {1000 True Fans} が集まりやすい。2つ目はビットコインがすでに証明しつつある、金銭的な価値が担保されるほどに社会から信頼された分散プラットフォームという舞台で、通貨{Fungible}に続いて商品 {Non-Fungible/NFT}が売り買いできるようになったイーサリアムの登場。3つ目はユーザー獲得に多額のコストをかけている中央集権的なプラットフォームと比べたとき、イーサリアムなどの分散型プラットフォームは0コストで Facebook {Meta}に迫る時価総額に短期間で成長。これは中間者マージンがさらに低下する力学の存在を裏付けてくれる上に、多くのエコシステム需要を予想させる。

  • 行った場所
    • 緊急事態宣言も明けてコロナがかなり落ち着いた頃を見計らって、強羅花壇に宿泊しました。はじめて Googleマイマップで作った旅程表を用意しました。Googleマイマップ自体は、アプリによくあるチェックイン機能を Postgis で実装した時に、任意の場所の KML{Keyhole Markup Language} ファイルをエクスポートする用途で使って以来でした。普段電車を使って移動していると地図上の位置関係をあまり意識しません。もう少し続けてみようと思ってます。
  • 会った人
    • Stay home 期間が長かったので、それ以外の期間は人と会って話す機会を作るようにしてました。以前一緒に働いていた同僚と久しぶりにランチをするのは楽しいです。考えていることの壁打ち相手になってもらうこともあり、偏った見方を矯正する良い機会にもなりました。
  • 子育て
    • 今年は、「たくさん笑う」、「たくさん寝る」、「たくさん外で遊ぶ」、「たくさんおしゃべりする」、「たくさん食べる」、を意識してました。やはり偏食は簡単には矯正できない中で、色々な食べ物を与えるようにしているので「たくさん食べる」は少し難しかったです。それ以外はよくできました。特に、お互い気まずい瞬間など目があったときにとにかく笑うようにしていたら、困ったらとりあえず大笑いする癖がついてきました。保育園で先生に怒られたときも、先生が笑い返すまでずっと嫌味な感じではなく笑ってます。
    • ピアノ教室に通い始めました。リトミッククラスです。
    • 子どもの成長はあっという間なので、後から振り返るとあのときもっと一緒に遊んであげればよかったと後悔するという話はよく聞きますね。自分の場合は、一般的な労働者の可処分時間マックスまで一緒に時間を過ごしているのでその心配はありません。いつもと同じ時間、同じ道、同じ公園、同じベローチェ、同じアイスラテ、同じお菓子。連日同じルーティンが続いた 12月30日16時頃、子供と手をつないで歩きながら、同じ日をループしてる感覚を覚えたときにそう思いました。これを限界と呼びます。
    • 英語の時間を週末取るようにしてから、二年が経ちました。最近、横で信号待ちしてるサラリーマンが電話しているのを聞いて、「No Japanese!」 と注意してました。
  • ベスト of 2021
    • ブック(一般)
      • Death's End (The Three-Body Problem Series, 3) -- 邦題は「三体III 死神永生」。話のスケールがでかくて、日常生活の些細なことがちっぽけに感じさせてくれます。壮大なフィクションを読んだ、という読後感です。3 日くらいで効果が切れるので Audible でお気に入りのパートを週明けとか聴いてます。
    • ブック(専門書)
    • ソング
    • ドラマ
      • Maid -- 邦題はメイドの手帖。2歳の娘と家出したシングルマザーがダイソンの掃除機片手にお金持ちの家を回って日銭を稼ぐ話です。終始一人称視点で物語が進行していくので没入感が高いです。話を重ねるごとにじわじわと追い込まれていく若い母親の不安と苦労を追体験できます。行政への問題提起を含む社会派ドラマです。
    • パラレル・オブ・ザ・イヤー
      • パラレルのユーザーとして今年一番良かった更新内容をここに称えます。
      • 通話内チャット -- 非公式な通称、聞き専チャット。グループ通話中に何らかの事情で話せなくなっても、これがあれば会話が続けられます。通話が終了した後に読み返したりできないので、話している感覚で気楽に書けます。

仕事

  • Ruby
    • v2.5.8 を使ったサーバーがリクエスト処理中に突然止まってしまい puma スレッドが完全に枯渇するという現象に遭遇したので upstream にバグ報告[2]をして、その調査過程を Medium に投稿しました[3]。後日 Reddit の ruby 板Ruby Weekly[4] で取り上げられていることを周りから教えてもらい、国外での Ruby の関心の高さを再認識しました。著名な Podcast である Ruby Rogues からゲストのお誘いも当時あったのですが、調整がつかずそのまま流れました。

[2] An exception still breaks monitor state and causes deadlock in 2.6.7: https://bugs.ruby-lang.org/issues/17669

[3] Why puma workers constantly hung, and how we fixed by discovering the bug of Ruby v2.5.8 and v2.6.6: https://itnext.io/why-puma-workers-constantly-hung-and-how-we-fixed-by-discovering-the-bug-of-ruby-v2-5-8-and-v2-6-6-7fa0fd0a1958

[4] Ruby Weekly Issue 549: April 22, 2021: https://rubyweekly.com/issues/549

  • サービス
    • ピークタイムのサーバーダウンは前回の 2020/09/05 21 時から 5 ヶ月後の 2021/02/22 21 時に一度ありました。Preemptive node が複数同時に落ちたのが直接の原因です。その後はありません。この時にまとめた再発防止策 6 つのうち、4 つが完了してます。残り 2 つは進行中です。
    • 5月頃から API の 5xx エラーが一日通して 0 件になる日が現れ始めました。多すぎて見きれなかった時代は過ぎ去りました。続いて 8/21 には終日でスロークエリが 0 件になりました。これも多すぎて見きれなかったところから大きく改善されました。0 件を維持する必要はないですが、多すぎることによって無駄に必要に迫られるモニタリング環境の構築を当面しなくて済むのが良いです。
    • ユーザーの増加に伴って、データ不整合による問い合わせが徐々に増えてきました。このままだといずれ通常業務を圧迫するおそれがあったので、適切な DB 制約をつけながら不整合データを整えていくデータクレンジングプロジェクトがはじまりました。論理削除用の deleted_at に直接ユニーク制約はつけられないので GENERATED カラムを含む複合インデックスを追加していくのがメイン作業です。10 月頃に一通り対応してもらったおかげで、問い合わせは来なくなりました。
    • その他にも色々ありますが、わかりやすいマイルストーンの列挙だけにとどめておきます。Sidekiq の Queue latency もすごい安定するようになりました、とか良くなったことはたくさんあります。機能開発は続けながらも、いつの間にか達成できていることが多いです。バランスを取れている一つの証だと思います。
  • 会社
  • チーム作り
    • 前半は、パラレル内にミニゲーム・ミニアプリを追加していく土台の設計やそのチームの立ち上げをしてました。第一弾は慣れたネイティブでサーバー含めた基盤を作ってから、第二弾で開発速度重視の Unity ゲーム、その後は数を増やしやすい Web ゲームと段階的に手を広げました。リスクとスピードをバランスさせながら経験値をたくさん積めました。おかげで安定した体制が出来上がりました。
    • 後半は、ボイスチャット基盤の安定化を行うチームの立ち上げをしてました。低レイヤーを完全なブラックボックスとして扱う限りにおいては、状態遷移図を書き出すようなデバッグ作業に大半の時間を使ったほうが直接的な効果が期待できます。一方で、基礎知識に欠けるとどこかで進捗が完全にスタックしてしまうリスクが残ります。デバッグ作業自体とても難しいですが任せられる人がいたので、その間自分は優先順位の決定やどこまで深くやるかの判断はしつつも基礎知識の理解に時間を使いました。DSP {Digital Signal Processing/デジタル信号処理, 広告ではないよ}が分野としてはそれに該当するので、教科書[5][6]を読んでました。その過程で、前提知識として求められる、電子工学・三角関数微積分・微分方程式あたりの復習と英単語インプットは本やオンライン動画で補完しました。Dummies シリーズ[7][8][9][10]ありがとう!子どもを寝かしつけしながら読み進めました。このチームの扱うタスクは既存の 2 週間くらいで目に見える進捗を出していく開発リズムには全然合わないことが予想されたので、お互いノイズにならないように隔離して進めました。おかげでシステムへの深い理解が蓄積されてきました。

[5] The Scientist and Engineer's Guide to Digital Signal Processing: http://www.dspguide.com/ch1.htm

[6] Understanding Signal Processing 3rd: https://www.pearson.com/us/higher-education/program/Lyons-Understanding-Digital-Signal-Processing-3rd-Edition/PGM202823.html

[7] Electronics For Dummies 3rd Edition: https://www.amazon.com/Electronics-Dummies-3rd-Computer-Tech-dp-1119675596/dp/1119675596/ref=dp_ob_title_bk

[8] Basic Math & Pre-Algebra For Dummies: https://www.amazon.com/Basic-Math-Pre-Algebra-Dummies-Science/dp/1119293634

[9] Pre-Calculus For Dummies 3rd Edition: https://www.amazon.com/Pre-Calculus-Dummies-Mary-Jane-Sterling-ebook/dp/B07JQDQLLD

[10] Calculus For Dummies: https://www.amazon.com/Calculus-Dummies-Math-Science/dp/1119293499

ソフトウェアエンジニアリング

雑記

  • 会社組織は職種別の縦割り構造からターゲット別のユニット構造に変わりました。入社当時から今までエンジニアが人員の一番大きな割合を占めている中で、PM との間に自分が立って、全エンジニアを一つのカンバンボードと二週間のタイムウィンドウで成果を監督する手法を入社して一ヶ月後に採用しました。その意味で、前者は自分が当初から積極的に推し進めた方針といえます。入社直後まだシステムの全体像を掴めていない中、多様な経験を積んだ唯一の正社員エンジニアとして、毎週ピークにサーバーダウンする状況をいち早く解消しつつ、大量に溜まったバックログを業務委託が大半を占める全 8 人に割り振るのにはこれは有効です。その後想定通り、正社員が増えて、システムも安定化、バックログも枯渇しはじめました。この頃になると、エンジニアの稼働効率・安定よりもプロダクトの創造性をいかに全社で上げていくかに周りの注目が集まるようになりました。最初に相談を受けた時に、組織を全く別方向に変えることによる、エンジニアリング面でのバックログの解消速度低下開発と運用(Devops)をバランスさせる力学の低下は避けがたいが誰も想定していなそうで、だけど実際は誰もそれを望んでない副作用だろうと考えてました。まず、下がった生産性を底上げするためには、各々にシンプルな目標設定と自律性の高さが必要です。複数の Tribe(自己完結した村社会みたいなニュアンス)がそれぞれ直交した目標に向かって 1Q(3ヶ月) 突き進む形はその点から理想的です。また、Server/iOS/Android という重要プラットフォームそれぞれの SLI/SLO 回復に責任を持つ開発 = インフラユニットという存在は必要だと判断しました。その後、全員で細かいところをすり合わせながら、エンジニアリング面での副作用を回避する形でターゲット別のユニット構造に変わることができました。以前のシンプルなマネージメント体制から比べると、この組織は飛躍的にコントロールのレバーが増えます。Q 初めの目標設定も非常に大事になります。適切なメンバーのアサインは以前ほど細かい粒度では行なえません。つまり、ポジティブな変化である一方、調整が常に求められます。

2020 年振り返り

2020 年振り返りを簡単にまとめました。 知人向けの近況報告のつもりです。

OSS 活動とかは、さすがに書き出すと細かい感想がどんどん出てくることに気づいたので 来年以降は別にまとめるとかしてもっとコンパクトな記事にしたいと、書きながら思いました。 特に同業者向けというつもりでもなかったので。

私生活

  • コロナの影響
    • リモートワークが常態化するにつれて、UberEats で朝はスタバ、昼はいきなりステーキの生活に違和感がなくなってきました。
    • 同人イベント(コミケなど)がすべてなくなったので、それらのお手伝い業務も今年はありませんでした。
    • 2, 3, 4 月は NYTimes などの詳細なコロナ関連ニュースを毎日読み漁ってました。その後あまり読まなくなりましたが、また徐々に再開してます。
  • 子供
    • 2020 年は、風邪をひかないこと・絵本をたくさん読むこと・歌を大きな声で歌うこと・ものを動かしたらもとに戻すこと・日光をたくさん浴びることを目標に掲げていました。ちゃんとやれていたと思います。
    • 最近は偏食をはじめイヤイヤ期が進行してきたので、この状況をどう打開するかが目下の課題です。
  • 最近ハマってること
    • Blackpink。NetflixBLACKPINK: Light Up the Sky を見てから。Quora のニュースレターが毎日 Blackpink のネタを送ってきてリンクを押すとさらに集中的にターゲットされるというサイクルに現在嵌ってます。Jennie は怠惰ではないと思いますが、このドキュメンタリーを見た上でもそう思うのか他の人の意見が気になります。

仕事

  • 7 月に転職しました。パラレル というスマホゲーム専用ボイチャアプリを開発してます。
    • 前職のメゾン株式会社は 2017 年 11 月から 2020 年 6 月までの 2 年 8 ヶ月在籍してました。0 -> 1 で自由に作る機会がたくさんあり良い経験になりました。最後は、バックエンドが SpringBoot/RabbitMQ/PostgreSQL/AppEngine で、フロントが TypeScript/Next.js(SSR) でネイティブアプリ用には WebView をラップする SDK(Swift/Kotlin)を実装して、HTTP(OpenAPI)/WebSocket でやり取りするコマースアプリを作ってました。openapi generator を使って通信インターフェースのコードを両端向けに生成するようにしてたのでそれは楽でしたね。
  • 伸び盛りのスタートアップということでリクルーティングとキャッチアップを兼ねて、以前一緒に働いたことがあるソフトウェアエンジニアを中心にランチやディナーなどお話する機会が例年よりも多かったです。
    • おかげさまで、良いチームで働けてます。
  • 今後も外のエンジニアとお話する機会を作っていくと思うので、パラレルのサービス的な成長はこちらを参照いただきつつ、ここでは簡単にパラレルの技術紹介を去年を振り返りつつ書いておきます。パラレルの大まかな技術構成は、バックエンドが Rails/Kubernetes/Sidekiq/Redis/MySQL/Spanner/BigQuery/Stackdriver で、クライアントが iOS アプリ(Swift)と Android アプリ(ReactNative)、通信形式が HTTP と WebSocket、パーティゲームで一部外部ゲームエンジンを利用、最後に音声通話機能で成り立ってます。プロジェクト管理は GitHub Issue/Project です。技術面に関しては当初すべて細かいところまでみてましたが、シニアなクライアントエンジニアがそれぞれ途中から入ってくれたこともあり、障害報を書くごとに徐々に去年はじめから一年通して会社として課題になっていたサーバー側の負荷対策・コスト低減・品質向上をメインでみるようになってました。チームとしての成果を 1 月現在から振り返ると、突発的な負荷増によるサービスダウンは 公式上 9/5 21 時を最後に解消、アクセス増と新機能追加に比例して増え続けていたインフラコストは大きく削減かつ増加ペースも抑制、目立ったアプリケーションエラーは概ね解消してログと監視体制も見通しよく整備、できたと思います。今年はこの分野に関して言うと、自分のサービス・システム理解もようやく揃ってきて、またシステムの可視化も徐々に整ってきたので、より詳細まで妥協なく突き詰めていきたいと思ってます。もう少し具体的な話(例えば これ)は事象発生から解決に至るまでの流れを解説する読み物としては多少面白みがあると思いつつ長くなるので別エントリにまとめる(か興味ある人に口頭で紹介する :) )ことにして、このエントリではこれくらいの抽象的な話でとどめておきます。

OSS 活動

  • 全体的には、以前公開したリポジトリに来る issue や PR に対応することが多かったです。
  • 他には、protolint に関係する PR を他に送る機会も何度かありました。

github.com

f:id:yoheimuta:20210111155131p:plain
スター数の推移グラフ

github.com

github.com

  • このリポジトリは、使い方の質問やバグレポートの issue を受け取ることが未だに多いです。手元で再現しないバグレポートもけっこうあります。なぜかプロダクションで使ってくれているユーザーにロシア系の人が多いみたいで英語での意思疎通が難しいことも一因です。ロシア語っぽい音声を再生するアプリをデバッグさせられたときは何が正解かわからなくてちょっと笑いました。押しが強くて個性なのか英語力不足から来るものか毎回不思議です。
  • 今年対応した中だと再生速度を変更できるようにする改修 が目立った機能追加ですね。

github.com

  • このリポジトリは、intellijプラグインを管理してます。久しぶりに管理画面を覗いてみたところ、累計ダウンロード数が 11,084(ユニークダウンロード数は 8,113)でした。いつの間にか 10000 を超えてました。たまに Twitter で言及されているのを読む以外、特に具体的なフィードバックをもらうわけでもないので忘れがちですが、こういうのを見るとせめて保守はちゃんとしようと思い出させてくれますね。
  • 今年は、依存している protostuff/protobuf-jetbrains-plugin が deprecated になったので別のパッケージに依存するように改修しました。

f:id:yoheimuta:20210103103803p:plain
ダウンロード数の推移グラフ

github.com

リポジトリに送った PR は次の通り。

外部コマンドを実行する JetBrains IDE プラグイン開発の注意点

最近、Protocol Buffer Linter プラグインをリリースした。

0.1.1 まではリント結果の反応が少し不安定で遅かった。 0.1.2(2019.07.06 時点でアップロード後審査待ち)でそこを高速化して安定するように修正できたので、方法などをメモしておく。

まず、外部コマンドを実行するプラグインの場合は、ExternalAnnotator というクラスを利用することが推奨されている。 実装者は ExternalAnnotator 内で外部コマンドを実行して該当する行・列に warning などを表示する。 フックになる ExternalAnnotator の各メソッド自体は IDE のデーモンが編集中のファイルを引数に渡して呼び出してくれる。

0.1.1 では素直にそのファイルパスを外部コマンド(以下リンター)に渡して結果をエディタに反映させていた。 ただ、どうも反応性が不安定でちょっと遅いときがあるなと感じていた。 ドキュメントによると、他のエディタ機能が処理的に優先するため実行には delay があると説明されているので、それかなと思いつつ解決したいのでフォーラムに投稿した。

どうも不安定みたいな挙動は仕様ではなさそうということがわかったので、もう少しちゃんと見直したり他の関連チケットも見てみたところ、エディタ上の編集内容と実際のファイルの同期がとれていない段階で ExternalAnnotator が呼ばれているというのに気づいた。 確かにデバッグするとそうなっていたので、これが原因。

ExternalAnnotator にはファイルと一緒に編集中の内容も引数として渡されるので、ファイルの代わりに編集中の内容を一時ファイルに書き出してそれを使うように修正したところ、リアルタイム性が格段に向上した。

  • github.com
  • ちなみに、Intellij が用意している VirtualFile クラスを経由した書き込みは ExternalAnnotator 内から行おうとするとエラーになるので、java.nio.file.Files を使って直接作成・コピーしている。

呼び出している protolint は標準入力に対応していないので今回はこういう実装にしたが、一時ファイルにいちいち書き出すより標準入力に渡したほうが効率的なので、また修正するかもしれない。

ちなみに、scss-lint-plugin も編集中の内容を一時ファイルに書き出してからリンターに渡している。ただ、こちらは編集ファイルが置いてあるパスに一時ファイルを作っているので、トラブルになっている。 システム標準のテンポラリーディレクトリに作ったほうが無難だと思う。

まとめ

外部コマンドを編集中のファイルに対して作用させたいといったプラグインを開発する場合、編集中の内容と実際のファイルが同期される前にプラグイン処理が開始される可能性がある。 そのため、編集中の内容をコマンドの標準入力とするか、編集中の内容を一時ファイルに書き出してその一時ファイルをコマンドに渡すようにした方がいい。

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

はじめに

例えば、友達 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 はそういうために使うといい。以下のブログにあるほどかっちりとする必要はケースバイケースだが、少人数でも「まあまあ複雑な」プロジェクトなら、ランチとか飲みでも良いので軽いものからやっていったほうがいいと思う。

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

まとめ

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