事業立ち上げ期からグロース期の開発 Tips
事業の立ち上げ期に1人目のエンジニアとして働く機会が何度かありました。
- コンサル会社のソフトウェアサービスにて、新規事業の PdM 兼エンジニア
- メディア・メディア売買会社にて、1人エンジニア
- ヘルスケア会社にて、新規事業のテックリード
その中で、プロダクトオーナーやプロダクトマネージャー(以下それぞれ PO, PdM. 以下 PO とまとめて記載します)と一緒に開発を進めていくにあたり、自分が気をつけていることを Tips としてまとめてみました。
- グロースしても開発のしやすさを失わない
- 新しい要件が来た時に詰まない
といった目的に比重を置いています。
サンプル数が n=1 なので、汎用的なものか・事業の成功に寄与しているのかなんとも言えないです。一つでも参考になれば幸いです。
対象読者・フェーズ
- 中小企業の PO の近くで働くエンジニア。業務範囲としてアーキテクチャの設計・要件定義への介入が求められる方
- 事業として 0→1 の売り上げを立てるフェーズは超えられて、機能拡張・販促などが焦点になっているフェーズ
- 書籍「エンジニアのためのマネジメントキャリアパス」における「テックリード」に興味がある方
書かないこと
- PO, エンジニア間の信頼関係やコミュニケーションの基盤の作り方(そういったものが一定ある状態を前提としています)
- 立ち上げ期のカオスを乗り切る方法(=だいたい気合い)
- 機能そのものの価値を高める取り組み
- 技術自体の方向性や設計の策定
以下本編
要件定義・設計・実装のステップごとに 2,3 個ずつ、合計 8 個 Tips を紹介します。
要件定義
1. PO が相談しやすい雰囲気を作る
狙い
狭い意味での拡張性とは「未来の要件に対して対応できること」だと考えています。そして、未来の要件は PO の頭の中から生まれてきます。ならば、 PO の頭の中にある情報を取れていた方が詰みにくい設計にしておくことができます。
ただし、 PO が接している市場はめまぐるしく変わっていくことが多いです。なので、 PO が考えていることを一度にまとめて取りに行く、というよりは、状況が変わるたびに情報交換ができる方が望ましいです。そのために、彼らが相談しやすい雰囲気を作るようにしています。
できていないと何が困るか
- PO はエンジニアに遠慮したつもりでも、エンジニアから見て的外れな遠慮をした要件を出す
- エンジニアは的外れな方向に拡張性のある設計をしてしまう
どうすればよいか
- 事業部や要件の始まりのタイミングから打ち合わせに参加させてもらう
- PO からの話を邪険に扱わない、頭ごなしに否定しない
- 上記の会話の中で、実現可能性について早期に判断を下さない
雰囲気づくりは人によってスタイルが変わると思うので、自分なりのスタイルを探すといいと思います。
注意点
- プロダクトを考える側・作る側の境界は明確にしないと責任の所在が曖昧になるので、首の突っ込み過ぎに気をつける
2. 要件が論理的に実現可能かを明らかにする
狙い
拡張性・保守性のいずれに対してもフラットな視点を持てるテクニックだと思ってます。
ラフな要件の段階で相談を受けた時、工数などの制約を抜きにして、その要件が論理的に実現できるのかどうかに明らかにしにいきます。基本的に、論理的に矛盾のないロジック・仕組みであれば実装不可能ということはないはずです。
効果としては
- 不確実性の高い要件について「本当に実現できるのか」という不安を抑えられる+要件が詰んでるのか詰んでないのかが分かることで精神的な余裕ができる。この2つによって、 Tips の 1 つ目にある相談しやすい雰囲気につながる
- PO から難しい要求を依頼されたときに、「難しいかも」という曖昧な返答ではなく、「やるとしたらこういう仕組みで、このくらい工数がかかる。複雑な〇〇をやるなら〇〇なリスクもある」と一歩踏み込んだ会話ができる
- 要件が論理的に詰んでいないかを明らかにしようとすると、自然と不確実なポイントを言語化しようとするため、次のアクションが見えやすくなる
- 日々の業務に忙殺されていると視野がどんどん狭まってしまい、何を基準に難しいと言っているのか分からなくなる。ベースを都度「論理的に詰んでいないか」にリセットすることで、冷静に選択肢を吟味できる
できていないと何が困るか
- 要件に対する「簡単」「難しい」の判断に一貫性が失われ、自信を持った回答ができなくなる
- なんでもかんでも「できる!」と言って後で痛い目を見る
どうすればよいか
- 相手が言っていることが分からない場合に聞く
- 理解できた上で、言っていることが相互に矛盾がないかを確認する
注意点
- 使っている語彙が PO とエンジニアの間で違っていると、認識がズレることがある。抽象度の高い話であれば、時間はかかるが図示するなど共通認識を作るための工夫をすること
設計
3. 設計の選択肢を常に複数持つ
できていないと何が困るか
受け取った要件を愚直に設計に起こして実装すると、既存のコードから見て無茶が生じがちです。
これをチーム全員がやると、掛け合わせによってバグが起きる可能性が格段に上がります。
狙い
保守性を高める一番の方法は、「綺麗な設計をすること」ではなく「作らないこと」です。問題が起きたときにそれを何とかするのは作り手である自分なので、未来の自分が苦労しない方法を考えましょう。
また、保守性が高いかどうかを評価するにあたり、
- プログラミング・設計の原則による絶対評価
- 複数の設計の選択肢による相対評価
という 2 つの方法がありますが、前者は抽象度が高く、後者の方が他者と認識を揃えて議論しやすいです。
どうすればよいか
松竹梅で以下のような 3 つの選択肢を考えるようにしています。
- 愚直にやる案
- 開発都合の作りやすさを優先した場合の簡単案
- より汎用性の高い仕組みに改善した場合の案(現在の複雑性をより高度な仕組みでカバーする)
ここまで考えておくと、これらのグラデーションが落とし所になると思います。
汎用性の高い仕組みは、工数バランスが悪いので基本的に採用されないですが、この思考の積み重ねが、技術的負債に取り組む際により高いレベルの機能開発に繋げられると思っています。
4. 開発の都合優先案を提案してみる
行動
3 を考えた上で、簡単案を PO にラフに「こんなんでよくない?」と提案する
狙い
これは 2 つメリットがあります
- 案外それでいいとなることが多い
- そうならなかったとしても、 PO のこだわりポイント=事業成功のポイントやユーザーのペインについての理解が深まる。単純に PO のこだわりってこともあるが、 PO 自体の理解に繋がる(1 への効果)
実装
前提として、スター級のエンジニアの集まりではないチームを想定しています。
売上立ち始めのときはキャッシュに余裕がない、でも人手も足りないから人を雇うみたいなことがよくあります。その際の Tips です。
5. フレームワークのデフォルトの機能を使いこなす
狙い
機能拡張のベースになるのは既存コードになることが多いです。
なので、一箇所トリッキーな実装があると、「すでに本番環境で動いていること」によって安心感が生まれ、新しく機能を作る際に本来転用すべきでないコードがそのまま転用されることがあります。そして、レビュアーも同じく「すでに本番環境で動いていること」による安心感で適切な転用でないことを見落としたりします。
フレームワークのデフォルトであれば変な場所は見つけやすく、保守性が上がると考えています。
できていないと何が困るか
例えば、 SQL のロークエリで実装されている箇所が 1 つあると、それを見てロークエリが増殖します。ロークエリと ActiveRecord の関係考えてなくて N+1 問題が仕込まれる、など。
どうすればよいか
ちょっとデフォルトから外れた書き方をした方が計算量が減る・パフォーマンスが上がるとしても、よほど効果がない限りはデフォルトの書き方を優先する。
注意
- OSS を深く理解しているメンバーが多い場合など、組織のレベル・フェーズによってこの Tips は有効でないことがある
6. ビジネスロジックの分岐を増やさず、許容できる制約に落とし込む
狙い
テストケースは、分岐が 1 つ増えるごと( if 文が増えれば増えるほど)掛け合わせ的に増えていきます。はじめは「このくらいのケース展開なら影響範囲も理解できるだろう」と思っていたとしても、各エンジニアがそれぞれに分岐を追加していくことで、掛け合わせが膨大になることがあります。そうなったときに、何が起きるのかを考えるのは非常に難しいです。
特に、分岐が発生する理由がレアケース対応の場合、上記のようなバグを埋め込むリスクに対して価値を提供できるユーザーの数が少なく、割に合わないことが多いです。ここでも作らず済ませないかを考えましょう。
できていないと何が困るか
思わぬケースの掛け合わせによるエラーが発生する
どうすればよいか
- レアケース対応をどこかで諦める。諦めると言ってもデータは破綻させられないので、
- レアケースが発生する前に、事前にエラーなどを返しユーザーを締め出してしまう
- オペレーションなど人間でカバーする(人間の方がシステムより柔軟)
- 諦める基準は、データの整合性が破綻しないか、その対応によって本来の責務分担が歪まないか、としています
注意
ただし、命やお金が関わっている場合にはどうしても手が抜けない
7. オンボーディングのしやすさを維持するために工数をかける
狙い
立ち上げたばかりのサービスは、思わぬタイミングで急成長することがあります。一気にエンジニア増えた時に、環境の構築に時間がかかったり、暗黙的な手順がたくさんあり、戦力になるまでの時間がかかると、オンボーディングコストがかなりかかることがあります。
ここまで書いてきたことと矛盾しますが、立ち上がりまでのコストがかかりすぎないように、事前に工数をかけておくことをお勧めします。
どうすればよいか
- リポジトリを clone してから開発に入るまでの期間を短くするための投資を怠らない
- そのために、例えば 12 factors などを意識して、外部サービスとの密結合を減らす
- README などの手順を定期的にメンテナンスする
注意
向こう数年の人材状況(例えば、ずっと1人で開発するなど)が確定している場合には、この Tips は有効ではない
番外編
8. うまくいかなかったプロジェクトこそ振り返る
狙い
自分ががむしゃらに働いてどうにかしたような場合、自分は失敗したと思っていても、 PO から見ると「なんかなんとかしてくれた」程度に思われることも多いです。その不満を抱え込まず、明確に「このプロジェクトには今後改善しなければならない課題があった」という共通認識を作り、次に活かしましょう。
できていないと何が困るか
「自分だけ頑張ってる」みたいな認識が積もり、関係性が悪化する
どうすればよいか
- 振り返りという形式で、人ではなく仕組みに対して課題を洗い出し、次に活かす
おわりに
どの程度汎用的な Tips なのか分からないので、使えそうなところを使っていただき、使ってみた感想をフィードバックしてもらえると嬉しいです!
よきエンジニアライフを!
Discussion