Gaudiy Tech Blog

Gaudiyの技術、開発組織、カルチャーについてお伝えするブログです

システムの変動性の特定とアーキテクチャ設計

f:id:hanahanayaman:20220128221846p:plain

こんにちは。エンタメ領域のDXを推進するブロックチェーンスタートアップ、Gaudiyでエンジニアをしている勝又(@winor30)です。

Gaudiyでは、アイドル、ゲーム、マンガなどの様々なIP(知的財産権を有するコンテンツ)をベースにしたファンコミュニティを提供し、そのコミュニティ上で様々なサービスが利用できるような "スーパーアプリ" のようなプロダクトを開発しています。

このような特性のプロダクトづくりにおいて重要なのは、特定のIPコンテンツに特化させずに、どうやってコミュニティ上のサービスをつくっていくのか? という点です。

そこでGaudiyでは、よりスケーラブルでレバレッジの効いた開発をするため、ソフトウェアの原則を重視しながらも、コラボレーションを通じてプロダクトビジョンを捉えることによって、正しい技術的な意思決定をしていこうという考え方があります。

今回は、上述したような意思決定プロセスを、実際に開発した様々なデジタルアイテムの購入システムを例に説明していこうと思います。事業にレバレッジをかけることができるような拡張性のあるソフトウェア開発の参考になれば嬉しいです。

1. レバレッジの効いた開発に必要なことは?

最も大事なことは、プロダクトビジョンを捉え、将来の拡張性を予想することです。

一般的に、将来の拡張性を予想することはYAGNIの精神に反するため、XP的な考え方からするとアンチパターンのように思われます。しかし、投資的な開発を実現できるとのちの追加実装が楽になり、事業進捗を加速させることができます。

そこでGaudiyでは、エンジニアだけでなく、PdM、BizDev、コミュニティマネージャーなど様々なステークホルダーからプロダクトに関するビジョンや将来の方向性を徹底的にヒアリングし、それらを設計に落とすようにしています。

1-1. ヒアリングの方法

ヒアリングの方法は、できるだけコラボワーク(協働できる作業)を取り入れて、ステークホルダーの考え方やメンタルモデルをつくることに注力しています。このコラボワークは、現在だとストーリーマッピングやDDDによるドメインモデルづくりなどがあります。

(GaudiyのDDDの取り組みについてはこちらの記事が詳しいです。)

techblog.gaudiy.com

このときに様々なことをヒアリングするのですが、最も大事だと考えているのは、プロダクトのWHYと将来性をヒアリングしていくことです。この部分は後述する「カプセル化すべきシステムの変動性」に直結していく部分になるので、どういう変化があるのか? というところを様々なステークホルダーにヒアリングすることが重要です。

また、聞き方として気をつけていることとしては、以下の点があります。

  1. ステークホルダーが使った単語・言葉をそのまま使う
  2. 具体例を聞いたあとに抽象的な話を聞く

まず1点目については、ステークホルダーがイメージするモデルを、聞き手のバイアスなしでそのまま引き出すためです。相手が使った単語・言葉を聞き手が言い換えてしまうと少し誘導してしまう形になり、本来のメンタルモデルを汚してしまう恐れがあります。この考え方は「クリーン・ランゲージ」という書籍にある考え方で、どうやって相手のメンタルモデルを100%引き出し、バイアスなしで理解できるか? という方法になります。

この手法はコンサルタントやUXリサーチャーなどがよく使っているのですが、エンジニアのモデリングも本質的には同じだと考えており、相手のモデルを理解し、それをアーキテクトしていくことが良いシステムを作っていく上で大切だと考えています。ただ個人的にはバイアスなしにヒアリングを進めるのはかなり難しく、「こういうシステムになるだろうな…」と予想しながらヒアリングをしてしまうなど、認識の誤差が埋まらないケースなどもありました。

次に、具体例を聞いたあとに抽象的な話を聞くこともメンタルモデルの理解を深めるためのひとつの手段です。最初に同じように認知できやすい実際のケースを聞くことによって、その後の抽象的な概念を具体例と照らし合わせることにより、認識の誤差を減らしていくことができます。

1-2. カプセル化すべきシステムの変動性の導出

また、前述のヒアリングを通して「システムの変動性」を見つけることが、プロダクトにレバレッジを効かせるためには不可欠です。

この変動性とは、Righting SoftwareBuilding Microservices, 2nd Editionなどに書かれている、ビジネスドメインの境界を見つける手法の一つになります。

変動性をソフトウェアに適応するということは、変更される可能性がある領域を明確にし、その部分をサービスやシステムとしてカプセル化することで、その変化が他のシステムに影響を与えないようにすることを指します。

サービスの境界を見つける手法としては、DDDを利用して、Bounded Contextが境界になるやり方も存在するとは思います。ですが、変動性による分解を利用する方が、どういった変動領域から他のシステムを守りたいのか?という視点で境界を定められるので、より柔軟なビジネスドメインの境界を見つけることができる印象をもっています。

また個人的には、SOLIDの単一責任の原則と変動性のモチベーションがかなり近いと考えており、分解の手法としてはかなり有用なものだと考えています。

この変動性領域は「あとから変更できる」という意味合いではなく、「将来的にどういう変化をする可能性が実際にあるのか?」という点が大事です。そのために、PdMやコミュニティマネージャーにプロダクトビジョンをヒアリングしながら、「将来どういうことが行われるのか?」「この機能に対してどんなイメージをもっているのか?」などをエンジニアのバイアスなしにヒアリングしていき、どのような変動性があるのかを見極めていきます。

2. 様々なデジタルアイテムの購入に関する適用例

上記で説明したような変動性の導出を実際の機能開発で行ったので、そのプロセスや実際にやったことを説明します。

2-1. ヒアリングによる変動性の導出と技術的意思決定

f:id:hanahanayaman:20220130145151j:plain
デジタルアイテムの購入イメージ

今回開発した機能としては、様々なデジタルアイテムをクレジットカードで購入できる機能です。

この様々なアイテムとは、具体的に下記3つを購入できるようになっています。

  1. コミュニティ内で閲覧できるライブ配信のデジタルチケット
  2. コミュニティ内でデジタルアイテムがもらえるガチャを引くことができるガチャチケット
  3. コミュニティと連携している(Gaudiyが運営していない)ソシャゲのアイテム

これらのアイテムを、Gaudiyが提供しているコミュニティ内から同じようなフローで購入できるような機能を開発しました。

このプロジェクトで実際にステークホルダーに対するヒアリングを実施した結果、「購入条件の変動性」と「購入商品の変動性」が存在することがわかったため、この部分をカプセル化するようなモデリングの意思決定を行いました。

購入条件の変動性としては、コミュニティで販売するにあたって、コミュニティや外部アプリでの条件(ex. コミュニティレベルや外部アプリのアカウントを持っているか?など)がありました。この条件が増えていくことは、将来的にコミュニティで利用できる新しいエンタメの購買体験を作るというビジョンを持っていたため、必要があると考えました。

また購入アイテムの変動性は、販売するアイテムがコミュニティ内部のアイテムだけでなく、同一IPのソシャゲやECなどコミュニティ外のアイテムを購入できることもビジョンとしてあるため、アイテムが増えるという変動性から他のシステムを守りたいと考え、必要だと考えました。

2-2. Sagaパターン x Orchestrationで結果整合性を担保

f:id:hanahanayaman:20220128153040p:plain
Sagaパターンの正常ケースと異常ケース

変動性を導出した上で、今回は機能の特性上、どうやってアプリケーションとの整合性を担保するかを考慮する必要がありました。

一般的には、可能であれば整合性はDBのトランザクション等を利用してアトミックに行うのがよいとされています。

しかし、アイテムが外部のサービスの商品であったり、そもそも決済代行のAPIが外部のものを利用したりしていたため、今回は結果整合性を担保するような方針でシステムを作っていくことにしました。

そのため、マイクロサービスでの結果整合性を担保させるのに有用なパターンである、Sagaパターンを利用しました。結果整合性を担保したいワークフロー的な処理のどこかで失敗した場合は、全てのデータを元に戻すような補償トランザクションを送ることによって、結果整合性の担保を実現しています。

また、Sagaパターンを利用しつつ、OrchestrationとCoreographyの選択としてはOrchestrationを採用しています。

この意図としては、全体的な購入のワークフローにおいて、失敗したときに、直感的にロールバックを実行しやすく、シンプルな構成になりやすいためです。Coreographyの選択も社内で議論はしたのですが、最終的にピタゴラスイッチ的になり複雑化する懸念があったので、シンプルなアーキテクチャパターンの方を選択しました。

3. 実際の構成

3-1. アーキテクチャ

f:id:tkatsumat:20220131111529p:plain
実際のアーキテクチャ

基本的にupstream serviceとしてPaymentServiceがあり、downstream serviceとしてCheckService、GiftService、決済代行の外部APIが存在するようなアーキテクチャになっています。

ステータスの状態に関しても、どこで失敗したのかに関しては観測可能な状態になっているため、仮に結果整合性が担保できなかった場合でも、どこまでやり直せば良いのかがわかる仕組みになっています。

また、各サービスは購入のメインユースケース以外にも、クレカの登録や商品情報の表示、購入条件の表示などのユースケースに対しても利用されています。

3-2. ストラテジーパターンの利用

購入アイテムや購入条件の変動性によってチェックロジックが走る部分に関しては、ストラテジーパターンを利用し、インターフェースは共通にしながらも内部実装を種類ごとに分けていきました。

 

また、ソフトウェアの構成的にもストラテジーの選択と実行を分けて、より疎結合な設計にしています。

 

ストラテジーパターンを利用した意図としては、購入アイテムや購入条件の変動性をカプセル化したとしても、変動性による影響がソフトウェア内部で発生はするので、その影響を最小限に留めたかったためです。

この設計パターンを利用したおかげで、基本的には新しいものが追加された場合は、その実装クラスを選択するロジックとその実装クラスの内部ロジックを実装するだけでよくなり、より柔軟なソフトウェアアーキテクチャになりました。

4. まとめ

今回は実際にGaudiyで開発したデジタルアイテム購入の機能に関して、どんなところを気をつけながら事業のレバレッジを仕込めるようなものにしていったのかという点に関して説明しました。

事業を推進させるためのエンジニアの役割として、ステークホルダーのメンタルモデルを正しく探り、ソフトウェアの原則を正しく適用することによってレバレッジのあるアーキテクチャを作っていくことが、非常に重要だと個人的には考えています。

ただし、こういった取り組みはまだまだ試行錯誤している部分も正直あるので、こういった不確実な領域でアーキテクトをしていきつつプロダクトに影響を与えたい方がいれば、ぜひ色々議論していき、よりよいプロセスや原則を探っていきたいです!

meety.net

Gaudiyの技術選定とその思想については、以下の記事をご参考ください。

techblog.gaudiy.com

プロダクト主導型の組織をめざして(2022年の抱負)

f:id:hanahanayaman:20220117175240p:plain

こんにちは!エンタメ領域のDXを推進するブロックチェーンスタートアップ、Gaudiy共同創業者の後藤(@PTeamd)です。

Gaudiyは2018年5月に創業し、今年は5期目を迎える年になります。

創業当初からブロックチェーン技術を活用したプロダクト検証を行い、2020年からはSony Music社、集英社、アニプレックス社などの国内大手IPホルダーと協業。エンタメ業界の構造的な課題を解決するプロダクトを通じて、新しいファン体験を提供してきたGaudiyですが、2022年はさらに「PLG(Product-Led Growth)」(※)へと舵取りをしていきます。

今回のブログでは、その背景とGaudiyが今年注力することについてお伝えします!ぜひご一読ください。

※PLG…「プロダクトがプロダクトを売る状態(Product sells itself)」をめざす戦略

1. 創業時からめざすのは「ファン国家」の実現

2018年の創業時より、ファンの応援や創作といった熱量が適正に認められ、ファンに還元されるエコシステム「ファン国家」の実現をめざしてきました。

Gaudiyでは単にブロックチェーン技術をPoCで試すというやり方ではなく、トークンを使ったコミュニティプロダクトをファンに向けて提供することで、New Standardかつベストな体験を社会に普及する取り組みを進めてきました。

創業初期はブロックチェーンの顕在的なニーズが世の中にあまりなく、先行事例も少なかったため、PMFをめざす上で重要だったのは「いかに関係者に価値を理解してもらえるか」でした。

そこでまずは、クライアント企業に深く入り込み、個別の状況に対して理解と共感を深め、エンタメ企業に共通するペインを見つけながら、それを解決するプロダクトをつくる。そのプロセスが必要であり、意図的に「案件ベース」でのプロダクト開発を進めてきました。

具体的には、Sony Music社のデジタル声優アイドルグループ「22/7(ナナブンノニジュウニ)」や、週刊少年ジャンプの人気漫画「約束のネバーランド」など、大手IPホルダー(知的財産コンテンツを有する企業)との協業案件です。

その中で、ファンコミュニティサービスの開発・提供を行いながら、中長期的なファン国家のエコシステム構築をめざして、様々な”仕込み”を行ってきました。

例えば、そのひとつが「分散型ID(DID)」の開発です。ブロックチェーン技術を活用した独自のIDシステムを構築し、実際のコミュニティプロダクトにも組み込んでいます。

note.com

また、Gaudiyの経済設計顧問である慶大・坂井教授や、同じくコミュニティサイエンス顧問である早大・石川教授とともに、トークンエコノミーの経済設計などにも取り組んできました。

このように、エンタメ企業の課題を解決するソリューションをブロックチェーンベースで組みながら、新しい経済圏づくりに必要な研究と実装を行いつつ、SLG(Sales-Led Growth)での着実な成長を遂げてきました。

2. 昨年起きた市場の変化と「PLG」への転換

そして昨年、市場に大きな変化が起きました。

NFTを中心にWeb3.0が大きな注目を集め、世間からの認知度・関心度が一気に高まりました。ありがたいことに、Gaudiyも大手IPホルダーから数多くのお問い合わせをいただいています。

創業時からこのタイミングが来ることを信じ、案件ベースで様々な仕込みを行ってきたGaudiyにとって、2022年は勝負の年。今後大きく飛躍できるかどうかの転換点になります。

そのために注力していきたいのが「PLG(Product-Led Growth)」です。

f:id:hanahanayaman:20220117084942p:plain

SaaSプロダクトでよく聞く言葉ですが、良いプロダクトが次の顧客を呼び込むような、プロダクト主導型の事業成長モデルのことです。(PLGについて詳しく知りたい方はこちらの本がおすすめです。)

2022年は「ファンと共に、時代を進める。」というミッションに向けて、より多くのファンに「Web3.0の体験」を提供し、最高の体験を実現をめざします。

具体的にいうと、Gaudiyでは単にNFTを販売するのではなく、Non-Fungibleな体験を提供していきます。トークンエコノミーで最も重要とされる「コミュニティ」を形成し、そのコミュニティと従来は散らばっていた関連サービスをDIDで統合することで、ファンの活動に対して還元するエコシステムをつくります。

また、エンタメ企業の課題を解決する、IP独自のファンプラットフォーム「Gaudiy Fanlink」というプロダクトに全集中します。国内はもちろん、海内のIPコンテンツとそのファンに対しても最適な体験を一貫して提供することをめざします。

3. これからの「プロダクト主導型組織」について

PLG型で世界中のファン体験を前進させるために、組織全体としても、プロダクトに対してフルベットします。「Product-Led Organization(PLO)」という言葉もありますが、Gaudiyはプロダクト主導型の組織づくりに注力します。

プロダクト主導の成長・組織構築をしていくためには、ソフトウェアの開発だけでなく、ビジネス、コーポレートなどを含むすべての活動を、プロダクトビジョンへのコミットに紐付けて目標設定と戦略実行のできる体制が重要です。

その大方針として、以下3つに取り組んでいきます。

3-1. 全社でプロダクトをつくる

あらゆる活動を上位のプロダクトに紐付けて設計します。エンジニアリング、デザイン、ビジネス、採用、組織開発、広報、バックオフィスなど、あらゆる活動を個別最適化させずにプロダクト中心に組み立てることで、より良いプロダクトづくりをめざします。

例えば、これまでプロジェクトベースで動くことが多かったBizDevの活動も、いかにプロダクトの成功に紐付くアウトプットにつなげられるかを軸に進めていけるようにする。またtoC向けサービスであることから、プロダクトを触ったり、関連したプロモーションを見て興味を持っていただくことも多いため、採用・広報として伝えていきたいストーリーをプロダクト側でも汲み取り反映していく。

さらには、全社的に「プロダクトの成長」を目標にすると同時に、プロダクトサイドでは全ステークホルダーがプロダクトづくりを「自分ごと化」できるように、要望に共感し成果につながるよう支援することで、全員が一丸となってPLGにコミットできる体制をめざします。

3-2. 人間中心設計(HCD)を強化する

人間中心設計(Human Centered Design)とは、簡単に言うと「人のことを理解し、ユーザーにとって使いやすいシステムを設計する」ということです。 案件ごとに、個別のユーザーやクライアントに向けてプロダクトをつくることは、その要望も目標も個別の最適化が追求できたため、ある意味で対象への共感がしやすい側面もありました。

しかしながら、国内外のより多くのコンテンツとファンにプロダクトを提供していくと、汎用性をめざす必要性が出てきますし、関係者と直に接点を持てる度合いも制限されます。それにより、これまでよりも「共感」をベースとしたFandomな体験の実現が難しくなります。

そこで、より体系的な形でファンにとって最高の体験を作るために、共感をベースとしたプロダクト開発手法である人間中心設計を強化していきます。

3-3. プロダクトを作るように組織を作る

上記のようなプロダクト開発手法を、ソフトウェア開発だけでなく、組織も広義の”プロダクト”として、それぞれの手法を一般化して各所に取り入れていきます。

例えばチームトポロジーに代表されるように、カプセル化・抽象化・インターフェースの設計など、エンジニアリングの観点を組織開発にも取り入れて、組織フェーズごとに最適なアーキテクチャーをつくり続けます。

またUXデザインにおける調査・モデリングの手法を、エンジニアリングではDDDなどのバックエンドの設計手法に、採用ではEXの可視化・改善のために利用します。

さらにピープルマネジメントにおいて重要なコーチングの概念は、プロダクトマネジメントや自律分散的な組織マネジメント、カスタマーサポートなどコミュニティの運営にも共通のコミュニケーションスタイルを利用していきます。

4. おわりに

今回のブログでは、2022年の抱負として、PLG型の事業成長と組織づくりの方針をお伝えさせていただきました。

Gaudiyでは、ファンにとっての最高の体験を実現し、時代を進める取り組みをもっと加速させていくため、プロダクト中心組織を一緒に創りあげていきたいと思う方を全方位で募集しています。

職種や職務で分断された形ではなく、ビジネス・テクノロジー・ユーザーの3領域を横断してプロダクトを磨き続けることは、ある意味では個々の専門性に閉じて役割分担をするよりも大きな負担がかかり、難しいことです。

f:id:hanahanayaman:20220116220154p:plain

出典:The Product Management Triangle – Product Logic

ですが、まだ世の中にない世界観である「ファン国家」の実現に向けて、新しい概念や技術を取り込みながらプロダクト開発を進めるGaudiyにとっては、この形が必要不可欠だと考えています。

困難なチャレンジになるとは思いますが、プロダクト中心組織をつくり、2022年もビッグなIPと時代の先端をいく取り組みを進めていきます。

国内はもちろん、言語の壁を超えてグローバルで通用する突き抜けたプロダクトを生み出すことに興味のある方は、ぜひお気軽にご応募ください!ワクワクする未来を、共創していきましょう。

---

最後に宣伝させてください🙏 1月25日(火)19時〜、クラウドサインさんと一緒に「不確実性に向き合うプロダクトマネジメント」をテーマにしたウェビナーを開催します!Gaudiyの開発全般についてお話しするので、PdMの方はもちろん、エンジニアやデザイナーの方々もよければご参加ください。

bengo4.connpass.com

ほぼ全職種オープンしています。お気軽にご応募ください。

www.wantedly.com

いろんな職種のメンバーがMeetyをオープンしてますので、こちらからでも!

meety.net

借りたものはきっちり返す。技術的負債への向き合い方

f:id:hanahanayaman:20211224133024p:plain

はじめまして。エンタメ領域のDXを推進するブロックチェーンスタートアップ、Gaudiyでエンジニアをしている@kaa_a_zuです。

早速ですが、質問です。みなさんは、所属している組織のコードを誇りに思い、この先数十年間に渡って使い続けることができると確信していますか?

私は、この質問をされた場合、顔を背ける自信があります。今回は、私と同じようにこの質問に対して "YES" と答えることが出来なかった人たち、そして 「リファクタリングをしたい」と思っているエンジニアが在籍する組織の偉い人たち に読んでもらいたい内容を書こうと思います。

テーマは、技術的負債の返済方法と技術的負債をためない方法についてです。(かなり長いので、HOWだけ知りたい方は4章から読んでいただけたらと思います。)

1. 一般的な技術的負債とは

「負債」という言葉を、日々の開発ではよく耳にするかと思います。改めて、技術的負債とはなんなのでしょうか。

技術的負債というものは、1992年にWikiの開発者であるウォード・カニンガム氏によって使われた表現です。彼の言葉を引用すると、技術的負債は「借金」と表現できます。それも開発が進めば進むほど、利息が高くなる悪魔のような借金です。

Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite. Objects make the cost of this transaction tolerable. The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, object- oriented or otherwise.

初めてコードを出荷することは、借金をするようなものです。少しの借金は、書き直しですぐに返済される限り、開発を加速させます。オブジェクトは、この取引にかかるコストを許容範囲にしてくれます。危険なのは、借金を返せなくなったときです。正しいとは言えないコードに費やされた時間は、借金の利息としてカウントされる。オブジェクト指向であろうとなかろうと、統合されていない実装の負債によって、技術者組織全体が立ち行かなくなる可能性があるのです。

お金に余裕のない企業が国や金融機関から借金をして事業をするのと同じように、「余裕がない状態で、負債をしてでもサービスをつくり提供する」という意味が込められています。この意味を読み取ると、改めて技術的負債という表現は上手くできていると感じます。

しかし、エンジニアリングにおいて、技術的負債をためようと思ってためているチームは存在しないはずです。ではなぜ技術的負債がたまってしまうのか。技術的負債と借金が大きく異なる点は「借主が借りたことを知らない(気付かない)」ことだと私は思います。

もちろん、納期が近いなかでやっつけの開発をした場合には、負債がたまっていることを自覚しています。しかしながら、みなさんが既に経験をしているように、通常の開発においても技術的負債はたまっています。借りていたことに気がつくのは数日後かもしれないですし、数年後かもしれません。

そして非常に残念なことに、その負債に関連したコードを書けば書くほど利息がついてきます。気がついた時には、利子が複利になっており、返済額もとても大きくなっているかもしれません。取り立てをされることはないですが、寝れない日が続く可能性は高いはずです。

f:id:hanahanayaman:20211224110532p:plain

さまざまな技術的負債が存在しますが、まとめると以下4つに分類することができると思います。

  1. 影響範囲が大きく、目に見えるもの
  2. 影響範囲が小さく、目に見えるもの
  3. 影響範囲が大きく、目に見えないもの
  4. 影響範囲が小さく、目に見えないもの

次の章では、4種類の技術的負債がなぜ発生するのかについて、私の考えを示します。

2. なぜ技術的負債が発生するのか

4種類の技術的負債がたまる代表的な原因をそれぞれ挙げてみます。

※原因の大きさによって、生じる技術的負債の種類が変わることをご了承をいただきたく思います

f:id:hanahanayaman:20211224103307p:plain

1. 影響範囲が大きく、目に見えるもの

  • ビジネスプレッシャー…ビジネス的な観点ですぐにリリースする必要があり、設計やコードにおいて妥協せざるを得なかった。
  • 不十分な先行定義…時間短縮のために、要件がまだ定義されていない状況で開発を開始しなければならなかった。
  • 誤ったテックリード…十分に考えられていない指示が指揮系統のもとに伝わってしまった。

2. 影響範囲が小さく、目に見えるもの

  • 割れ窓理論…DRYでなかったり、直交性がなかったり、変数名が適当なコード、コード規約が守られていないコードが散乱していたため、同様のごみ(ひどいコード)が捨てられ、さらに汚くなってしまった。
  • ビジネス的柔軟性…機能が適切な粒度のモジュールになっていないため、ビジネス要求の変化に柔軟な対応を取れない状態になってしまった。

3. 影響範囲が大きく、目に見えないもの

  • 継続的な開発…プロジェクトの息が長い場合、利用しているコアなライブラリやソリューションが最適ではなくなってしまった。
  • コラボレーション不足…知識や決定事項が組織内で共有されておらず、エンジニアと他の部署での認識のずれが生まれてしまった。
  • 知識の欠如…その時点で在籍している開発者が、問題に対してのベストな解決策や綺麗なコードの書き方を知らなかった。

4. 影響範囲が小さく、目に見えないもの

  • 偶発的プログラミング…コードがたまたま上手く動いているが、なぜ動いているのかを説明することができない。または、データ構造やアルゴリズムについて深く考えることができていなかった。
  • 不十分なテスト…テストスイートがないため、迅速だがリスクの高い暫定的なバグ修正が行われた。
  • 属人化…(小さな組織では特に)知識が属人的になってしまい、負債かどうかの判断もつけにくい状態になってしまった。

これらの原因のうち、心当たりがあるものはありましたか?もしあった場合、それは悪いことではなく改善するチャンスだと私は思います。

3. 技術的負債がもたらす問題点

返済方法について考える前に一度立ち止まって、技術的負債の問題について考えてみます。私は、技術的負債がもたらす問題には、大きく分けて3つあると思っています。

3-1. バグの温床になる

他の部分に影響が出ないと思って書いたコードが、実は様々な部分に影響を及ぼしていた場合にバグが生じます。バグは、サービスのユーザーをイライラさせます。そして悪い評判が立ったり、遅延やセキュリティ問題が発生することは、サービスだけではなく会社に悪影響を及ぼします。

また、CSチームやQAチームのやることも増えるため、社内の環境も悪くなります。当然、エンジニアはそのバグの対処に時間を割かなくてはいけなくなります。該当コードを書いた人はすでに組織を去っているかもしれず、バグの温床になってしまいます。

3-2. 新しい機能をユーザーに届けることが出来ない

よくない設計をしていたが故に、想定していなかった修正をしなくてはいけなくなる恐れがあります。そうなると見積もりで引いていたスケジュールの間にギャップが生まれるため、機能のリリースが遅れます。結果的に機能を渇望しているユーザーの期待を裏切ります。

スケジュールが数日ズレるだけならまだ良いですが、内容によっては「現在の設計だったらこの機能を作ることは難しい」という結論に至る可能性があります。新たな機能が加わらないために飽きがきたユーザーは、そのサービスから離れていってしまいます。

3-3. DXが損なわれる

思いもよらぬ様々なバグを生じさせた過去があったり、ノンリーダブルなコードを見ていると、コードを書く前に勇気をふり絞らないといけなくなります。また、新しいコードを書くために、多くの既存コードを読む必要がでてきます。

最終的に、離職率の上昇やエンジニア採用の成功率低下にもつながる可能性もあります。ひどい作業を好んで取り組みたい、引き継ぎたいと考えるエンジニアはかなり少数なはずです。

…いかがでしょうか?「技術的負債を甘くみていた」と思ってくれた方がいたら嬉しいです。

以上、技術的負債がどういう時に発生して、何が問題であるのかについて説明をしてきました。ここまで読んでくださった方は、おそらく技術的負債を抱えている人だと思います。大変お待たせしました。

次の章では、技術的負債の返済方法について、私の考えを示します。

4. 技術的負債の返済方法

もしも、読んでくださっている方の中に「海老で鯛を釣る」ことが好きな方がいたら、非常に残念なお知らせをしなくてはいけません。

人生と違って、宝くじや玉の輿に乗って大逆転をすることができないのがこの世界です。

また、目に見えない負債を返済することもできません。私たちにできることは、目に見える負債を減らすことと、目に見えない負債を少なくすることの2つだけです。

先ほど「2. なぜ技術的負債が発生するのか」の章で、4種類の技術的負債における代表的な発生原因を挙げました。それぞれの原因を潰すことができれば、返済をする、または返済額を減らすことが可能です。返済が簡単な順で見ていきます。

f:id:hanahanayaman:20211224115129p:plain

4-1. 影響範囲が小さく、目に見えるもの

まず、影響範囲が小さく、目に見えるものが最も簡単です。その発生原因としては「割れ窓理論」と「ビジネス的柔軟性」がありました。 それぞれの返済方法には、以下が挙げられると思います。

<割れ窓理論>

割れ窓理論…DRYでなかったり、直交性がなかったり、変数名が適当なコード、コード規約が守られていないコードが散乱していたため、同様のごみ(ひどいコード)が捨てられ、さらに汚くなってしまった。

  • コード規約ツールの利用
  • フォーマットの自動化
  • コードレビュー
  • CIで規制
  • 割れた窓を見つけた時に直す、もしくはチケットを切る

<ビジネス的柔軟性>

ビジネス的柔軟性…機能が適切な粒度のモジュールになっていないため、ビジネス要求の変化に柔軟な対応を取れない状態になってしまった。

4-2. 影響範囲が小さく、目に見えないもの

次に、影響範囲は小さいけれど、目に見えないものです。その発生原因としては「偶発的プログラミング」「不十分なテスト」「属人化」がありました。それぞれの返済方法には、以下が挙げられると考えます。

<偶発的プログラミング>

偶発的プログラミング…コードがたまたま上手く動いているが、なぜ動いているのかを説明することができない。または、データ構造やアルゴリズムについて深く考えることができていなかった。

  • 利用しているアルゴリズムとオーダー(O)を意識
  • 劣化が起きていないかCIでモニタリングを行う
  • TDD
  • コードレビュー

<不十分なテスト>

不十分なテスト…テストスイートがないため、迅速だがリスクの高い暫定的なバグ修正が行われた。

  • テストを書く
  • テストカバレッジをCIで規制

<属人化>

属人化…(小さな組織では特に)知識が属人的になってしまい、負債かどうかの判断もつけにくい状態になってしまった。

  • 社内勉強会
  • ドキュメント作成の義務化

4-3. 影響範囲が大きく、目に見えるもの

次に、影響範囲は大きいけれど、目に見えるもの。この発生要因としては「ビジネスプレッシャー」や「不十分な先行定義」「誤ったテックリード」がありました。それぞれの返済方法には、以下が挙げられると思います。

<ビジネスプレッシャー>

ビジネスプレッシャー…ビジネス的な観点ですぐにリリースする必要があり、設計やコードにおいて妥協せざるを得なかった。

この原因はエンジニアだけでは絶対に解決できません。ビジネスサイドの技術的難易度や技術的負債への理解と、ビジネスサイドとエンジニアサイドの心理的安全性を高める日々のコミュニケーションが必要です。 その上で、以下の方法があります。

  • ビジネス要件のうち落とせるものがないかを確認
  • 生じた負債はすぐにチケットを切る
  • アジャイル開発をしている場合は次スプリントに負債返済を入れる

<不十分な先行定義>

不十分な先行定義…時間短縮のために、要件がまだ定義されていない状況で開発を開始しなければならなかった。

  • 曳光弾の利用
  • 使い捨て前提のコードを利用するプロトタイプの作成

<誤ったテックリード>

誤ったテックリード…十分に考えられていない指示が指揮系統のもとに伝わってしまった。

  • キックオフミーティングや定期的なミーティングでその指示について議論する
  • (全開発者が意見を言えるように)開発者がただの作業員だと思わないような環境づくりを行う

4-4. 影響範囲が大きく、目に見えないもの

さいごに、影響範囲が大きく、目に見えないという返済が最も難しいもの。この発生原因には「継続的な開発」「コラボレーション不足」「知識の欠如」がありました。それぞれの返済方法としては、以下が挙げられると思います。

<継続的な開発>

継続的な開発…プロジェクトの息が長い場合、利用しているコアなライブラリやソリューションが最適ではなくなってしまった。

  • 定期的にライブラリをアップデートする
  • ライブラリアップデートの自動化
  • 技術アンテナを高く持ち、日頃から新しい技術を試す機会を設ける

<コラボレーション不足>

コラボレーション不足…知識や決定事項が組織内で共有されておらず、エンジニアと他の部署での認識のずれが生まれてしまった。

  • 勉強会を開く
  • デザインコラボレーションの機会を設ける

<知識の欠如>

知識の欠如…その時点で在籍している開発者が、問題に対してのベストな解決策や綺麗なコードの書き方を知らなかった。

  • 既存の類似サービスの真似をする
  • 先に利用する技術についての勉強会を行う
  • 知見を持つ技術顧問を雇う

上記のそれぞれに対する解決方法を用いることで、いくつかの原因を潰すことができると思います。次の章では、これらの解決策をふまえて私たちがどのような取り組みをしているのかについて紹介します。

5. Gaudiyの技術的負債に対する向き合い方

ここからは弊社が技術的負債とどのように向き合っているのかについて、いくつかの事例をご紹介しようと思います。

はじめに、弊社はWebアプリケーションを提供しています。メインのリポジトリは2つで、それぞれがモノレポの形を取っており、フロント, BFF, 複数のバックエンドサービスが管理されています。さらに興味がある方はこちらの記事をご覧ください。

5-1. 技術的負債を解消する取り組み

5-1-1. ソリューションの乗り換え

私たちのアプリケーションには、WindowAとWindowBでリアルタイムなやり取りをしなければならない仕様があります。これを実現するために、当初は window.postMessage() を1年近く利用し、うまく動いていました。ところがある日、それが負債であることに気がつきました。

この負債は、前章までに挙げた「影響範囲が大きく、目に見えない技術的負債」に当たります。感覚としては、ある日郵便受けを見ると、数千万円と書かれた連帯保証請求書が届いている感じです。当然びっくりしますね。

この負債に気がついた時に、問題や影響箇所の詳細について調査し、今乗り換えるべきかどうかをプロダクトオーナーを含めて相談しました。そして返済をするべき負債と決定したものの、どのようすれば返済ができるのかがすぐにはわかりませんでした。

ここで用いた方法が「知識の欠如」で挙げた「既存の類似サービスの真似をする」でした。幸いなことに、私たちが実現をしようとしていたタブ間通信と非常によく似ている挙動をするサービスを見つけることができました。その挙動がどのように実現されているのかをDevToolsのパフォーマンスタブやネットワークタブを用いて徹底的に調べ、解決方法を見つけることができました。

旧アーキテクチャ

f:id:hanahanayaman:20211224115000p:plain
旧アーキテクチャ図

新アーキテクチャ

f:id:hanahanayaman:20211224115020p:plain
新アーキテクチャ図

私たちのサービスは新たなアーキテクチャに乗り換えられ、(今この瞬間は)うまく動いています。

5-1-2. 戦略的に作った負債の回収

私たちのアプリケーションは一言でいうと「エンタメSNS」に当たります。機能として、投稿一覧で画像や動画などのリッチなコンテンツが見れたり、他にも様々なアニメーションや動的なコンテンツを提供しています。ユーザーを飽きさせないために、新しい機能を頻度高く提供をすることも多いです。

また、ブロックチェーンなどの不確実性の高い要素によってスケジュールの見積もりが難しい側面があり、時折、QCDでいうQualityを二の次にしDeliveryを優先した開発をすることもあります。そうして出来上がったコードは、当然ながら質が良いものではありません。

これは、前章までに挙げた「影響範囲が大きく、目に見える技術的負債」に当たります。ユーザーからは見えづらい負債であっても、後々すばやい機能開発やより良い体験の提供がしづらくなってしまうため、すぐに返済計画を立てる必要があります。実際に、弊社ではアジャイル開発をしているので、「次スプリントに負債返済を入れる」ことで解消しています。

また、このうちの一部は「影響範囲が小さく、目に見えない技術的負債」に当たります。その代表例になるのが、パフォーマンス劣化です。時間がない中で書いたコードは、吟味されたものではないため、その塵が積み重なると、いつのまにか目の前には大きな山ができあがっています。

この負債を返済をするためには、パフォーマンスチューニングという地道な作業をする必要があります。Gaudiyでは、この山を作らないようにするために「偶発的プログラミング」で挙げた「利用しているアルゴリズムとオーダー(O)を意識する」や「劣化が起きていないかCIのタイミングでLighthouseAPIを使いモニタリングを行う」を取り入れています。

5-2. 技術的負債を未然に防ぐ取り組み

最後に、そもそも借入をしないために、技術的負債を未然に防ぐ取り組みについてご紹介をします。

5-2-1. DDDの推進

DDDの目的は「影響範囲が小さく、目に見える技術的負債」を防ぐことです。

私たちのアプリケーションには複数のドメインが存在し、バックエンドではマイクロサービスの運用を行っています。ある時、追加開発を行う必要がでた時に、破壊的修正を要してしまうという問題を抱えていました。そこでDDDの導入を行いました。

結果的にドメインエキスパートの考え方やメンタルモデルをシステムに組み込むことができ、これによってレバレッジが効きつつも、柔軟性をもった開発ができるようになりました。これは「ビジネス的柔軟性」が原因で起こる負債を防ぐために機能しています。

5-2-2. ちょいコラ、ちょいデモ、マルチアイ

次に、パターン・ランゲージとして社内で使っている「ちょいコラ」「ちょいデモ」「マルチアイ」の取り組みです。この目的は「影響範囲が大きく、目に見えない技術的負債」を防ぐことにあります。

大前提として、人は誰しもがケアレスミスをしてしまいます。ですがこのミスは、他者とのコラボレーションをすれば防ぐことが可能です。それを日常的に意識するため、利用しているパターン・ランゲージが以下になります。

  • ちょいコラ…デザインとビジネスの観点をエンジニアリングに取り込みたいときに、担当者がその人達に助言をもらいにいく。
  • ちょいデモ…細かいサイクルでデモを実施して、実際に動くものを確認するタイミングを設けることで、ユーザー視点を最初から開発に取り入れる。
  • マルチアイ…偏った視点ではなく、複数の視点を交えて、最適解を導き出す。

これらは「偶発的プログラミング」や「コラボレーション不足」が原因で起こる負債を防ぐために機能しています。

5-2-3. オールオーナー(ALL OWNER)の考え

この行動指針は「影響範囲が大きく、目に見える技術的負債」を防ぐために機能しています。

どれだけ経験を積んできた人でも、勘違いや誤ったリードをしてしまうことがあります。この問題は、言われたことを鵜呑みにしないことで防ぐことが可能です。

Gaudiyには16のクレド(行動指針)がありますが、そのひとつに「オールオーナー(ALL OWNER)」という考えがあります。自律分散的なブロックチェーンの考え方に基づいて運営されている弊組織では「相談した上で、自身で最終決定をする」という考え方が存在します。

この考え方が組織で当たり前となっているため、プロダクトオーナーや、開発経験が長い人、年上の人、その他すべての人の意見を脳死で受け入れることはありません。これは「ビジネスプレッシャー」や「誤ったテックリード」が原因で起こる負債を防ぐことができます。

5-2-4. ドキュメントをすぐに作る文化

最後に、ドキュメント文化は「影響範囲が小さく、目に見えない技術的負債」を防ぐために機能します。

私たちは、様々な技術や言語、プラットフォーム、さらにブロックチェーンという変化の激しい先進技術を利用して開発に取り組んでいます。十数人のエンジニアしかいない組織ですので、いちコンテキストに関わっているエンジニアは、1〜3人程度です。つまり、設計背景や技術知識が簡単に属人化してしまいます。この「属人化」を防ぐために、実施したことや知見をNotionに蓄積しています。これもひとりだと後回しにしがちなので、朝会や夕会のタイミングでドキュメント作成をタスク化しています。

6. まとめ

この記事では、技術的負債をテーマに、発生原因や返済方法などを弊社の具体例を添えて書かせていただきました。

正直、私は恵まれていると思っています。というのも、未熟さが故に発生させてしまった技術的負債を解消する機会を設けてもらえているからです。

よく「コードの改修(=リファクタリング)をしてビジネス的になんの旨味があるの?」と問われたり、「リファクタリングをするならこの機能を作ってほしい」と要求をされる組織があるという話を聞きます。この時に、エンジニアは、WHYをしっかりと答える責任がありますが、(上下関係や心理的安全性の低さが故に)そのWHYを答えることすらできない組織もあると聞きます。

冒頭で質問させていただいた「所属している組織のコードを誇りに思い、この先数十年間に渡って使い続けることができると確信していますか?」という問いに 「YES!」 と答えることが出来ないのは仕方がないことかもしれません。でもこれは、エンジニアだけが悪いという話ではないと思っています。サービスを提供する組織全体として技術的負債を認知し、その返済をサポートする必要があると思っています。

この記事を読んだみなさんが少しでも技術的負債への解像度を高め、上記のような働きかけができるようになれば、書いた甲斐があるなと感じています。

ここまで読んでくださり、ありがとうございました。 書ききれていないこともあるので、よければカジュアルにお話しさせてください。

meety.net

techblog.gaudiy.com

10min勉強会の導入と、運用改善をふり返る。

f:id:gaudiy:20211217112850p:plain

こんにちは。エンタメ領域のDXを推進するブロックチェーンスタートアップ、Gaudiyでフロントエンドエンジニアをしているkodai(@r34b26)です。

色んなアドベントカレンダーをみながら、もう2021年が終わるのか…という実感が湧いてきました。

今回は、約2ヶ月前から開発チームで取り入れた「10min勉強会」について、その運用と改善の道のりを振り返ってみたいと思います。

勉強会がなかなか続かなかったり、チーム間のコラボレーションを促したい方にかなりオススメなので、よければご参考ください!

1. 10min勉強会を導入した背景

元々Gaudiyでは「dev hour」という名の、1時間枠での勉強会を開催していました。

その後、職種横断のコラボレーションをより促進するために、エンジニアに閉じない全社向けの勉強会としてGaudiy Hourが今年の6月から始まり、その運用が継続されている状況でした。(今もGaudiy Hourの運用は続いています。詳しくは、デザイナーのTORAJIROくんが以下noteにまとめてくれてます。)

note.com

このGaudiy Hourは「発表するトピックを投票制で決める」というDAO的な仕組み(民主的なやり方)で、うまく運用を回せていましたが、開発が忙しい時期になるとどうしても「続かない…」という課題が再び発生してきました。

続かない理由はいくつかあるのですが、

  • 開発が忙しすぎて時間が取りづらい
  • 発表準備に時間がかかり、負荷が高い
  • 1時間も話せるようなトピックは枯渇する

みたいなところがありました。

加えて、今年の夏頃からExperience TeamとPlatform Teamの2チーム体制に移行したことから、チーム間でのナレッジ共有がうまくできていなかったり、コミュニケーション頻度が減ってしまったことも新たな課題としてありました。

こうした課題を解決するため、今年の10月から「10min勉強会」の運用を、開発チーム全員を対象に導入してみることにしました。

2. 運用のはじまり

きっかけは、エンジニアのshoさんからの提案でした。

f:id:gaudiy:20211216235842p:plain

Slackを遡ってみたら、10月11日に提案がありました。

この10min勉強会は、ANDPADさんやログラスさんの発信を参考にして導入しました。

tech.andpad.co.jp

Gaudiyにおける目的としては、ナレッジを属人化させず、実際の開発で使えるようなレベルまでチームに浸透すること。10分という短い時間設定にすることで、日々のスコープでの学びや気づきを共有しやすくし、習慣化することを狙いとしています。

初期の運用としては、以下のような形でスタートしました。

  • 開催日:月・水・金の12:00〜(10分間)
  • 対象:開発チームのメンバー全員
  • 内容:Notionにかるくまとめてシェア

GaudiyではSlackのハドルで会話する文化が根づいているので、10min勉強会も、月・水・金の12時に#dev_teamのSlackチャンネルでリマインダーを飛ばし、そこのハドルに全員が集まる形で実施しています。

f:id:gaudiy:20211217000112p:plain

スレッドに共有したいNotionやPRのリンクなどを貼ってます

3. つまずいたポイントと改善プロセス

2ヶ月ほど運用を続けてきた中で、いくつか躓いた点があったので、その改善プロセスについてもご紹介したいと思います。

3-1. 発表用の資料をつくらず、書記を立てる

はじめは発表者がかるくNotionにまとめてから共有するスタイルにしていましたが、人によっては準備に時間がかかることもあったので、発表者ではなく、他の人を書記に立ててドキュメント化するスタイルに変更しました。

これによって負荷が分散され、かつ発表が終わった段階できちんとドキュメント化がなされる状態をつくることができました。

f:id:gaudiy:20211217000254p:plain

実際の提案①

また、開始時刻に間に合わない人がいた時に、以前は集まるまで待っていることがあり、結局10分以上かかっていたことも課題のひとつでした。これに対しても、その場でメモを書き進めることで、途中から入ってきた人もある程度キャッチアップしやすくなりました。

3-2. ネタぎれ防止とkaizenをセットにする

もうひとつは、勉強会テーマの「ネタぎれ」の問題です。週3でやっていると、10分間とはいえ、発表ネタが尽きてくることがありました。

そこで10min勉強会の空いたコマに、Slackに投稿されているチームのkaizenを拾って、共有する時間を取り入れてみることにしました。

日々のSlackで、細かいレビューの観点や、細かいコード上の改善点などが共有されてはいるものの、投稿が流れてしまったりしてチームに十分浸透できていない課題もあったので、10min勉強会でその週のkaizenを拾いながら、軽く議論するみたいな形式も導入しました。

f:id:gaudiy:20211217000457p:plain

実際の提案②

Slackの共有で終わってしまいがちな細かいナレッジの蓄積だったり、習慣を途切らせない工夫として、うまく運用が回っている点かなと思います。

4. 10min勉強会を運用してみての変化

10min勉強会を運用してみて、ナレッジ共有の習慣がついたのと、課題のひとつであったチーム間でのコラボレーションが促進されるようになったなと感じます。

エンジニアメンバー全員が集まる場ができたことで、誰がどこに詳しいのか、何に興味持っているかが以前よりもわかるようになり、「このレビューだったら、この人に聞いてみようかな」という動きが、チームをまたぐ形で生まれてきています。

一方で、kaizenやナレッジの共有はチーム横断でできるようになったものの、それを実践まで落とし込むレベルまではまだ至っていないので、そこは今後の課題かなと思います。また、発表者が同じ人に偏りがちなところもあるので、うまく分散化する仕組みを導入していきたいです。

5. さいごに

今回は、Gaudiyの開発チームで取り組んでいる「10min勉強会」についてご紹介しました。

簡単に始められて、習慣化しやすい取り組みだと思うので、ぜひ試してみてください。

最近は個人としてだけじゃなく、チームとしてつよつよにならないとな、という思いが強いので、チームの改善に興味ある方がいればぜひお話ししてみたいです!

自分のmeety貼っておきます。

meety.net

あとGaudiy Hourは社外の人も参加できますので、よければぜひー

www.notion.so

LaunchDarklyを入れてフィーチャーフラグの運用を改善した話

f:id:gaudiy:20211208171540p:plain

こんにちは!エンタメ領域のDXを進めるブロックチェーンスタートアップ、Gaudiyでエンジニアをしている椿(@mikr29028944)です。

僕が所属しているExperienceチーム(ユーザー体験に関わる開発を担う)では、リリースのサイクルを極力短くして、ユーザーの方になるべく早く価値をお届けできるように「フィーチャーフラグ」を活用しています。

今年の7月頃から導入し、チームで運用を続けてきましたが、その中でいくつかの課題も見えてきました。そこで今回は、実際に直面した課題と、Gaudiyがそれに対してどのようにアプローチし、解決してきたかについて、お伝えできればと思います。

フィーチャーフラグを導入してみたけれど、うまく運用できていないチームや、フィーチャーフラグの導入を検討する上で、どのような課題が起こり得るのか把握したい方などにご参考になると嬉しいです!

1. フィーチャーフラグを運用する中での課題

はじめに、フィーチャーフラグの運用を理解いただく上で、Gaudiyのアーキテクチャ構成について簡単に説明させていただきます。

Gaudiyが提供しているコミュニティアプリのアーキテクチャは、下図のようなマイクロサービスアーキテクチャを採用しています。

f:id:gaudiy:20211208010634p:plain
全体のアーキテクチャ構成

ここでは詳細な説明は省きますが、この構成のもとで、新規フラグの追加フローとしては、以下のような形で運用していました。

  1. データベースにフィーチャーフラグを追加
  2. GraphQLのスキーマを修正
  3. フロント側も同様にスキーマを修正
  4. Notionなどのドキュメントにフィーチャーフラグの詳細を記入

ただ、このフローで生じてきた問題は、フィーチャーフラグの実装コストがめちゃくちゃかかる…ということです。特に感じた課題としては、2点ありました。

1-1. 全環境におけるフラグの状態把握がしづらい

データベース上でフラグを管理していたため、全環境×テナントごとに用意されているフラグを、一覧で確認することが不可能でした。

また、いつ、誰によって状態の変更がなされたかの把握が難しく、なにかあった際に誰に聞けばいいのかわからない状態でした。加えて、フラグを追加した人がNotionにその詳細を書くという運用をしていましたが、段々とメンテされなくなり、古いドキュメントのまま残り続けてしまう、といった問題もありました。

1-2. フラグの実装上のルールが統一されてない

さらに、使われなくなったフラグが削除されずに残り続けることで、コードベースを複雑化させてしまっていました。

たとえば、トップのコンポーネントですでに制御されているにもかかわらず、フラグを挿入してしまうなどの無駄が生じる問題や、フラグを挿入する際にリファクタリングで関数を分けるのではなく、そのコード上に上書きしてしまって一つの関数が肥大化していく、みたいな問題が起きていました。

これらに加え、他にも課題がたくさん……

カテゴリ 課題
管理 環境ごとのDBにフラグを用意するコストと運用ミスの発生
管理 Bizサイドなどの開発者以外の人がフラグを変更しにくい
UX 単一ごとのフラグ取得のローディング状態を考える工数がかかり、UXも悪化
設計・開発 実装コストが高く、メンテナンスが大変(※)
設計・開発 フラグを使う方法・宣言がバラバラ
設計・開発 もともとフラグを置く想定をせずにコンポーネント設計をしていたため、
既存のコードに置く際に散在してしまうことがある

※補足すると、BFFにフラグのコードを書いていましたが、フロントからの呼び出しも含めてフィーチャーフラグの実装コストがかかるのと、BFFのないサービス環境もあるため、その場合は実装の差異が生まれてしまってメンテナンスが大変という課題がありました。

2. フィーチャーフラグのツールを調査

これらの課題を解決するため、フィーチャーフラグのよりよい活用の仕方を検討している中で、フィーチャフラグ管理ツールの利用を検討することにしました。

いくつかのツールを調査した結果、Gaudiyでは「LaunchDarkly」というツールがよさそうだ、という結論になりました。

launchdarkly.com

各ツールの比較は、下図のCodeZineさんの記事がわかりやすかったです。

f:id:gaudiy:20211208011431p:plain
参照:https://codezine.jp/article/detail/14662

特にGaudiyの場合は、サービスの品質維持の観点から、リアルタイムでフラグの状態を切り替えられるという点が大きなメリットとしてありました。実際、瞬時にON/OFFが反映できるので、非常に運用しやすいです。

他にも、「ミニマムの場合はコストが抑えられる」「障害が起きてもフラグの状態が保存されるため、サービスの継続性が高い」「公式ドキュメントが充実している」などのメリットがあることから、LaunchDarklyを利用してフラグを実装し、リファクタリングを併せて行う運用に変更しました。

docs.launchdarkly.com

また、LaunchDarklyは、開発する上でのUXが良いのも特徴です。

たとえば、Gaudiyのエンジニアの多くが使用しているエディター、VS Codeのプラグインも備わっています。

このプラグインの特徴としては、以下の3点があります。

  1. ソースコード上で各フィーチャーフラグの現在の値を確認できるため、そのためだけに管理画面に入ったり、どのような値が入るかをデバッグしたりする必要がない。
  2. ソースコード上でフィーチャーフラグのkey入力を自動補完してくれるため、keyのタイポによる意図しないバグが生まれにくい。
  3. VS Code上でフィーチャーフラグの値を変更できるため、変更のために管理画面にいく必要がない。

f:id:gaudiy:20211208011828p:plain
👆key部分をホバーすると、現在のフラグの値が確認できる

f:id:gaudiy:20211208011913p:plain
👆各フィーチャーフラグの値を変更できる

上記のような感じで、エディターのみでフィーチャーフラグの操作を完結でき、ストレスのないフラグ管理を可能にするのが、開発者目線での魅力かなと思います。

3. LaunchDarklyを導入して何が変わったのか

LaunchDarklyの導入と、コードのリファクタリングを実施した結果、以下のように前述した課題を解決することができました。

カテゴリ 課題 結果 詳細
管理 環境ごとのDBにフラグを用意するコストと運用ミスの発生 各環境に自動的にフラグが生成されるようになった
管理 Bizサイドなどの開発者以外の人がフラグを変更しにくい GUIツールで誰でも更新がしやすい
UX 単一ごとのフラグ取得のローディング状態を考える工数がかかり、UXも悪化 フラグを一括で取得することができるようになった
設計・開発 実装コストが高く、メンテナンスが大変 フロントからLaunchDarklyのフラグを参照する形で実装コスト減
設計・開発 フラグを使う方法・宣言がバラバラ フラグの使う方法・宣言をLaunchDarklyのuseFlagsに統一した
設計・開発 もともとフラグを置く想定をせずにコンポーネント設計をしていたため、既存のコードに置く際に散在してしまうことがある リファクタリングを実施して解消した(※後述)

たとえば、フィーチャーフラグの設定一覧はこんな感じです。

f:id:gaudiy:20211208012257p:plain
👆右のトグルボタンのON/OFFでフラグを切り替えられる

また、サービス環境も一覧できます。

f:id:gaudiy:20211208115233p:plain
👆フラグ追加時に右の全環境にフラグが追加される

Gaudiyでは1つのソースで複数のサービス(コミュニティ)を管理しているため、フィーチャーフラグを追加した時に、全サービスに一律でフラグが追加されるのはとても便利です。

また、フィーチャーフラグまわりの課題解決だけでなく、特定のユーザー限定でフラグを有効にできる機能を利用することで、管理者ユーザーのみフラグをONにして、本番環境での動作確認をすることが可能になりました。これによって、テスト環境でのテストから、本番環境へのデータ移行をするコストが大幅に削減できました。

※付け加えると、一部のユーザーにこの機能を適用することで、クローズドβ公開のような限定公開も簡単に実現することができます。

4. 実装の際に注意していること

ツールを導入したことでかなり運用しやすくなりましたが、実装の際に注意している点がいくつかあるので、それについてもご紹介します。

4-1. 親コンポーネントでの制御を意識する

特にフロントエンドでは、バックエンドと比べてフラグが多くなる傾向にあります。そこで、できるだけ親コンポーネント側で制御することを優先しています。

こうすることで、フィーチャーフラグを使っていることを明示できますし、検証が終わったときには削除しやすくなります。

社内での工夫としては、フィーチャーフラグライブラリにあるLaunchDarklyのHooksを、Contextを使ったコンポーネントとして、複合コンポーネントを作って利用しやすくしています。

kentcdodds.com

...

// FeatureFlagを適用するためのコンポーネントを作成
export const FeatureToggle = ({ featureFlagName, children }: Props) => {
  ...
  return <FeatureToggleContext.Provider value={value}>{children}</FeatureToggleContext.Provider>;
};

const On = ({ children }: ChildProps) => {
  const { featureFlagEnabled } = useFeatureToggleContext();
  return <>{featureFlagEnabled && children}</>;
};

const Off = ({ children }: ChildProps) => {
  const { featureFlagEnabled } = useFeatureToggleContext();
  return <>{!featureFlagEnabled && children}</>;
};

FeatureToggle.On = On;
FeatureToggle.Off = Off;

フィーチャーフラグコンポーネントの活用例:

const Group = () => {
  ...
  return (
      <CommunityHome>
         // フィーチャーフラグを活用している箇所が深掘りをしなくてもわかる
        <FeatureToggle featureFlagName="groupTimelineReleaseFlag">
          <FeatureToggle.On>
              <TimelineGroupPage />
          </FeatureToggle.On>
          <FeatureToggle.Off>
              <GroupPage />
          </FeatureToggle.Off>
        </FeatureToggle>
      </CommunityHome>
  );
};

4-2. フィーチャーフラグの種類によって実装方針を定義する

また、フィーチャーフラグの利用法によっても実装の仕方は変わってきます。

Gaudiyでは、主にリリースフラグとアクティベーションフラグとして利用することが多いですが、できるだけコード上に存在しないほうが将来的な負債にならないと考えているため、リリースフラグとして早期に消すことを前提とした使い方が多いです。また、アクティベーションフラグに関しては、利用ケースとしても少し長期でみて、動作を変更したい時に利用しています。

リリースフラグを実装する場合は、例えばhooksの関数を制御したい場合は、同じ処理が重複することがあったとしても関数を2つ設ける方針にしています。これは消しやすさを優先した実装です。

そのため、スコープとしても、リリースフラグを消すところまで開発チームのコンテキストとして抱えるようにしています。

2つの関数に分けてフラグで制御するパターン:

const { singleGroupReleaseFlag } = useFlags();

const handleSubmitV2 = useCallback(
    async (value: TopicCreateValue) => {
        await createOrUpdateTopic(value);
    },
    [createOrUpdateTopic]
  );

const handleSubmit = useCallback(
    async (value: TopicCreateValue) => {
        ... // 他の処理
        await createOrUpdateGroupTopic(value)
    },
    [...]
  );

逆にアクティベーションフラグの場合は、すぐに削除できないものに利用されるため、2つの関数に分けて運用するのではなく、同じ関数内にフラグ制御を設けて使う場合が多いです。

これは長期に滞在することになるため、関連する箇所で不具合が発生した場合に、複数箇所を修正する必要が出てしまうことを避けるための運用です。デメリットとしては、より複雑になってしまうことがありますが、たとえば不具合発生時に、片方しか修正できていなかったなどの問題を考慮しての方針としています。

同一関数内でフラグによる制御するパターン:

const { singleGroupActivationFlag } = useFlags();

const handleSubmit = useCallback(
    async (value: TopicCreateValue) => {
       
   // フラグが適用される場合の処理    
        if (singleGroupActivationFlag) {
            await createOrUpdateTopic(value);
   // それ以外
        } else {
            await createOrUpdateGroupTopic(value);
        }
    },
    [...]
  );

4-3. フィーチャーフラグの追加・更新管理

また、フィーチャーフラグを追加し忘れて実装してしまうことも一部発生していたので、フィーチャーフラグが必要かどうかのチェックと、名前、対象範囲、消すタイミングを開発チケットの段階で記入することで、抜け漏れを防ぐようにしました。

これにより、チケット作成の段階でフィーチャーフラグの考慮をするようになり、実装漏れすることがなくなりました。

f:id:xiaochuan:20211208134605p:plain
👆実際のチケット

5. 解決できた課題とこれから

以上のようにフィーチャーフラグをうまく利用することで、開発コストの大きな削減と品質の向上につなげることができました。

現在はフラグが増えてきたこともあり、不要なフラグをきちんと削除することや、命名ルールなどを揃えてオペレーションミスが発生しづらくするなど、引き続き改善しています。

また、LaunchDarklyの料金プランを上げると、スケジュール機能A/Bテスト機能なども利用できるので、このあたりは今後利用を検討していけたらと思っています。

6. おわりに

今回は、フィーチャーフラグの運用で出てきた課題と、その解決アプローチとしてのLaunchDarkly活用についてご紹介させていただきました。

まだまだ試行錯誤中なので、フラグのうまい利用の仕方や、出し分ける機能の粒度など、他社さんのよいTipsがあったらぜひお話をお伺いしてみたいです。

Gaudiyでは他にも、アジャイル開発を改善していくための取り組みを色々行っているので、開発プロセスの改善に興味のある方がいたらぜひお話ししましょう!

(僕のMeetyです。DDD以外でも全然大丈夫なのでよければ!)

meety.net

Gaudiyの技術選定については、こちらの記事をご参考ください!

techblog.gaudiy.com

毎週水曜日、オープン勉強会やオープンオフィスもやってます!

www.notion.so