inSmartBank

B/43を運営する株式会社スマートバンクのメンバーによるブログです

サブスクリプション機能制御の設計における勘所

こんにちは、スマートバンクでアプリエンジニアをしている ロクネム です。

弊社では B/43という家計簿プリカアプリ を提供しており、つい先日サブスクリプションサービス「B/43プラス」をリリースしました。

このようなサブスクリプションを提供するサービスにおいては、そのサブスクリプションを利用しているユーザーのみが特定の “機能” を使用できるように “制御” する必要があるかと思います。

このサブスクリプションの機能制御を実装するにあたって、「サブスクリプションが有効ではない場合は機能を制限する」という設計では実は不十分で、その他にもさまざまな要件を考慮した上でより柔軟な設計を行う必要があります。

本記事では、このようなサブスクリプション機能制御の設計における勘所について、B/43プラスを例にご紹介します。

※ 本記事は B/43 Tech Talk 〜 Fintech×サブスクリプションサービス立ち上げの裏側〜 にて発表した内容を書き起こしたものとなっております

speakerdeck.com

機能制御の要件

詳細な設計について話す前に、まずは一般的なサブスクリプションにおける機能制御の要件について整理していきます。

プランごとに使用可能な機能の範囲

サブスクリプションにおいて、提供するすべてのプランで使用できる機能がすべて等しいとは限りません。 上位プランで使用できる機能が下位プランでは使用できないということも考えられます。

例えばB/43においては、現在はB/43プラスというただ1つのサブスクリプションのプランを提供していますが、今後他のプランを追加して使用できる機能の差を表現する必要が出てくるかもしれません。

仮想サービスのプランごとに使用可能な機能

サブスクリプションを利用可能な範囲

サブスクリプションにおいて、申し込んだ方のみが機能を使用できる対象となるとは限りません。 ファミリープランのように、1人のユーザーがサブスクリプションを利用することで複数のユーザーがサブスクリプションの機能を使用できる場合も考えられます。

例えばB/43プラスでは、申し込んだユーザーの持っているB/43カードを一緒に利用しているすべてのユーザーがB/43プラスの機能を使用できます。

B/43プラスを利用可能な範囲

機能制御の実装パターン

次に、サブスクリプションにおける機能制御の実装パターンについて整理していきます。

サーバー側で機能制御の処理が完結するパターン

サブスクリプションの機能使用時に、サーバー側で機能の使用可否を判定して処理する場合がこのパターンに該当します。

例えば、B/43プラスでは「1年以上前の支出まとめ閲覧」という機能を提供しており、B/43プラスを利用していないユーザーが1年以上前のまとめを閲覧しようとした場合はエラーを表示しています。

「1年以上前の支出まとめ閲覧」の機能制御

この場合、支出まとめのデータを返すAPIにて、ユーザーが「1年以上前の支出まとめ閲覧」の機能を使用可能かどうかを判定し、その結果に応じて正常なレスポンスかエラーレスポンスを返すことになります。

クライアント側での機能制御が必要なパターン

サブスクリプションの機能使用前に、クライアント側の導線を塞いで使用を制限する場合がこのパターンに該当します。

例えば、B/43プラスでは「明細に画像を追加」機能を提供しており、B/43プラスを利用していないユーザーに対してはその機能の導線にて制限を設けています。

「明細に画像を追加」の機能制御

この場合、画像追加の導線を表示している明細画面にて、ユーザーが「明細に画像を追加」の機能を使用可能かどうかをサーバー側へ問い合わせ、結果に応じてクライアント側で導線を出し分けて表示することになります。

みなさんならどう設計しますか?

前置きが大変長くなってしまいましたが、このサブスクリプションの機能制御をどのように設計するかというのが本記事でご紹介したい内容です。

「プランごとの使用可能な機能の範囲」と「サブスクリプションを利用可能な範囲」という2つの要件を考慮しつつ、機能の使用可否の判定ロジックをサーバー側で組み、その結果をクライアント側へうまく返せるよう設計する必要があります。

みなさんならどのような設計を考えますか?

我々はこう設計しました

ここからは、実際にB/43プラスにてサブスクリプションの機能制御を実装する上で我々がどのような設計を行なったかについてご紹介します。

テーブル設計

テーブルを設計する上で、サブスクリプションの複数プランを想定してプランごとに使用可能な機能の範囲を表現できるようにする必要があります。

再掲: 仮想サービスのプランごとに使用可能な機能

B/43プラスでは、「サブスクリプションの機能」を表すテーブルを用意し、「機能に必要となるプラン」を紐づけて、マスターデータとして管理するようにしました。

※ 厳密には「機能の使用に必要なプラン」は別テーブルで定義していて1対多の関連を持たせています

これにより、各機能を使用するにあたって必要となるプランがなんであるかを表現できるようにしています。

アプリケーションロジック

アプリケーションロジックを組む上では、サブスクリプションを利用可能な範囲を意識して設計する必要があります。

再掲: B/43プラスを利用可能な範囲

B/43プラスでは、B/43カードの利用者のうち1人でもサブスクリプションに申し込んでいた場合はすべての利用者がサブスクリプションの機能を使用可能となります。

よって、まずはB/43カードを起点に利用者一覧を取得し、各利用者のサブスクリプションの申し込み状況を取得します。

そして、もしサブスクリプションを申し込んでいるB/43カード利用者がいた場合、該当プランで使用可能な機能を「サブスクリプションの機能」テーブルから取得し、機能の使用可否を判定します。

このように、サブスクリプションの機能制御のアプリケーションロジックでは、安易にユーザーのサブスクリプション購読状態のみから機能制御の判定を処理するのではなく、サブスクリプションを利用可能な範囲に応じたロジックを組むことが肝要です。

API設計

クライアント側で導線を塞ぐことによる機能制御を想定して、先ほどご紹介したアプリケーションロジックの結果をAPIから返してあげる必要があります。

再掲: 「明細に画像を追加」の機能制御

サブスクリプションの機能制御のAPIでは、レスポンスとして「サブスクリプションの機能」テーブルの各レコードを返します。 そして、各機能ごとに「機能の使用に必要なプラン」と、「機能を使用可能かどうか」を合わせて返します。

これにより、クライアント側で導線を塞ぐことによる機能制御を実装する上で「この機能を使うためにはどのプランに申し込む必要があるのか」を表現できるようにしています。

クライアント側の状態管理設計

サブスクリプションの機能制御におけるクライアント側での状態管理では、不整合を発生させないことが極めて重要です。

せっかくサブスクリプションに申し込んだのに、目当ての機能が使用できないままとなっていては非常に残念な体験となってしまいます。

B/43では、サブスクリプションの申し込み完了時に機能制御APIのレスポンスをインメモリでキャッシュし、サブスクリプション機能の導線を表示する画面にて変更を監視することで、機能制御の最新状態が常に導線の表示へ反映されるように設計しています。

インメモリキャッシュによる状態管理の設計については、「キャッシュによる状態管理のアーキテクチャ」の資料にて詳しく説明しておりますので、気になる方はそちらもご覧ください。

speakerdeck.com

また、クライアント側で機能制御の状態管理を設計する上では、サブスクリプションを利用可能な範囲を意識することも重要です。

例えばB/43プラスでは、カード単位でサブスクリプションの利用可否が変わります。

マイカードではサブスクリプションの機能を使用できないが、ペアカードではパートナーがサブスクリプションに申し込んでいるから機能を使用できる、というような状態が起こり得るのです。

B/43では、DIコンテナのカスタムスコープを用いてカード単位のライフタイムを持つインスタンスを生成しています。サブスクリプション機能制御の状態を持つインスタンスはカードに紐づくカスタムスコープで管理することで、サブスクリプションの利用可否がカード単位で適切に判定されるように設計しています。

B/43におけるDIコンテナによるカスタムスコープ周りの設計については、nakamuuuさんの「“ユーザー起点” のモバイルアプリの開発プロセス」の資料にて詳しく説明されておりますので、気になる方はそちらもご覧ください。

speakerdeck.com

最後に

本記事における サーバーサイドの設計はuribouさんに担当いただいたもの で、最終的な設計についてもPJメンバーで議論した結果醸成されたものとなります。

Special thanks to: @uribou, @ohbarye, @hirotea, @nakamuuu


スマートバンクでは一緒に B/43 を作り上げていくメンバーを募集しています!カジュアル面談も受け付けていますので、お気軽にご応募ください 🙌 smartbank.co.jp

We create the new normal of easy budgeting, easy banking, and easy living.
In this blog, engineers, product managers, designers, business development, legal, CS, and other members will share their insights.