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

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

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

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の出し分けは、多少の辛さを覚悟しておく(メール大変だった。。。) • 新しいサービスドメインを確立させていくには ◦ クラス設計においては、適宜分けていく • 技術的負債と投資のバランス、負債の返済タイミング