Upgrade to Pro — share decks privately, control downloads, hide ads and more …

スピンオフサービス構築で培われた開発ノウハウをご紹介!

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

 スピンオフサービス構築で培われた開発ノウハウをご紹介!

Avatar for AkitoTsukahara

AkitoTsukahara

March 13, 2023
Tweet

More Decks by AkitoTsukahara

Other Decks in Programming

Transcript

  1. Copyright© M&Aクラウド 7 ざっくりとサービスの紹介 求人広告のように買い手がM&Aニーズを公開することで、売り手自ら買い手を探せる ダイレクトマッチングにより人に依存しないスケーラビリティを実現 買い手 月額無料 成功報酬 ・

    案件報酬はM&A成功報酬のみ ・最低手数料なし ・売り手ソーシングのチャネルが増える ・M&Aニーズを発信するだけで売り手を集客 ・仲介業者を介さずにダイレクトにやり取り可能 ・潜在層にもリーチが可能 手数料無料 売り手 ・買い手のM&Aニーズを自ら調べることが可能 ・仲介業者を介さずにダイレクトにやり取り可能 ・買い手のM&A担当者に直接コンタクトをとれる ・仲介業者を使わないので手数料が無料 買い手のメリット 売り手のメリット ・仲介手数料が無料 〇〇領域の会社を 募集します この会社と一緒に やっていきたい! 1.掲載する 2.オファー M&A・出資ニーズを掲載
  2. Copyright© M&Aクラウド 出資企業 資金調達企業 9 資金調達クラウドのサービスフロー 完全無料で出資企業のマッチング(紹介)ができるプラットフォーム 手数料完全無料 1.掲載する 3.資金調達依頼

    M&A・出資ニーズを掲載 2.発信する 〇〇領域の会社に 出資したい! この会社から 資金調達を受けたい 【メリット】 出資ニーズを発信するだけで、資 金調達ユーザーから連絡が来る 【メリット】 出資企業の出資ニーズを見ること で、適切なマッチングが可能
  3. Copyright© M&Aクラウド リリースまでの大まかな流れ • 開発スケジュール ◦ PdMとビジネスサイドのすり合わせは3ヶ月程度 ◦ 開発は3ヶ月(7月〜10月末) ◦

    リリースは11月1日(必達で!) • スコープ ◦ 新規作成は新プラットフォームの3ページ ▪ リリースに間に合うように調整可能 ◦ 既存プラットフォームと共存できるように機能拡張 ▪ 同じアカウントで資金調達とM&Aの両プラットフォームを利用したい
  4. Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jpOR

    macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
  5. Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jpOR

    macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
  6. Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 新しいサービスを「サブドメイン」と「パス」のどちらでリリースするか問題 ◦ サービスの関連性 ◦ ユーザーの認識性 ◦

    SEOの影響 この判断はエンジニアチームではなく、経営サイドの判断が必要になる 将来的にプラットフォームをどのように拡大させていくのか、事業構想に直結する
  7. Copyright© M&Aクラウド • 後回しにできない仕様決定である ◦ サブドメインなら ▪ サブドメインによるログインセッション管理 • 同じアカウントでPFを行き来するため

    ▪ 既存フロントフレームワークへのページ追加だと対応が複雑に(Nuxt.js) • できなくはないが、基本仕様から離れた実装になる • 新しくフロントエンド環境を用意することも検討 ◦ 新しいデプロイフローが必要になる 弊社は「サブドメイン」にする決定をしたので、サブドメイン採用時の対応内容をまとめていきます! (課題・なぜ)サイト構成
  8. Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 既存フロントフレームワークへのページ追加だと対応が複雑に(Nuxt.js) • もしも、どちらのサービスにも同じパスが必要になった場合 ◦ macloud.jp/offers ◦

    finance.macloud.jp/offers • pages配下にoffersディレクトリは1つしか置けないため、実装できない... → /about →/ Nuxt.jsでは/pagesフォルダ構 成によってルーティングが決 まります。
  9. Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 既存フロントフレームワークへのページ追加だと対応が複雑に(Nuxt.js) ◦ サブドメインの場合 ▪ 基本のルーティング仕様から離れた実装が必要になる ▪

    ディレクトリを分けて、モジュールでルーティング機能を拡張する • nuxt-router-module で実装できそうな見込み ◦ パスの場合 ▪ /AAA/mypage, /BBB/mypageとパスを分けるだけで対応できる
  10. Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 別の課題としては、 ◦ ビルドが遅い ◦ 一方のチームとコンフリクトする確率が高い ◦

    FeatureFlagの切り替えが増えるほど、if分岐が増えて実装が面倒になる ▪ コードの可読性が下がる ▪ リリース後にコードを削除する手間が増える
  11. Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jp

    OR macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
  12. Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる • 新しいログインステータス ◦ usersテーブルに資金調達ユーザーのフラグ(isFunding)を追加 ▪ 資金調達クラウド経由で登録・変更するとフラグがONに ▪

    既存の調達ユーザーにもフラグを付与する ◦ 売り手サービスドメインのエンティティに値オブジェクト(isFunding)を追加することで、 ログイン中の売り手が調達ユーザーかどうか識別できるように
  13. Copyright© M&Aクラウド (課題・なぜ)同じアカウントでどちらかのサービスを利用できる • 文言の出し分け ◦ ログインユーザーのステータスに合わせて表示を切り替える ▪ サイトのヘッダー・フッター ▪

    登録情報項目 ▪ メッセージやメールの内容 ◦ ページ ▪ (back)middlewareで出し分けするための変数を設定 ▪ (front)データをフェッチしてページ内で文言の出し分け ◦ メール ▪ Mailableを拡張してユーザー毎に出し分け
  14. Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる /** * @var array|string[] * @description ユーザーの資金調達フラグに応じて、資金調達クラウドとして振る舞いたいページを指定する指定はRouteName

    */ protected array $routeNameCheckedByUser = ['AAAApage','BBBBpage']; /** * @param Request $request */ public function handle($request, ¥Closure $next) { if ($this->isIncludeRouteNameCheckedByUser($request)) { $user = $this->authUserHelper->getUser(); if (!is_null($user)) { $this->viewFactory->share( 'serviceAttribute', new ServiceAttribute($user->isFunding()->rawValue()) ); return $next($request); } } } App/Http/Middleware/SetServiceAttribute.php 一部抜粋した実装イメージ
  15. Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる class ServiceAttribute { public function __construct(private readonly

    bool $isFunding) { } public function isFunding(): bool { return $this->isFunding; } public function getName(): string { return $this->isFunding ? '資金調達クラウド' : 'M&Aクラウド'; } } App/DataTransferObjectServiceAttribute.php 一部抜粋した実装イメージ
  16. Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる • メールの文言の出し分け(サービス毎に情報を出し分けする設計) SellerMailable BaseSellerMailable SellingTargetComplete CreationToSeller Mailable

    SellerImporta ntMailable SellerMagazin eMailable Laravel 売り手向けメールの 抽象クラス 売り手向けメールの送信 元を定義した 抽象クラス 売り手ユーザーが案件登録し た時に送信するメールのサブ クラス
  17. Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる abstract class BaseSellerMailable extends BaseMailable { public

    function __construct( public ServiceAttribute $serviceAttribute, ) { } public function serviceNamePrefixSubject(string $title): static { return $this->subject("【 {$this->serviceAttribute->getName()}】 {$title}"); } public function serviceNamePostfixSubject(string $title): static { return $this->subject("{$title}【 {$this->serviceAttribute->getName()}】 "); } } BaseSellerMailable.php 一部抜粋した実装イメージ 出力イメージ 【M&Aクラウド】(メールタイトル) 【資金調達クラウド】(メールタイトル)
  18. Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる abstract class SellerMailable extends BaseSellerMailable { public

    function __construct( public ServiceAttribute $serviceAttribute, ) { parent::__construct($serviceAttribute); if ($this->serviceAttribute->isFunding()) { $this->from( config('mail.finance.address'), config('mail.finance.name'), ); } else { $this->from( config('mail.from.address'), config('mail.from.name'), ); } } } SellerMailable.php サービスに合わせてメールの ドメインを変更する 一部抜粋した実装イメージ
  19. Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる class SellingTargetCompleteCreationToSeller extends SellerMailable { public function

    __construct( public AbstractSellingTarget $sellingTarget, public Seller $seller ) { parent::__construct(new ServiceAttribute($seller->getIsFunding()->rawValue())); } public function build(): SellerMailable { $title = $this->serviceAttribute->isFunding() ? '調達情報の入力が完了しました。' : '売却情報の入力が完了し ました。'; return $this ->serviceNamePrefixSubject($title) ->to($this->seller->getEmail()->rawValue()) ->markdown('emails.selling_target.complete_creation.to_seller'); } } SellingTargetCompleteCreationToSeller.php 一部抜粋した実装イメージ メールタイトル、宛先、メー ルテンプレートを用いて生成 する
  20. Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jp

    OR macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
  21. Copyright© M&Aクラウド • 技術的に負債について ◦ 財務的に利息と元本が投資の利回りよりも低ければ、負債はポジティブ ◦ ソフトウェアでも同じことが当てはまるはず 開発における課題と解決策 最初に市場へ出るために内部品質を犠牲にしたとしても、より良い内部品質で後から市場に出た

    場合よりも、この決定によって得た金額が高ければ、利益を生み出します。 しかし、ある程度不確かなことがあるため、そのような利益を予め見積もるのは難しいので、こ こにはリスクがあると言えます。 引用:InfoQ(技術的負債を管理する)
  22. Copyright© M&Aクラウド まとめ • 「サブドメイン」か?「パス」か? ◦ 両方に対してのメリット・デメリットを用意する • 同じアカウントでPFを行き来できるようにする ◦

    「サブドメイン」か「パス」かで難易度が変わってくる ◦ 「サブドメイン」は対応できるのか、できるとしてどれくらいかかるのか調査 ◦ 既存Viewの出し分けは、多少の辛さを覚悟しておく(メール大変だった。。。) • 新しいサービスドメインを確立させていくには ◦ クラス設計においては、適宜分けていく • 技術的負債と投資のバランス、負債の返済タイミング