Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
スピンオフサービス構築で培われた開発ノウハウをご紹介!
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
AkitoTsukahara
March 13, 2023
Programming
210
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
スピンオフサービス構築で培われた開発ノウハウをご紹介!
AkitoTsukahara
March 13, 2023
More Decks by AkitoTsukahara
See All by AkitoTsukahara
『自分のデータだけ見せたい!』を叶える──Laravel × Casbin で複雑権限をスッキリ解きほぐす 25 分
akitotsukahara
2
1.2k
PHP8.2にバージョンアップして もっと型表現を豊かにしよう
akitotsukahara
0
500
オンボーディングのために 私はプロダクト考古学者になりました!
akitotsukahara
3
520
プロダクトチームから他部署に 伝播するふりかえり文化
akitotsukahara
0
560
ビルドツールViteを10分で解説!
akitotsukahara
0
1.3k
今日からSvelteで開発だ! どうする?何から始める?
akitotsukahara
0
340
どのくらい速くなるの?Laravel MixとViteを性能比較してみました!
akitotsukahara
0
11k
スクラムマスターを経験して得られた学びとエンジニアとしての成長
akitotsukahara
0
490
チームでカレーを作ろう!アジャイルカレークッキング
akitotsukahara
1
2.7k
Other Decks in Programming
See All in Programming
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
1
180
自作OSでスライド発表する
uyuki234
1
3.8k
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
1
260
20260623_Loop Engineeringで自分の分身の問い合わせBotを作る
ryugen04
0
220
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
330
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
2.7k
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
140
これからAgentCoreを触る方へトレンドはGatewayです
har1101
6
490
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
360
フィードバックで育てるAI開発
kotaminato
1
120
作るコストが小さくなった時代 幸せに働くために改めて考えたいこと 〜エンジニアとして価値を出し続けるために注視している二分野〜
yuppeeng
0
100
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
520
Featured
See All Featured
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
350
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
260
GitHub's CSS Performance
jonrohan
1033
470k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.4k
Fireside Chat
paigeccino
42
4k
Unsuck your backbone
ammeep
672
58k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
870
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
63
55k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.3k
Transcript
Copyright© M&Aクラウド スピンオフサービス構築で 培われた開発ノウハウをご紹介! PHPerKaigi2023 リジェクトカンファレンス Akito.Tsukahara
Copyright© M&Aクラウド 2 自己紹介 塚原彰仁 AkitoTsukahara 株式会社M&Aクラウド AkitoTsukahara akito_tsukahara
Copyright© M&Aクラウド 昨年2022年11月に 「資金調達クラウド」を リリースしました🎉 3
Copyright© M&Aクラウド スピンオフサービス構築で 培われた開発ノウハウを お伝えします! 4
Copyright© M&Aクラウド この発表で聞けることは? 今日話すこと • スピンオフサービス開発で直面した課題と解決策 ◦ 「サブドメイン」か?「パス」か?後回しにできない仕様決定 ◦ 同じアカウントでPFを行き来できるようにする
◦ 新しいサービスドメインを確立させていくには 今日話さないこと • プロジェクトマネジメントに関するノウハウ
Copyright© M&Aクラウド ざっくりとサービスの紹介 • M&Aクラウド ◦ M&Aクラウドは会社・事業を売却したい売り手と会社・事業を買収したい買い手のマッチン グプラットフォーム ◦ 資金調達することもでき、事業会社からの調達が可能
Copyright© M&Aクラウド 7 ざっくりとサービスの紹介 求人広告のように買い手がM&Aニーズを公開することで、売り手自ら買い手を探せる ダイレクトマッチングにより人に依存しないスケーラビリティを実現 買い手 月額無料 成功報酬 ・
案件報酬はM&A成功報酬のみ ・最低手数料なし ・売り手ソーシングのチャネルが増える ・M&Aニーズを発信するだけで売り手を集客 ・仲介業者を介さずにダイレクトにやり取り可能 ・潜在層にもリーチが可能 手数料無料 売り手 ・買い手のM&Aニーズを自ら調べることが可能 ・仲介業者を介さずにダイレクトにやり取り可能 ・買い手のM&A担当者に直接コンタクトをとれる ・仲介業者を使わないので手数料が無料 買い手のメリット 売り手のメリット ・仲介手数料が無料 〇〇領域の会社を 募集します この会社と一緒に やっていきたい! 1.掲載する 2.オファー M&A・出資ニーズを掲載
Copyright© M&Aクラウド 新サービス「資金調達クラウド」 • 資金調達クラウド ◦ 資金調達目的で登録してくださるユーザーが増加傾向にある ◦ M&Aクラウドで資金調達ができることの知名度が低い ▪
資金調達ユーザー向けのプラットフォームを開発しよう
Copyright© M&Aクラウド 出資企業 資金調達企業 9 資金調達クラウドのサービスフロー 完全無料で出資企業のマッチング(紹介)ができるプラットフォーム 手数料完全無料 1.掲載する 3.資金調達依頼
M&A・出資ニーズを掲載 2.発信する 〇〇領域の会社に 出資したい! この会社から 資金調達を受けたい 【メリット】 出資ニーズを発信するだけで、資 金調達ユーザーから連絡が来る 【メリット】 出資企業の出資ニーズを見ること で、適切なマッチングが可能
Copyright© M&Aクラウド リリースまでの大まかな流れ • 開発スケジュール ◦ PdMとビジネスサイドのすり合わせは3ヶ月程度 ◦ 開発は3ヶ月(7月〜10月末) ◦
リリースは11月1日(必達で!) • スコープ ◦ 新規作成は新プラットフォームの3ページ ▪ リリースに間に合うように調整可能 ◦ 既存プラットフォームと共存できるように機能拡張 ▪ 同じアカウントで資金調達とM&Aの両プラットフォームを利用したい
Copyright© M&Aクラウド リリースまでの大まかな流れ
Copyright© M&Aクラウド 開発における課題と解決策 12
Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jpOR
macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jpOR
macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 新しいサービスを「サブドメイン」と「パス」のどちらでリリースするか問題 ◦ サービスの関連性 ◦ ユーザーの認識性 ◦
SEOの影響 この判断はエンジニアチームではなく、経営サイドの判断が必要になる 将来的にプラットフォームをどのように拡大させていくのか、事業構想に直結する
Copyright© M&Aクラウド • 後回しにできない仕様決定である ◦ サブドメインなら ▪ サブドメインによるログインセッション管理 • 同じアカウントでPFを行き来するため
▪ 既存フロントフレームワークへのページ追加だと対応が複雑に(Nuxt.js) • できなくはないが、基本仕様から離れた実装になる • 新しくフロントエンド環境を用意することも検討 ◦ 新しいデプロイフローが必要になる 弊社は「サブドメイン」にする決定をしたので、サブドメイン採用時の対応内容をまとめていきます! (課題・なぜ)サイト構成
Copyright© M&Aクラウド (課題・解決策)サイト構成 サブドメインによるログインセッション管理方法(Laravel) 値をしてしないとnullになるが、 とすることでサブドメインのセッション共通化が行えるようになる 'domain' => env('SESSION_DOMAIN', null),
config/session.php APP_NAME=macloud.jp #一緒に変更する必要あり SESSION_DOMAIN=.macloud.jp .env
Copyright© M&Aクラウド (課題・解決策)サイト構成 この対応でハマったポイント すでにログイン中のユーザーは古いドメイン(サブドメインじゃない)のCookieを保持しているため、 ログインセッションが狂ってしまう。(Cookie名の重複) そのためCookie名を変更する必要がある。その際にログイン中のユーザーは強制ログアウトされてしま うので注意! 'cookie' =>
env('SESSION_COOKIE', str_slug(env('APP_NAME', 'laravel'), '_').'_session'), config/session.php APP_NAME=macloud.jp .env
Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 既存フロントフレームワークへのページ追加だと対応が複雑に(Nuxt.js) • もしも、どちらのサービスにも同じパスが必要になった場合 ◦ macloud.jp/offers ◦
finance.macloud.jp/offers • pages配下にoffersディレクトリは1つしか置けないため、実装できない... → /about →/ Nuxt.jsでは/pagesフォルダ構 成によってルーティングが決 まります。
Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 既存フロントフレームワークへのページ追加だと対応が複雑に(Nuxt.js) ◦ サブドメインの場合 ▪ 基本のルーティング仕様から離れた実装が必要になる ▪
ディレクトリを分けて、モジュールでルーティング機能を拡張する • nuxt-router-module で実装できそうな見込み ◦ パスの場合 ▪ /AAA/mypage, /BBB/mypageとパスを分けるだけで対応できる
Copyright© M&Aクラウド (課題・なぜ)サイト構成 • 別の課題としては、 ◦ ビルドが遅い ◦ 一方のチームとコンフリクトする確率が高い ◦
FeatureFlagの切り替えが増えるほど、if分岐が増えて実装が面倒になる ▪ コードの可読性が下がる ▪ リリース後にコードを削除する手間が増える
Copyright© M&Aクラウド (課題・解決策)サイト構成 • せっかくならフロントフレームワークを新しく用意しよう! ◦ SSRできること ◦ 素早くキャッチアップできること ◦
将来性のあるもの(?) →大事なのは、チームにあったものフレームワークを選択する
Copyright© M&Aクラウド (課題・解決策)サイト構成 詳しくはこちら!
Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jp
OR macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
Copyright© M&Aクラウド (課題・なぜ)同じアカウントでどちらかのサービスを利用できる • 売却ユーザーは「M&Aクラウド」、調達ユーザーは「資金調達クラウド」 ◦ 売却⇆調達で目的が変わっても同じアカウントで実施したい ◦ 調達して、事業を拡大し、最後にM&AでExitできるようにサポートしたい ◦
ユーザーがどちらのPFを利用しているのか意識することなく、サービスを利用できる ようにしたい • 実現させるには ◦ 新しいログインステータス ◦ 文言の出し分け
Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる • 新しいログインステータス ◦ usersテーブルに資金調達ユーザーのフラグ(isFunding)を追加 ▪ 資金調達クラウド経由で登録・変更するとフラグがONに ▪
既存の調達ユーザーにもフラグを付与する ◦ 売り手サービスドメインのエンティティに値オブジェクト(isFunding)を追加することで、 ログイン中の売り手が調達ユーザーかどうか識別できるように
Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる • 新しいログインステータス M&Aクラウド ユーザー 資金調達クラウド ユーザー isFunding
ログイン true false
Copyright© M&Aクラウド (課題・なぜ)同じアカウントでどちらかのサービスを利用できる • 文言の出し分け ◦ ログインユーザーのステータスに合わせて表示を切り替える ▪ サイトのヘッダー・フッター ▪
登録情報項目 ▪ メッセージやメールの内容 ◦ ページ ▪ (back)middlewareで出し分けするための変数を設定 ▪ (front)データをフェッチしてページ内で文言の出し分け ◦ メール ▪ Mailableを拡張してユーザー毎に出し分け
Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる • 文言の出し分け
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 一部抜粋した実装イメージ
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 一部抜粋した実装イメージ
Copyright© M&Aクラウド (課題・なぜ)同じアカウントでどちらかのサービスを利用できる • メールの文言の出し分け
Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる • メールの文言の出し分け(サービス毎に情報を出し分けする設計) SellerMailable BaseSellerMailable SellingTargetComplete CreationToSeller Mailable
SellerImporta ntMailable SellerMagazin eMailable Laravel 売り手向けメールの 抽象クラス 売り手向けメールの送信 元を定義した 抽象クラス 売り手ユーザーが案件登録し た時に送信するメールのサブ クラス
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クラウド】(メールタイトル) 【資金調達クラウド】(メールタイトル)
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 サービスに合わせてメールの ドメインを変更する 一部抜粋した実装イメージ
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 一部抜粋した実装イメージ メールタイトル、宛先、メー ルテンプレートを用いて生成 する
Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる • メールの文言の出し分け
Copyright© M&Aクラウド (課題・解決策)同じアカウントでどちらかのサービスを利用できる この対応でハマったポイント(未来形) • 技術的負債になっていく ◦ 案件を複数化する機能ニーズが高まってきたタイミングで、 負債解消としてリファクタリングが必要になる ▪
パーミッションのような扱いにしてもよかった • パーミッション毎にページを用意する ▪ ログイン基盤の作成 売り手情報にisFunding を持たせている
Copyright© M&Aクラウド • サイト構成 ◦ 「サブドメイン」と「パス」どっちで新サービスを用意するのか ▪ この選択で開発作業が大きく変化する ▪ finance.macloud.jp
OR macloud.jp/finance • 同じアカウントでどちらのサービスも利用できる ◦ M&A目的でも後から資金調達に切り替えられるように(その逆も) • 新しいサービスドメインを確立させていく ◦ 既存サービスドメインと中途半端に混ざらないように 開発における課題
Copyright© M&Aクラウド (課題・なぜ)新しいサービスドメインを確立させていく • サービス毎の情報差分を分けてそれぞれサービスドメインで表現する ◦ 共通部分は継承しつつ、新しい情報は新規サービスドメインで表現 ▪ 出資に関する募集情報を参考に
Copyright© M&Aクラウド (課題・なぜ)新しいサービスドメインを確立させていく • 共通部分は継承しつつ、新しい情報は新規サービスドメインで表現 ◦ サービスを分けることでサービスドメインの重要な情報が変わる ◦ 既存のサービスドメインで対応するとファットクラスになってしまう ▪
2つのサービスで利用するデータを全部持っているクラスが誕生する ◦ 一方のサービスで機能改修時に思わぬ事故が発生したりもする ▪ 不具合を発生させないような設計にしたい
Copyright© M&Aクラウド (課題・なぜ)新しいサービスドメインを確立させていく
Copyright© M&Aクラウド (課題・なぜ)新しいサービスドメインを確立させていく • 共通部分は継承しつつ、新しい情報は新規サービスドメインで表現 Offer 募集情報クラス
Copyright© M&Aクラウド (課題・なぜ)新しいサービスドメインを確立させていく • 共通部分は継承しつつ、新しい情報は新規サービスドメインで表現 BaseOffer 抽象募集クラス AcquisitionOffer InvestmentOffer 買収募集クラス
出資募集クラス
Copyright© M&Aクラウド (課題・なぜ)新しいサービスドメインを確立させていく • 影響範囲があまりも広かったため、一時的に Offer 募集クラス InvestmentOffer 出資募集クラス
Copyright© M&Aクラウド (課題・なぜ)新しいサービスドメインを確立させていく • 影響範囲があまりも広かったため、一時的に ◦ これも技術的負債をいつ返すのかというお話し ▪ 1. 作ったらすぐに返済する
▪ 2. 次の改修前に返済する • 普段の業務効率を著しく悪くするなら1のパターン • そうでなければ2のパターン
Copyright© M&Aクラウド • 技術的に負債について ◦ 財務的に利息と元本が投資の利回りよりも低ければ、負債はポジティブ ◦ ソフトウェアでも同じことが当てはまるはず 開発における課題と解決策 最初に市場へ出るために内部品質を犠牲にしたとしても、より良い内部品質で後から市場に出た
場合よりも、この決定によって得た金額が高ければ、利益を生み出します。 しかし、ある程度不確かなことがあるため、そのような利益を予め見積もるのは難しいので、こ こにはリスクがあると言えます。 引用:InfoQ(技術的負債を管理する)
Copyright© M&Aクラウド 本日のおさらい 48
Copyright© M&Aクラウド まとめ • 「サブドメイン」か?「パス」か? ◦ 両方に対してのメリット・デメリットを用意する • 同じアカウントでPFを行き来できるようにする ◦
「サブドメイン」か「パス」かで難易度が変わってくる ◦ 「サブドメイン」は対応できるのか、できるとしてどれくらいかかるのか調査 ◦ 既存Viewの出し分けは、多少の辛さを覚悟しておく(メール大変だった。。。) • 新しいサービスドメインを確立させていくには ◦ クラス設計においては、適宜分けていく • 技術的負債と投資のバランス、負債の返済タイミング
Copyright© M&Aクラウド 参考資料 • https://tech.macloud.jp/entry/2022/08/30/122131 • https://ymmooot.dev/articles/3/ • https://www.infoq.com/jp/articles/managing-technical-debt/
Copyright© M&Aクラウド ありがとうございました! 51