Gaudiy Tech Blog

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

クリエイターに還元し続けるNFTの流通を考えてみた

f:id:gaudiy:20210819121649p:plain

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

突然ですが、みなさんはNFTをご存知でしょうか? 聞いたことがある人や、中には実際にNFTを売買したことがある人もいるかもしれません。

Gaudiyでは、トークンエコノミーの実現に向けて、ブロックチェーンを活用したファンコミュニティサービスを開発していますが、その中で電子書籍やトレカ、チケットなどに「NFT」を活用しています。

今回は、そのNFTの売買、特に二次流通における課題と解決策をテーマに、リサーチした内容と私の考えをご紹介したいと思います。

本記事で取り扱う内容は以下です。

  • NFTの流通プロセスとロイヤリティという概念
  • クリエイターに永続的に報酬が入る仕組みは作れるのか?
  • ロイヤリティに関する課題とその解決策

本記事を読む前にNFTをキャッチアップしたい方は、日本総研が出しているレポートをご一読いただくのをおすすめします。

NFT(Non-Fungible Token)に関する動向

テックブログではありますが、コードを読まなくても理解いただける構成を心がけたので非エンジニアの方にも読んでいただきたいです。

1. NFTの流通プロセスとロイヤリティ

最初に、NFTの売買や流通の仕組みについて簡単にご紹介します。

NFTは、基本的には「NFTマーケットプレイス」と呼ばれる取引所で売ったり買ったりすることができます。

f:id:gaudiy:20210819112252p:plain
NFTの取引の流れとブロックチェーン
ref. NFT(Non-Fungible Token)に関する動向 p4

例えば、有名なものだとNBA TOPSHOTが挙げられます。バスケのプレー名場面を収録した動画コンテンツの売買ができる取引所です。

https://i.gyazo.com/0631b3ccafae952bdf95d7010090c957.gif

上記であげたNBA TOPSHOTは、NFTコンテンツ作者から直接購入できる「一次流通」のマーケットプレイスです。

これに対して、一次流通で売買したNFTコンテンツが売買されることを「二次流通」と呼びます。

イメージとしては、中古品の販売に近いです。コンテンツ作者から購入するのではなく、既に購入した人からNFTを購入する取引で「転売」と言われることもあります。

有名どころだとOpenSeaやRaribleが二次流通の機能を持ったマーケットプレイスとして該当します。

※厳密にはOpenSeaもRaribleも認定クリエイターとしてNFTコンテンツ作者が登録できるので、その人達と売買する場合は一次流通となります。なのでOpenSeaは一次流通と二次流通の機能を持ち合わせたNFTマーケットプレイスと言えます。

https://opensea.io/

Rarible – Create, sell or collect digital items secured with #blockchain

また、二次流通の手数料のことを「ロイヤリティ」といいます。NFTのユニークな機能のひとつで、上図の赤枠で囲んだ部分を設計することで得られる収益です。

NFTコンテンツ作者はもちろん、NFT購入者も自身がNFT販売者の立場になる際はロイヤリティ配布対象になり得ます。

ロイヤリティがあると、二次流通以降の取引でも継続的にNFTコンテンツ作者(+NFT購入者にも)に収益が入るので、NFTコンテンツの取引の活発化にむけたインセンティブになります。

例えばメルカリのようなプラットフォームで書籍を売っても本の作者には1円も入りませんが、NFT化した電子書籍コンテンツであれば、二次流通(転売)するたびにロイヤリティが作者に入ります。

2. クリエイターに永続的に報酬が入る仕組みをどう作るか?

NFTコンテンツを売買するとき、おそらく多くの方は、前述したNFTマーケットプレイスで取引するはずです。

大手のNFTマーケットプレイスでは、二次流通におけるロイヤリティを自身で設定することができます。例えば大手取引所のひとつRaribleでの具体的なロイヤリティ設定は以下です。

  • Raribleで取引されるNFTコンテンツに関しては10%のロイヤリティが設定できる
  • NFTコンテンツがRaribleで二次流通(転売)される場合も転売される度に10%のロイヤリティが作者に入る

しかし現状、RaribleとOpenseaといったNFTマーケットプレイス間でのロイヤリティの配布はできないので、別の取引所でユーザーが出品してしまうとNFTコンテンツの作者にはロイヤリティが入りません。

同じようなことは個人間売買にも言えます。作者にロイヤリティを払うと自分の取り分が減ってしまうため、この流れは想定できます。

f:id:gaudiy:20210818180524p:plain
二次流通をRarible以外の場所で行ったケース

このように、ロイヤリティを付与する/しないがユーザーに委ねられてしまうので強制力が働きません。これはユーザーがロイヤリティを設定するというUXに委ねられているのが原因です。

なので視点を変えて、アプリケーションレイヤーでの解決策ではなく、もう一つ下のプロトコルレイヤーでの解決策を深堀りしていきたいと思います。

NFT取引所ごとではなくデフォルトのNFT機能としてロイヤリティの仕組みを持たせたい

ひとつ下のレイヤー層でロイヤリティ機能を入れられたら、NFTマーケットプレイスごとに独自実装しなくて良いですよね。

結論から言うと、Ethereumというブロックチェーン上ではこの機能を提案する議論がされています。(提案のステータスがドラフト段階ではなく、最終段階のステータスになっているのでおそらく標準実装として入ると思ってます。)

また、Ethereum以外のチェーンだとNEARというブロックチェーンでもロイヤリティを配布する機能が実装がされているので、こちらも合わせて紹介したいと思います。

※レイヤーについての補足・・・ブロックチェーンには大きく分けてアプリケーションレイヤーとプロトコルレイヤーがあります。ブロックチェーンの機能として担保できるものが後者です。NFTマーケットプレイスはアプリケーションレイヤーにあたります。

f:id:gaudiy:20210818201305p:plain
ブロックチェーンにおけるアプリケーションレイヤーとプロトコルレイヤー
ref. https://www.fsa.go.jp/policy/bgin/ResearchPaper_MRI_ja.pdf

Ethereumにおけるロイヤリティ実装

Ethereumがもっているロイヤリティ機能の要約です。

  • 複数人に対して異なるパーセンテージでロイヤリティを配布できる(ex. NFTコンテンツの売上金のXX%はロイヤリティとして作者Aに、YY%は作者Bに対して支払われる)
  • ロイヤリティ機能が実装されたNFTコンテンツであればどこのNFTマーケットプレイス OR 個人売買でもロイヤリティが作者に配布される

github.com

複数人で作った共同作品を出品した場合、各々が異なるロイヤリティ額を受け取れる設計にできます。著作権の帰属先が複数ある場合などに使えそうです。

実際のサンプルプロジェクトを日本人の方が作成されていたので紹介させていただきます。 バーチャル空間で使えるNFTコンテンツを販売するマーケットプレイスのようです。ここで買ったNFTコンテンツは以後、転売する場合に作者のもとに一定のパーセンテージでロイヤリティが入る設計になっているとのことです。(詳細はこちらのnoteの記事が参考になります)

github.com

NEARにおけるロイヤリティ実装の仕組み

NEARというブロックチェーンでもEthereumと同様にロイヤリティを実装できます。 ロイヤリティ機能もEthereumとほぼ同じです。

Ethereumと異なるのはロイヤリティをパーセンテージではなく、額指定(単位は$NEAR)という点です。個人的にはNEARの価値が上下した際に一定額のロイヤリティ配布だと柔軟性がないようにも感じました。

具体的なNEARのロイヤルティ実装のインターフェイスは以下になります。

github.com

EthreumとNEARの両方の課題

ロイヤリティが配布されるタイミングですが、厳密にはNFTの売買するタイミングではなく、NFTが転送されたタイミングです。 問題はこのNFTの転送が行われたタイミングが「NFTの売買」なのか「NFTの移管」なのか区別ができない点です。

f:id:gaudiy:20210819071013p:plain
NFTの売買と移管はどちらも転送なので区別がつかない

本来の売買のタイミング以外でロイヤリティが過剰に発生してしまう課題に対しては今後方針を決めるようです。

One more reasonable approach MAY use the number of transfers of an NFT to decide which percentage value is used to calculate the royaltyAmount. The idea being that the percentage value could decrease after each transfer of the NFT. Another example could be using a different percentage value for each unique _tokenId.

Ethereumでは一つの提案として転送回数ごとにロイヤリティのパーセンテージを減らす、というアプローチ方法を挙げています。

3. さいごに

NFTコンテンツ作成者も購入者もお互いに取引したくなるようなインセンティブ設計していく上で、ロイヤリティの仕組みをどう扱っていくかが個人的には鍵になってくると思います。

本記事を読んでいただいて、NFT自体の本質的な価値などに興味が湧いた方は弊社CEOの石川が書いた記事がわかりやすいのでぜひこちらもご一読してみてください。

note.com

Gaudiyでは流通プロセスに関わる人全員がNFTコンテンツを扱いたくなるような世界を実現しようとしています。

自分は一年くらい前までブロックチェーンのことは何一つ知らないソフトウェアエンジニアでしたが、Gaudiyに入ってブロックチェーンの思想をチームで議論したり、最新の技術動向を教え合ったりしてこの世界にのめり込むようになりました。

少しでも興味を持っていただけたエンジニアの方は、ぜひTwitteri(@kei32bit)やMeetyなどお気軽にご連絡ください。

▶Meetyはこちら

▶オープンオフィス・オープン勉強会はこちら

Gaudiyがフロントエンド開発でフィーチャーフラグをどう使っているか

f:id:gaudiy:20210812085458p:plain

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

弊社では最近、フロントエンド開発で「フィーチャーフラグ」の運用を開始しました。

フィーチャーフラグは「信頼性を保ちつつ開発スピードを高める手法」として知られていますが、その運用はプロダクトの特徴や開発のレイヤー、チームの特性などによって様々だと思います。

そこで今回は、Gaudiyでのフィーチャーフラグ導入の背景や、実際の運用の仕方、1ヶ月ほど運用する中で感じた気づきや学びについてブログにまとめてみようと思います。

※フィーチャーフラグはフィーチャートグルとも呼ばれますが、この記事ではフィーチャーフラグの名称を使用しています。

なぜ導入したのか

導入の背景としては、Gitフローからトランクベース開発へと開発手法を変更したことがありました。

それによって、メインブランチを常にリリースできる状態に保つ必要が出てきたことから、そのための手法としてフィーチャーフラグの運用を始めることになりました。

※トランクベース開発への移行背景などは、弊社の @winor30 が前回のブログに書いていますので、併せてご覧いただけると嬉しいです。

techblog.gaudiy.com

フィーチャーフラグとは何か

そもそもフィーチャーフラグとは、「コードを変更することなく 、システムの動作を機能(フィーチャー)単位で動的に変更することができる」開発手法です。

これにより、機能ごとにオン / オフを切り替えることができるようになります。(詳しくは以下の記事がわかりやすかったです。)

martinfowler.com

フィーチャーフラグの種類は複数ある

フィーチャーフラグの種類は複数あります。どのフィーチャーフラグも、機能ごとにオン / オフを切り替えることができるものですが、どういった理由で切り替えたいのかによって使う種類が異なります。そのため、どのフィーチャーフラグを運用するかは、プロダクトや開発のレイヤー、組織によっても変わってきます。

弊社の場合は、現在フロントエンド開発で「リリースフラグ」「アクティベーションフラグ」の2種類のフィーチャーフラグを運用しています。

1. リリースフラグ

これは、Gitフローで開発していた時のフィーチャーブランチの代わりになるフラグです。新機能のリリースやリファクタリングの際に使用され、リリース後にはコードからもデータからも削除されることが想定されるものです。

2. アクティベーションフラグ

これは、テナントによって提供する機能を出し分けるためのフラグです。特定の機能をもつテナントにはリリースしたいけれど、他のテナントにはリリースしたくないときなどの制御に使います。

弊社では複数のテナントが存在するプロダクトを単一のコードで提供しているため、このアクティベーションフラグを活用することで各テナントごとに機能を提供できています。リリースフラグとは違い、その機能が全体を通して削除されることがない限り、半恒久的に使用されます。

フィーチャーフラグの実装方法

大まかな流れとしては、BFFで計算してbooleanで返却し、その値でフロントエンドで制御しています。

データベース

フィーチャーフラグに必要な値はFirestoreで管理しています。 ドキュメントIDを機能名にして、フィールドに releaseFlagactivationFlag を持っています。

BFF

マイクロサービスアーキテクチャを採用しており、フロントエンドからマイクロサービスへのアクセスをシンプルにするためにもBFFを設けています。 GraphQLとApollo Serverで構築されており、BFFからFirestoreの値を参照して、それを元に計算しています。 具体的には、以下のようなスキーマを用意しています。

# query.graphql
type Query {
  featureFlags: FeatureFlags!
  ...
}

# schema.graphql
type FeatureFlags {
  id: ID!
  chatReleaseFlag: Boolean!
  postReleaseFlag: Boolean!
  postActivationFlag: Boolean!
  ...
}

フロントエンド

Next.js でフロントエンドを構築しており、 Apollo Client でデータの取得をしています。

const Component = () => {
  const { chatReleaseFlag } = useChatReleaseFlag();
  return <div>{chatReleaseFlag ? <NextComponent /> : <PrevComponent />}</div>;
};

フラグの種類が増えてくると、コードがフラグだらけになってしまいメンテナンスコストが高まってくることが予想されるので、フラグはできるだけ上位のコンポーネントに置き、散在させないことを意識することが大切です。

フィーチャーフラグの運用方法

管理しているフィーチャーフラグの数が増えてくると、どのフラグがどのようなステータスなのかを把握するのが大変になってきます。

また弊社のプロダクトの関係上、BizDevやコミュニティマネージャーなどのエンジニア以外の人ともどういった機能がリリースされているかなどを把握し、全社共通の言葉として使っていかなければなりません。

そのため、今どのようなフラグがあり、どういったステータスなのかを誰でも確認できるようにしています。(弊社では情報管理のアプリケーションとしてNotion を活用しているので、一覧で確認できるページを作成しています。)

f:id:gaudiy:20210811232222p:plain
Notionで作成した「フィーチャーフラグ一覧」

運用してみての課題 & 改善

まだ運用してみて日は浅いですが、以下のような点は課題だと感じています。

1. コンポーネント設計次第ではフラグを置く位置が多くなってしまう

特に既存のコードにフラグを置くときは、もともとフラグを置く想定をせずにコンポーネント設計をしていたため、散在してしまうこともありました。

2. フィーチャーフラグの切り替えで直接データベースを触っている

エンジニア以外の人が変更することもあり、直接データベースを触るやり方はミスが発生しやすくなります。それを防ぐには、管理画面を用意して切り替えられると良いかと感じています。

この辺りは、今後、運用しながら改善していきたいと考えています。

まとめ

今回は、弊社のフロントエンド開発で使用しているフィーチャーフラグについて紹介させていただきました。 Gitフローからトランクベース開発への変更とともに、リリースサイクルを早めることや、別プロジェクトとのリリースタイミングの連携も取りやすくなりました。

まだまだ改善できる点やこれから出てくる課題もあると思いますが、引き続きよりよい開発ができることを目指していきます。 もしGaudiy に興味を持っていただいた方は、ぜひお気軽にお話ししましょう!

youtrust.jp

gaudiy3.notion.site

トランクベース開発とカンバン改善でリリース速度を早めたDevOpsの取り組み

f:id:gaudiy:20210804120506p:plain

こんにちは、Gaudiyでエンジニアをしている勝又(@winor30)です。

アジャイル的に開発することは、ソフトウェアに関連するサービスをもつ会社であれば、ほぼ全ての企業が採用する意思決定だと思います。不確実性の高い現代社会において、柔軟かつ効率的にアプローチができる手法なためです。

そのプラクティスでよく言われることとして、「小さいバッチで開発して、頻繁にリリースをしよう」というものがあると思います。これを悪だという開発者の方はほとんどいないと思いますが、その実践はかなり難易度が高いと思います。

実際にGaudiyでも、アジャイルが大切であることは理解しながらも、個人の意識、文化、しくみ等が十分ではなく、自然とアジャイルから離れることを行ってしまうことがありました。

そこで最近、QAやユーザー価値を担保しながら「小さいバッチで開発して、頻繁にリリースをしよう」という理想を追求するために、トランクベース開発をはじめとした様々なしくみやプラクティスを導入してみました。

実際に成果も出てきているので、今回はその取り組みをご紹介していきたいと思います。

そもそも「小さいバッチで開発して、頻繁にリリースをしよう」なのはなぜ?

f:id:tkatsumat:20210804083939j:plain

問題点や実際やったことを書く前に、先に理想的な状態とその理由に関して書いておきたいと思います。

そもそも「小さいバッチで開発して、頻繁にリリースをしよう」なのはなぜか、についてです。これは、アジャイル的な開発を進めていき、よりユーザー価値のあるプロダクトをアウトプットすることに繋がるためです。

なぜアジャイルが使われるか?と同じ理由にはなりますが、どんなユーザー価値があるのか?どうやればよいのか?というのは、現代の市場やプロダクトの不確実性が高いことから、すべてを詳細まで予測することはかなり難しいです。

そこでアジャイル的な開発では、今提供できるユーザー価値を頻繁にアウトプットしていくことで不確実性を徐々に潰しつつ、フィードバックループを回して意思決定の変更を頻繁に行うことで、最終的な予測を確実なものにしていく必要があります。この意思決定の変更を頻繁に行い、プロダクトを正しく作るためにも「小さいバッチで開発して、頻繁にリリースをしよう」が必要となります。

この「小さいバッチで開発して、頻繁にリリースをしよう」やアジャイル的な開発がなぜ必要なのか?に関しては、最近の資料ですと、@t-wadaさんが書かれた下記資料が非常によく分かるので、ぜひ一読いただきたいです。(他の話題に関しても書かれていますが、歴史から理解できる内容だと思います)

speakerdeck.com

既存のしくみ・問題点

既存のしくみは、カンバンとGitフローを採用した開発フローになっていました。ざっくり説明すると、カンバンの1チケットが1つのPRに相当し、このチケットが大きな機能を表現していました。それを様々なステークホルダーでレビューした上でマージし、全体の機能ができたらリリースをしていく流れとなっていました。

理想状態を目指す上では、基本的に大きなバッチの開発によるリードタイムの低下が問題となっていました。さらにその原因を細分化すると、下記のような問題がありました。

  1. リソース効率(マルチタスク)に陥りやすい
    • mainブランチとの乖離が大きいfeatureブランチでQAをする
      • 開発以外の視点がこのときに入るのは👍
      • 差分が大きくて、マージまでの速度が上がらない → 待っている間に他のタスクをやる → リソース効率
  2. コンフリクトやデグレリスクが高まる
    • 早くmainブランチに取り込まれないため、差分が大きくなりコンフリクトやデグレの確率が上がっていた
    • 結局mainにマージする前のreleaseブランチでリリースする機能すべてにQAをして、バグを洗い出し、リリースみたいな感じになってしまい、アジャイルらしくなかった
  3. ユーザー価値の測定・判断が不明確
    • featureブランチでの検証や価値を判断する項目が多い
    • もっと前に気づけたのでは?みたいなことがあって出戻る

上記の問題を解決するために、トランクベース開発の導入とカンバンの見直しを行いました。

トランクベース開発とは?

引用:Trunk Based Development

トランクベース開発とは、メインブランチ(トランク)をベースとして、トランクに対して修正を行っていく方法です。詳細に関しては、GCPの記事が分かりやすいかと思います。

DevOps 技術: トランクベース開発 | Google Cloud

トランクベース開発の本質的な価値としては、トランクと修正するブランチの差分が極限まで下がり、コンフリクトやデグレリスクを下げつつ、トランクを常に最新の状態に保つことができる点だと思います。

この性質が特に今回の課題であった「1. リソース効率に陥りやすい」「2. コンフリクトやデグレリスクが高まる」に関して、効果がありそうだと考えました。

カンバンで足りなかったところは?

今までのGaudiyのカンバンでは、「ストーリーを小さく分割し、リードタイムを短くする」という部分に対して、うまく動けなかったところがありました。これを実現することによって、このチケットでなにを行えばよいのか?というゆらぎが減りつつ、最速でユーザーへの価値提供ができるようになり、様々な側面での不確実性を減らすことができるようになります。

これは当たり前ではあるのですが、意外とカンバンやスクラムをやることに集中してしまい、それに慣れてしまって形骸化していたのが事実としてあったので、今回の機会にカンバンとしてどう進めればよいのか?何を意識すべきなのか?というところを再考しました。

実際に導入したトランクベース開発とカンバンのプラクティス

f:id:tkatsumat:20210804092057j:plain

今回行ったトランクベース開発とカンバンのプラクティスは、下記のようなものを導入しました。

  • トランクベース開発に必要なプラクティスの導入
    • Githubフローライクな自動デプロイ設定
    • 同期的なレビューを率先して行う
    • mainブランチがデプロイできない状態を作らないように徹底する
  • カンバンの見直し
    • デイリースタンドアップで青ワークに切り替える
    • ストーリーの価値を明確にし、その検証を小さく多角的に行う
    • WIP制限をうまく使い、リリース頻度を上げる

トランクベース開発に必要なプラクティスの導入

トランクベース開発は原則として、トランクを中心に開発していく開発手法になります。ただし、これを実現するためには、レビューコストと自動テストが課題となります。そのため、トランクベース開発を導入しつつこのあたりの課題も解決するようなプラクティスを導入しました。

Githubフローライクな自動デプロイ設定

Gaudiyでは今までGitフローを採用していました。開発してPRがマージされたものが取り込まれるdevelopブランチが存在し、大きな機能開発があるときはfeatureブランチを作ってそこで開発していました。リリース準備にはリリースブランチを切り、最後にmainブランチにマージすることで、デプロイ・検証・本番反映を通してリリースが完了するような流れでした。

わりと自然にこのような形にたどり着いたのですが、ブランチ間の差分が大きくなることが多々あり、コンフリクトリスクやレビューのコストが増大していました。

ここから、トランクベース開発に変えるために、developブランチを削除し、PRを基本mainブランチからしか切らないようにしました。

f:id:tkatsumat:20210804084649p:plain

また、各環境のデプロイに関しては、mainブランチマージ時にdevelopとstaging環境にデプロイし、mainからリリースタグを切ることによって本番環境にデプロイするようになっています。この理由としては、基本的にmainブランチにマージされたものがユーザー価値の現在の最新状態であるため、それを各環境にできるかぎり反映し、検証やすぐに本番反映できるような状態にしておきたかったためです。

f:id:tkatsumat:20210804085237j:plain

同期的なレビューを率先して行う

トランクベース開発の原則として、mainブランチとPRの差分は極力減らす必要があります。そこで大事なのが、レビューの速度を上げることです。そのため、Gaudiyでは以前から取り組んでいるペアプロを率先して行いつつ、ペアプロを行わなかった場合でも同期レビューを頻繁に行うようにしました。

基本的に非同期のレビューも行ってはいるのですが、デイリースタンドアップ等でPRを投げているがレビュー待ちなものがあるというところから判断し、同期レビューをそこでアサインするようになっています。

f:id:tkatsumat:20210804081956p:plain

mainブランチがデプロイできない状態を作らないように徹底する

トランクベース開発では、mainブランチは基本いつでもデプロイできる状態を作る必要があります。これを実現するために、下記のようなことを行いました

  • featureフラグをうまく使う
  • 自動テストを使って、品質を担保する

featureフラグとは、新しい機能を隠してリリースを行いたいときなどに、その機能を隠す(制御できる)フラグのことです。featureフラグはかなり昔からある考え方になりますが、トランクベース開発ではデプロイ可能状態というものを維持することが重要になるので、featureフラグを使いユーザーにはまだ見せないがデプロイはしたいみたいなことを実現できる必要があります。

自動テストを使って、品質を担保するについては、基本的にはよくあるCI時の自動テストになります。GoでもReactの場合でもunit test、hooksのtest、コンポーネントのインテグレーションテストなどCI環境で実行できるものはすべて実行し、基本的に品質担保を目指します。また、GaudiyではAutifyという自動E2EテストのSaaSを利用しており、これを毎日実行することでmainブランチの品質担保をしています。

詳しくはGaudiyの西岡が下記ブログで説明しているので、興味ある方は読んでいただければと思います。

GaudiyがAutifyを導入して手戻りコストを削減した話 - Gaudiy Tech Blog

また、このあたりのテストや検証で気づいたりした場合は、基本的にその問題の優先度を上げ、なるべくデプロイ可能な状態を作ることにフォーカスすることも重要な点です。

カンバンの見直し

さらに、「小さいバッチで開発して、頻繁にリリースをしよう」を達成するため、カンバンでもいくつかの点を見直しました。これらの改善点も基本的にはアジャイル的な原則に従った、ということが結論になります。

デイリースタンドアップで変更できるようにする

f:id:tkatsumat:20210804090621j:plain

デイリースタンドアップが形骸化されていたときは、タスクの進捗や困ってることの報告がメインになっていました。この方法でも、どこまでチームが達成しているのか?が分かるので良いとは思うのですが、アジャイルの原則で言えば、そういったことを踏まえてどう柔軟に意思決定を変えていけるか?ということが大事になります。

これを実現するために、デイリースタンドアップでは上記のような報告に加え、どうしたらよりリードタイムを縮めることができるかをベースに、どう変更することができるのか?を問いかけるようにしています。具体例としては、ストーリーの分割を行ったり、ビジネスの状況から考えて次優先すべきところを話したりなどがあります。

また、この変更するような作業を「青ワーク」と呼び、プログラミングやデザイン作るなどの作業を「赤ワーク」とGaudiyでは呼んでおり、言葉としても使うことで「今は青ワークだから変更に柔軟になろう」と意識付けられるようにしています。

ストーリーの価値を明確にし、検証を小さく多角的に行う

https://i.gyazo.com/967f7893e1df900a0c5f65794ac8a1e2.png

f:id:tkatsumat:20210804082055p:plain

もうひとつ、ここも形骸化されやすいポイントですが、チケットのストーリーの価値を明確にすることに注力しました。基本的にテンプレートを作成し、作業に入る前には必ず書くようにしました。このチケットを達成したとき、ユーザーにどんな価値を提供できるのか?というところを明らかにしてから作業に入るように徹底しています。

また、ユーザー価値の検証のためにストーリーが一通りできたら、エンジニア、デザイナー、Biz、コミュニティマネージャーなど様々な視点からそのストーリーの検証を同期的に行い、どこが良いか、どこが改善必要 or 足りないかなどを実際にアプリを触りながら話すようにしています。

ストーリー分割とこのプロセスが合わさることで、かなり認識のブレはなくなりつつ、開発としてもYAGNIな精神を維持することで、バーティカルスライスを意識した開発を実現することができます。

WIP制限をうまく使い、リードタイムを減らす

f:id:tkatsumat:20210804090834p:plain

引用:Recruit Tech Blog

カンバンの原則として「WIP制限」というものがあり、これを徹底することでリードタイムを下げるようにしています。

詳しくは下記記事が分かりやすく書かれているので、こちらを見ていただければと思います。

SUUMOアプリチームがスプリントを廃止してカンバン方式に移行した話

WIP制限とはフロー効率的に動くためにカンバンボードに導入される仕組みとなります。フロー効率とは、たくさんの仕事に労力をかける(リソース効率)よりも、何かの1つの仕事にフォーカスし、それを終わらせたあとに次の仕事に集中する方式(フロー効率)のほうが最終的にかかる時間は同じ、かつリードタイムは短くなるという考え方です。これを実現するために、カンバンではWIP制限というものが存在し、カンバンボード内で取り掛かることができるチケットの枚数を制限しています。

Gaudiyでは、作業中やレビュー中などのレーン単位でWIP制限を導入し、基本的にそれを超えないように作業しています。WIP制限により、多くの種類の仕事ができないため、ペアプロなどの同期的作業が強制され、属人化の防止やレビューコスト削減などの恩恵もあります。

結果

今回のトランクベース導入とカンバンの見直しを行いよりアジャイルな開発文化に変えた結果、リードタイムがかなり短くすることができました。また、下記例は1週間だけですが、基本的にこのぐらいのリードタイムを安定して出しているので、定常的にアウトプット出せているものだと思います。

f:id:tkatsumat:20210804082123p:plain リードタイム10日

f:id:tkatsumat:20210804082137p:plain リードタイム4日

また、定性的なものを例に上げると、チームのメンバーからも「開発フローがガラリと変わったけれど、よりアジャイルな開発になって前よりもストレスなく開発できる」という声も上がっていました。

まとめ

今回の記事で紹介したとおり、トランクベース開発とカンバンの改善を行ったことにより、アジャイルな「小さいバッチで開発して、頻繁にリリースをしよう」という理想的な状態に少しだけ近づくことができたと思います。

特に、チームのメンバーからも「アジャイルな開発に明らかに変わった感じがして良かった」という声が上がったのはかなり良かった点かなと思います。

ただ、まだまだ改善できる点はあり、Gaudiyはかなり不確実性が高い事業領域を扱っていることもあるので、よりアジャイルな組織を目指していければと思っています。Gaudiyの開発組織に興味を持っていただいた方は、ぜひ気軽にお話ししましょう!

▶︎カジュアル面談はこちら

▶︎オープンオフィス・オープン勉強会はこちら

GaudiyがAutifyを導入して手戻りコストを削減した話

f:id:gaudiy:20210730154604p:plain

こんにちは!エンタメ領域のDXを推進するブロックチェーンスタートアップ、Gaudiyで社員代表(笑)をしている西岡(@TakeshiNishioka)です。

今回はスタートアップ企業の社員代表がどのような役割を担っているかを、この場を借りて紹介させていただきたいと思っています。

…というのは冗談で、今回は主に業務で携わっているプロダクト開発のプロセスや、QAまわりのお話をさせていただこうと思います。

前回に永井(@sho0910K)から紹介させていただいたATDDの話にも関係する内容になりますので、併せてご覧いただけると嬉しいです。

techblog.gaudiy.com

プロセスやQAまわりお話といわれても「?」と思いますので、そもそもの前提からお話しします。

Gaudiyに求められる速度と品質

Gaudiyはいわゆるスタートアップといわれる企業ですが、事業ドメインがエンタメ領域ということもあり、週刊少年ジャンプの漫画『約束のネバーランド』など人気IPのコミュニティサービスを開発・運営させていただいています。

人気IPかつ、集英社やアニプレックス社など誰もが聞いたことのある企業様との協働になりますので、弊社が提供するコミュニティサービスには高いレベルのクオリティを求められていますし、プロダクトの品質も同様となります。

さらに複数のコミュニティを並行開発しており、まだ未発表のIPも多数動いている状況のため、肌感覚で普通は3ヶ月ほど掛かる規模の開発を1ヶ月でリリースするぐらいのスピード感が求められています。

ただ早ければ良い訳ではなく高い品質も求められますので、個々のスキルは当然ながら、チームとしてどれだけ効率良くプロセスを推進できるかが大切になります。

分かりやすくいうと、どれだけ手戻り作業をなくせるか、どれだけ重複や無駄な作業をなくせるか、が肝になります。

手戻りや重複など無駄な作業を発生させない為に

無駄な作業を発生させない為に、GaudiyではAgile的な取り組みを実施していますので、3つ紹介します。

スリーアミーゴス

前回のATDDでも紹介されていますが、Biz(BizDev、コミュニティマネージャー)、デザイナー、エンジニア、テスター(テスターはPOやPdMが兼任することが多い)が、ストーリーマッピングや受け入れ条件の設定、QAにも参加して、多角的な視点を取り込みながらプロダクト開発を推進しています。

早い段階から複数職種の視点を加えることで、開発視点だけでなく、クライアント要求、顧客価値の側面で問題点に気付け、手戻りの発生を防ぐことができています。

とはいえ、大人数になって逆に効率が悪くなるのではないか?と思われるかもしれませんが、Gaudiyでは最小・最適なコラボレーションを促進しているので、 個別に確認できることは日々のコラボレーションで解決したり、同じロールの人が複数参加しないなど、同じ視点が重複しないように意識しています。

f:id:nissy18:20210730165835p:plain

GaudiyではFourAmigos

バーティカルスライス

次に、ストーリーを可能な限り小さく分割することを意識しています。

具体的には、実装からQAまで最大でも3日で完了できるボリュームに抑えています。

その理由として、Gaudiyではカンバンを運用していますが、大きいチケットでは1つのレーンに数日間留まってしまい、同じチケットだけでWIP制限に達するなどしてレーン全体の動きが滞りかねません。視覚的に動きがないとメンバーのモチベーションにも影響を与え、ボディーブローのようにチームの生産性を落としていきます。

一方ストーリーを小さくすると、チケットに対する解像度が上がり、デイリースタンドアップで他のメンバーからの疑問や懸念も挙がりやすくなったり、担当者が気付けていない問題や課題が見つかりやすくなりました。

また、無駄のないハッピーパス(正常系)を通すことができるようになり、ハッピーパスのQAを早い段階で行えるので、QAで挙がった修正箇所の修正コストも抑えられています。

さらにQAが必要な範囲も狭まるので、QAに参加するスリーアミーゴスの拘束時間も減らすことができています。

f:id:nissy18:20210730170807p:plain

薄くスライスしてもケーキとして価値がある

リグレッションテスト

最後はリグレッションテストです。けっこう普通に思えるかも知れませんね。

ただ前述の通り、小さいストーリーで細かく結合しているので、その度に既存機能でデグレが発生していないかをテストする必要があります。

まとめてリグレッションテストをしてデグレが見つかると、手戻りの修正コストが大きくなるので、ストーリーを結合する度にテストを実施しています。

頻繁にリグレッションテストを実施するので、常にリソースが枯渇しているスタートアップでは手動テストは現実的に難しく、その問題を解決する為にUI自動テストを導入しています。

ただUI自動テストを導入するといっても、エンジニアにテストコードを書いてもらうのもリソース的に厳しいので、ノーコードでE2Eテスト作成・自動化できるツールの導入を検討しました。

いくつかのツールを検討して、GaudiyではAutifyを選定しました。

autify.com

選定した理由は下記の通りです。

  • シンプルで直感的に操作しやすく非エンジニアでもテストが作りやすい。
  • AIによる画面の細かなズレも学習してチェックしてくれる。
  • CSがとにかく丁寧に対応してくれて、かつリードタイムが早い。

またUI自動テストをどのように使っているか?ですが、まずは開発プロセスの中にUI自動テストのテストシナリオを作成するプロセスを組み込んでいます。

どれだけツールが優秀でも、それを使わないと意味がないので、カンバンにテストシナリオ作成・実行のレーンを設置しています。

また作成されたテストシナリオは、以下のケースで実行するようにしています。

<定期実行>
定期的に11回実行しています。
テスト結果がNGの場合は、NG箇所を確認してOKになるように修正して再実行します。


<手動実行>
Autifyのテストプランを実行するSlackアプリを作成して、任意のタイミングでSlackから簡単に実行できるようにしています。
開発中のコードが既存機能に影響を与えていないかをいつでもチェックできるようにしています。

f:id:nissy18:20210730134907p:plain

Slackアプリ(Hatty)がAutifyのテストプランを実行

<自動実行>
GaudiyではSlackでリリース告知を行っていますが、リリース告知を行っても上記のSlackアプリが起動して自動でリグレッションテストが実行されます。

このようにGaudiyでは、UI自動テストによるリグレッションテストを頻繁に実行することでリリース後のデグレを防止するとともに、開発プロセスでの手戻りの発生を抑えています。

Autifyを使ったテスト事例をちょっとご紹介

先ほど紹介したAutifyを、Gaudiyでは「こんな感じで使ってますよ!」というのを少し紹介したいと思います。少しでも参考になれば嬉しいです。

前述の通り、Gaudiyではリグレッションテストを何度も実行しますので、繰り返し実行が可能かつ同じ操作が行われ、同じ結果にならなければなりません。

また同じ操作が行われ、同じ結果になったとしても、初回と2回目以降で違うロジックが走ってしまうのもテストとしては不十分です。

基本的にはテストシナリオはポチポチ操作だけでほとんどの画面や機能のテストシナリオは誰でも作成できます。ただ、Gaudiyのコミュニティサービスでは、DID(分散型ID)で外部アプリとID連携して取得したデータを使うファンバサダースコアや招待機能など、データを操作しないと繰り返してテストが行えない機能もあります。

そんな機能のテストでは、AutifyのJSステップ機能を使い、JavaScriptからコミュニティサービスのテスト用APIを呼び出してデータの初期化や登録、アカウントのステータスを更新するなどしています。

f:id:nissy18:20210730114424p:plain

データを初期化するJSステップ

f:id:nissy18:20210730114515p:plain

データを登録するJSスキップ

上記のようにGaudiyでは、AutifyのJSスキップとテスト用APIを駆使して、複雑な機能や手動では複数人で行う必要がある機能のテストを自動化しています。

さいごに

今回は手戻り作業などで発生してほしくないコストをなくす為の取り組みについてご紹介させていただきました。

スタートアップでは、エンジニアのリソースが常時不足しているのはよく耳にする話ではありますが、エンジニア以外のリソースも常時不足しています。

そんな状況下でGaudiyでは、組織・チームとして手戻りや重複など無駄なコストをいかに発生させないかについて強い意志を持って取り組んでおり、今回紹介したこと以外にも、フレームワークやツールの導入も積極的に行い、最大効率、最小工数で最大成果を生み出す組織を目指しています。

そんなGaudiyに少しでも興味を持ってもらえましたら、ぜひ一度お話を聞きに来てください。

▼毎週水曜、オープン勉強会&オープンオフィスを開催しています

gaudiy3.notion.site

▼カジュアルにお話ししましょう

youtrust.jp

ATDDの実践 ー非エンジニアの視点を取り込んだフロントエンドTDDの進め方ー

f:id:gaudiy:20210721141037p:plain

こんにちは!Gaudiyエンジニアの永井(@sho0910K)です。

今回はGaudiyのフロントエンド領域の開発で実施しているテストに関してご紹介したいと思います。

第2回の内容で弊社の後藤(@PTeamd)からも紹介がありましたが、Gaudiyではコラボレーションを重視した組織文化、プロセスを採用しています。そのテストにおいては、ATDD(受け入れテスト駆動開発)を推奨・実施しています。

プロジェクト単位で開発していますが、各プロジェクトチームに関わるメンバーとしては、以下3つの職種が存在しています。

  • Biz(BizDev、コミュニティマネージャー)
  • デザイナー
  • エンジニア

ATDDでは、このメンバー間でコラボレーションすることで、プロダクトの品質を高めています。

Gaudiyが抱えていた課題

まず、GaudiyでATDDを採用した背景としては、リリースサイクルを回す中で、Biz・デザイナーとエンジニアとの間で、コラボレーションの課題が存在していました。

具体的には、

  • エンジニアがリリースしたものをBizがわからない
  • Bizとデザイナーが意図したものと異なる形でリリースされてしまった

などです。

結果として、エンドユーザーに対してのリリース告知に漏れが発生したり、体験として良くないものを提供してしまうなどの課題が存在していました。

これを解消するために、リリース前のテストを手厚くするなど、Bizとデザイナー、エンジニアでテスト実施のコラボレーションをすることも考えました。

しかし、そもそも開発に入る時点にフォーカスすることで手戻りを無くすことや、エンジニアが何を開発していて、次にエンドユーザーに向けて何をリリースできるのかを事前に把握することができないか、それらを実践できる良い手段は存在しないかを求めてたどり着いたのが「ATDD(受け入れテスト駆動開発)」でした。

ATDDとは

ATDDを取り入れていくにあたっては、BASEさんの資料がとても参考になりました!
詳しくはこちらの資料を見ていただいたほうが理解しやすいと思いますので、ここでは省略させていただきます。

ATDDは、Acceptance test–driven development(受け入れテスト駆動開発)とあるように、ユーザーストーリーの受け入れ基準をベースとしたTDD(テスト駆動開発)になります。

開発するにあたってのユーザーストーリーの受け入れ基準は、エンジニアだけで書けるものではありません。つまり、コラボレーションを重視したテスト駆動開発になります。

f:id:strawberry4062:20210721095921p:plain

GaudiyのATDDプロセス

GaudiyのATDDプロセスは以下の手順で行われています。

  1. チケット上でのストーリー受け入れテスト作成
  2. フロントエンドTDDの準備
  3. フロントエンドTDD
  4. レビューでの受け入れ条件の確認

それぞれ順を追って説明したいと思います。

1.チケット上でのストーリー受け入れテスト作成

Gaudiyでは、開発のチケット管理をClubhouseを使って管理しています。
開発チケットはユーザーストーリー単位で作成しており、Bizとデザイナーと一緒に作成しています。そのため、このチケット内に受け入れ基準をベースとしたテストケースを記述していくようにしました。

こうすることで、そのユーザーストーリーでエンドユーザーに届けたい価値を確認しつつ、それを達成するための受け入れ条件としては何が必要になるのかをスムーズに記載していくことができます。

チケットのサンプル

f:id:strawberry4062:20210721085141p:plain

このテストケースの作成に関しては、Gherkin記法を採用しています。
これはBDD・ビヘイビア駆動開発 と呼ばれる、振る舞いを軸とした開発手法ですが、この振る舞いをユーザーストーリーの受け入れ基準として扱う点でATDDとしても利用ができます。

Gherkin記法はそれぞれ、Given(振る舞いを実行する前の状態)、When(振る舞い)、Then(振る舞いの結果)を表しています。Andは複数条件の場合に利用します。

例)
Scenario: 特定のコミュニティをフォローできる
Given ログイン済み
And 未フォローのコミュニティがある
When 特定コミュニティのフォローボタンを押す
Then 特定コミュニティがフォローできる

BDDツールにもいくつか存在しますが、ほぼ自然言語のみで書くことができ、非エンジニアとの共通認識をとりやすい点、また後ほど紹介するフロントエンド開発でのTDDプロセスへの流用も扱いしやすかったこともあり、CucumberのGherkin記法を採用しました。

2.フロントエンドTDDの準備

コラボレーションして記載したテストケースを使い、今度はフロントエンドにてTDDで開発を進めていきます。ここでは、Clubhouseで作成したテストケースをそのまま流用できるようにしています。

フロントエンドの開発環境には、Visual Studio Codeを利用していますが、Gherkinを扱いやすいように事前に2つのExtensionを導入しています。

marketplace.visualstudio.com

marketplace.visualstudio.com

まずはテスト用のディレクトリに、featureファイルを作成し、Clubhouseで記述したテストケースを貼り付けます。このまま保存すると、CucumberのExtensionによってフォーマットされます。

Feature: コミュニティのフォロー処理

Scenario: 特定のコミュニティをフォローできる
Given ログイン済み
And 未フォローのコミュニティがある
When 特定コミュニティのフォローボタンを押す
Then 特定コミュニティがフォローできる

Scenario: フォロー後続けて、別の未フォローコミュニティのフォローボタンを押す
Given ログイン済み
And 未フォローのコミュニティがある
When 特定コミュニティのフォローボタンを押す
Then 特定コミュニティがフォローできる

Scenario: 特定のコミュニティをフォローした後、フォロー解除ができる状態になる
Given ログイン済み
And 未フォローのコミュニティがある
When 特定コミュニティのフォローボタンを押す
Then フォロー解除ボタンが表示される

次に、このファイルからテストコードを自動生成します。
ファイル内の Feature 部分にフォーカスを当てて右クリックメニューを表示すると、「generate code from feature」というメニューがあるので、これをクリックすると、クリップボードにテストコードがコピーされます。

コピーされたテストコードは、事前に用意しておいた、テストファイルに貼り付けます。

https://i.gyazo.com/f9fb7712179d689c3a61160148d80412.gif

3.フロントエンドTDD

エンジニアがTDDで開発を行っていく流れになります。
テストケースが複数ある場合は、1つ目以外は一旦はskipにしつつ、コードを組み立てながらテストを確認していきます。
テストコードは、Given-When-Thenにあわせて記載していきます。

テストコードのサンプル
test('特定のコミュニティをフォローできる', ({ given, and, when, then }) => {
given('ログイン済み', () => {
render(<CommunityCard userId={USER_ID} community={communityData} />);
});

and('未フォローのコミュニティがある', () => {
expect(screen.getByRole('button').textContent).toBe(`フォローする`);
});

when('特定コミュニティのフォローボタンを押す', async () => {
fireEvent.click(screen.getByRole('button'));
await wait();
});

then('特定コミュニティがフォローできる', async () => {
expect(screen.getByRole('button').textContent).toBe(`フォロー中`);
});
});
4.レビューでの受け入れ条件の確認

エンジニアによる開発完了後、プルリクエストの段階でもBizとデザイナー含めてレビューを実施するのですが、コードも少しわかるメンバーの場合は、アプリケーションとしての動作確認だけでなく、実際に受け入れ基準が守られているかをコードベースでも確認してもらうことができます。

また、ATDDの形でテストコードを書いていることで、他プロジェクトのエンジニアがレビューする際にも、何のためのコードなのか、これによってどんな価値を届けることができるのかを確認の上でコードレビューしてもらうことができます。

さいごに

フロントエンドでのATDDに関して、チケットでのコラボレーションから実際のコードでの実装まで書きました。

今回紹介したのはReactのhooksとコンポーネントのテストにスコープを置いた内容となっていますが、ユーザーストーリーによっては、ページをまたぐ場合など、E2Eレベルのテストだったり、パフォーマンスなど、実証ツールが必要な場合も存在しています。その時は、Autifyやマニュアルテストも取り入れています。

テスト駆動にならないものも存在してしまいますが、プロダクト開発で大切なことは、ユーザーストーリーをプロダクトの価値として、僕らのユーザーであるファンの方々に届けられることだと思いますので、そこをブレさせないためにも、エンジニア以外の視点をテスト観点に織り交ぜていくATDDはオススメできるものだと思います。

このブログを読んでご関心を持ってくださる方がいれば、ぜひ一度カジュアルにお話ししましょう!TwitterのDM(@sho0910K)でも、募集リンクからでもぜひお気軽に。

youtrust.jp