2024/12/27

自社SaaSで働くということと「設計」の目指すところ

対象読者

  • 自社SaaS以外の業種から自社SaaSを提供する企業に転職する人、転職した人
  • 自社SaaSを提供する企業に就職を考えている人

はじめに

これから自社SaaS企業に入社する方が今後行う業務においては、単に動作するアプリケーションを作るだけでなく、そのアプリケーションを長期的に保守・運用し続けることになります。
リリースした後も頻繁に機能改善やバグ修正、ビジネス要件の追加などが求められるため、コードが長い期間にわたって生き続けることになります。

こうした背景から、近年注目されている設計手法にドメイン駆動設計(DDD)クリーンアーキテクチャなどの考え方があります。

こうした設計手法が注目を集める理由は、単に「きれいなアーキテクチャを組みたいから」という美学的なものにとどまりません。

従来のWEB開発の主流だったMVC全盛の時代のDBテーブル中心の設計とは異なり、ビジネスロジックを中心にアプリケーションを構築することによって変更のスピードや柔軟性が手に入る、すなわちビジネス価値の提供速度を落とさずにアプリケーションを進化させられるという、企業にとっての大きなメリットがあります。

本記事では、アプリケーションレイヤのエンジニアが設計を意識することの重要さを、特に自社SaaSを提供する企業の長期運用の観点から考えてみます。


今回想定しているアプリケーションの形態

この記事でいう「アプリケーション」とは、日本企業でよく見られるような「受託開発」や「SES(システムエンジニアリングサービス)」「派遣」などで扱う、契約上“作成すればビジネスとして完了”、利益が生まれるソフトウェアとは異なります。
納品によって開発が一区切りつく性質のシステム開発では、多くの場合、完成時点でビジネスがゴールに達することになります。

しかし、ここで想定しているのは、ユーザーが継続的に利用し続けるアプリケーションです。SaaSとして提供されるプロダクトがその典型例ですが、他にも自社サービスとして運営され、リリース後も機能追加やUI/UX改善を繰り返しながら収益を得るタイプのアプリケーションをイメージしています。このようなアプリケーションは、

  • リリース後も終わらない: ユーザーが使い続けてくれる限り、改善要望やバグ修正、新機能の開発が継続的に発生する
  • 長寿命が基本: 大規模に集客が成功した場合や、ある程度のユーザー数が定着した場合、数年〜十数年という長期にわたってビジネス運用される
  • 契約完了よりも継続利用が重要: 作って終わりではなく、いかにユーザーの満足度を高めつつ開発コストを抑えて運用するかが企業の収益に直接関わる

という特徴を持っています。こうしたアプリケーションでは、最初のリリース後こそが本当のスタートラインとも言えるでしょう。会社やチームが成長し続けるためにも、長期的な視点で設計、継続投資を行う必要があるのです。


この記事における「設計」とは

ここでは先ほどの「アプリケーション」の定義から、設計という言葉についても整理します。

ソフトウェア業界において、「設計」という単語は幅広い意味を持ちますが、本記事では特に以下の観点で設計を捉えます。

ます、「設計」という言葉からは、ER図やクラス図などを頭に思い浮かべる方も多いと思います。しかし、ここではもう少し広い意味での設計、つまりアプリケーションの構造を整理し、どこに責務を置き、どのように変更に耐えられるようにするかを考える行為を指します。とりわけ、ビジネスロジックが集中するアプリケーション層の設計を意識することが最も重要です。

その上で、本記事で取り扱う設計手法について概要を説明します。

  • ドメイン駆動設計(DDD): ドメイン(ビジネス領域)をよく理解し、エンティティや値オブジェクト、ドメインサービスなどの概念を用いてコードを組み立てることで、ビジネス上の意味を失わないままモデル化を行う手法です。
  • クリーンアーキテクチャ: アプリケーションを複数の層(レイヤ)に分割し、ドメイン層やユースケース層を中心に据えて、インフラ層(フレームワークや外部サービス)への依存を最小限に抑えることで、将来的にフレームワークや外部サービスを切り替えやすくする設計パターンです。

これらの設計手法がもたらす共通の恩恵は、**“ビジネスの変化に合わせて柔軟にコードを進化させられるようになる”**という点に集約されます。SaaSのように継続的な機能追加・変更が必須のサービス開発では、こうした柔軟性がビジネス上の利益にも直結する強みとなります。


DB設計ベースのアーキテクチャが抱える課題

DBに引きずられるドメインモデル

長らくMVCアーキテクチャやActiveRecordを用いたフレームワークが広く用いられてきたことから、データベースのテーブル構造とモデルクラスが1対1に結びついた設計が主流でした。これは一見すると実装がスムーズに進むように見えますが、以下のようなデメリットが顕在化しがちです。

  1. ビジネスロジックとの乖離
    テーブルを正規化していたり、リレーションを貼っていたりすると、ビジネス上の概念としては一つの単位なのにコード上は複数のテーブルやモデルに分散してしまい、開発者同士の認識がズレやすくなります。
  2. 不要な結合度の上昇
    DB主導の設計では、モデルの変更がそのままDBスキーマの変更に直結する場合が多く、アプリケーションレイヤの改修とDBのマイグレーションが分離できなくなることがあります。
  3. テストの難易度
    DBのスキーマとモデルがベタに結合していると、ユニットテストのような小さな単位での検証が難しくなり、結果的にテストが書かれない、もしくは膨大なテスト用DBデータが必要になってしまいます。また、DBへのI/Oのコストも大きくなります。

つまり、作り上げるまでの0 => 1には強いが、1 => 10や10 => 100の段階ではコードの変更が難しくなります。

こういった技術は変更容易性を犠牲にして作り上げるまでのスピードを取得するためのもので、借金のようなものです。こういった選択が技術的負債と呼ばれます。

個人的には世の中で技術的負債と呼ばれるものは多くの場合技術の選択肢が少ない状況での選択であり、積もうと思った負債ではないので、技術的負債という言葉には違和感を感じます。トレードオフを理解した上であとでやる選択肢を選んだ結果が技術的負債であると思っています。

データの寿命とコードの寿命

ビジネスロジックを変更するとき、テーブル構造まで含めて大規模な変更が必要になるケースでは、運用環境に溜まっているデータの移行も伴います。一度蓄積されたデータは企業にとって大切な資産であり、業務フローと密接に結びついているため、容易に“壊して”作り直すわけにはいきません。
一方で、アプリケーションコードは要件に合わせて積極的にリファクタリング・リプレースが行える部分です。**DB主導でコードを書いてしまうと、コード自体まで「変更が難しくなってしまう」**という問題が生じます。
本来DBと比べると変更が容易であるコードの変更容易性をDBと同程度まで変更を難しくしてしまうことにつながります。


ドメイン駆動設計(DDD)やクリーンアーキテクチャがもたらすメリット

近年流行しているドメイン駆動設計(DDD)やクリーンアーキテクチャは、上記のような問題を解決するための設計手法として注目されています。
これらの思想はMVCで作られたアプリケーションの課題の反省から、ビジネスロジックを中心に据え、DBやフレームワークといったインフラ層との依存を最小限に抑えることで、アプリケーションの変更容易性を高めることを目指しています。

将来の変更に対する柔軟性

DDDやクリーンアーキテクチャの思想に沿って設計を行うと、アプリケーションを構成する各要素の責務がはっきり分離されます。具体例としては、ユースケース層(アプリケーション層)ドメイン層を明確に分割する、さらにインフラ層(DBや外部サービスへのアクセス)はあくまでドメイン層やユースケース層から切り離して依存関係を一方向にする、といったアプローチが挙げられます。

ビジネス上の概念(ドメインモデル)がコードに明確に反映されるため、要件の変更が起こった際もドメイン側の修正で済んだり、あるいはユースケース層だけを変更すれば良いなど、局所的な修正で対応できる可能性が高まります。DBスキーマ変更を要さない場合は、速やかに新しいロジックへ移行できるでしょう。

修正が局所的になるということは、テストも局所的に行うことができます。テストというのは対象のスコープが小さければ小さいほど観点の網羅性を高めることができます。

ビジネス上の価値創出への貢献

アプリケーションの設計が良いと、新機能のリリース速度にも大きく寄与します。細かい機能修正や追加実装を行う際に、全体構造を大きく壊す必要がなければ、エンジニアはコアなビジネスロジックの改善に集中できます。

競合他社より早く、ユーザーの要望に応えることができれば、ユーザーの満足度向上につながり、ビジネスの成長にも寄与します。

また、定期的なリファクタリングが可能になるのも大きなメリットです。ビジネスロジックとインフラへのアクセスが密結合していない状態であれば、新しい要件に合わせてコードをスリムにしていくことが比較的容易になります。結果として、アプリケーションそのものの品質が向上し、ユーザーにとっても快適なサービス運用が続けられます。


設計の目指すところ

本記事のタイトルにもある通り、私たちが設計を意識するのは「アプリケーションのリリースから、サービス終了するまでの期間で、リターンに対するコストを最小にする」ためです。SaaS企業であれば、リリース後すぐにユーザーのフィードバックを得て改善を回す必要があり、そのサイクルを素早く回すほど競合他社に対して優位性を得られます。

  • 売れないアプリケーションに過度な設計投資をするリスク
    何事にもタイミングがあり、リリース前の段階で大掛かりなアーキテクチャを組んでも、そのプロダクト自体が収益を生まないまま終わる可能性は否定できません。
  • 設計スキルそのものは使い回しがきく
    一度学んだドメイン駆動設計やクリーンアーキテクチャの知識は、他のプロジェクトや将来のサービス開発でも有効活用できます。自分自身の市場価値向上にも寄与するでしょう。
    実際に一度習得した設計知識を使うこと自体のコストはあまり高くありません。
  • 変更コストを下げ、変更スピードを上げる
    長期運用が前提の場合、単なる仕様変更でも運用コストの差が積み重なり、企業収益に大きく影響を与えます。設計をしっかりしておくことで、その差を最低限に抑えられます。

技術面でのリスクヘッジ

フロントエンドとバックエンドの分離

ReactやVueなどのフロントエンドフレームワークが短い周期で進化を続けている中で、バックエンドが長期的にメンテナンスされるケースが増えています。

とはいえフロントエンドは流行り廃りが激しい、とはよく言いますが、Reactの流行はかなり長く、バックエンドと比べると短いものの、それなりの期間は続いています。

それでも、境界がしっかりしていれば、フロントエンドを別のフレームワークに乗り換えたり、モバイルアプリを追加して同じユースケース層やドメイン層を再利用できるなど、柔軟性が向上します。

SOLID原則を意識した責務分割

SOLID原則(単一責任の原則、オープン/クローズドの原則、リスコフの置換原則、インターフェイス分離の原則、依存関係逆転の原則)は、オブジェクト指向言語でコードを書く際の重要な指針です。これを実践することで、テスト容易性やコードの読みやすさが向上し、結果として「捨てる」範囲を最小限に絞ったリプレースが可能になります。

捨てやすさがもたらすアジリティ

長期運用の中では、どうしても不要になった機能や、時代遅れになった技術スタックが出てきます。

設計が悪いと、不要な機能を切り離すにも大量の依存関係を辿ってコードを修正しなければならず、その作業には大きなコストがかかります。一方、アーキテクチャの境界がはっきりしていれば、**“不要な部分だけサクッと捨てる”**という選択肢が生まれ、素早い意思決定を可能にします。


テストがもたらす安心感

設計の良いアプリケーションほど、テストが書きやすい構造になっています。これは、SOLID原則やクリーンアーキテクチャがドメインロジックとインフラの依存を分離しやすくしているためです。

  • ユニットテスト: ビジネスロジック(ドメイン層)を小さな単位でテストしやすくなる。
  • インテグレーションテスト: ユースケース層とインフラ層の統合をテストしやすくなる。
  • リグレッションテスト: コード変更による既存機能の破壊(デグレ)を早期に検知できる。

SaaS開発では小さい単位の変更が頻発し、短いスプリントを積み重ねるアジャイル開発スタイルを採用することが多いです。テストの自動化と設計の分離が進んでいれば、あるモジュールの変更が他のモジュールに影響を与える可能性を早期に検知でき、リリースまでのスケジュールにも好影響を与えます。


会社員エンジニアとしての設計意識

個人開発や小規模のプロトタイプ開発では、スピード重視の設計が求められ、ドキュメントも最小限となりがちです。実際、サービスが世の中に出るかどうかが不透明な段階で、あまりにも綿密な設計を組むと、「せっかく作り込んだのに誰も使わない」というリスクが高まってしまいます。
しかし、企業でのサービス開発、特にすでにユーザーが存在するSaaSでは状況がまったく異なります。リリースした瞬間からユーザーの声が届き、障害や問題が発生すれば即座に対処を迫られるでしょう。

こうした現場に身を置くエンジニアにとって、コードの可読性・保守性・拡張性は単なる「自己満足」では終わりません。

  • チーム全体で進める開発: 設計指針が共有されていなければ、開発者ごとに実装スタイルがバラバラになり、保守が困難になります。
  • 複数年にわたる運用が前提: 適切なアーキテクチャが組まれていなければ、新人の配属やメンテナンス担当の交代時など、属人化が原因のトラブルが頻発する可能性が高いです。
  • ビジネス要件の迅速な反映: 設計が整っていれば、仕様変更の影響範囲が限定的になり、実装に踏み切りやすくなります。

まとめ

本記事では、アプリケーションレイヤのエンジニアが設計を意識することで得られるメリットを、特に自社SaaSを販売・運用する企業にフォーカスして考察しました。

また、日本で一般的に見られる受託開発やSESなどの「作って終わり」型のシステム開発と違い、ユーザーが使い続けることが前提となるアプリケーションを想定している点を強調しました。

DBベースの設計からアプリケーション層中心の設計へシフトすることで、ビジネスロジックが明確になり、将来的な変更や拡張に強いアプリケーションを作り上げることができます。

  1. ドメイン駆動設計やクリーンアーキテクチャの流行背景
    単なる流行ではなく、長期的な保守運用とビジネス価値を考えたときの必然的な手法。
  2. DB設計とアプリケーション設計の切り離し
    DBはあくまでもデータの永続化手段。ビジネスロジックを表現するためには、アプリケーションレイヤでのモデル化が重要。
  3. 設計の本質的な目的
    アプリケーション開発・運用期間全体で、リターンに対してコストを最小にするための投資であり、売れる・売れないを含めたビジネスリスクをコントロールする手段でもある。
  4. テストしやすさと変更しやすさ
    良い設計はテストを書きやすくし、結果的に変更を恐れない文化を育む。SaaSに求められる高頻度な改善サイクルにマッチする。
  5. ユーザーの継続利用を前提とした考え方
    作って終わりではなく、リリース後からが本番。継続的な保守と運用こそが、企業の収益とユーザー体験に直接繋がる。

これから自社SaaSで働く方やには、まずは小さなプロジェクトでも「どのようにアプリケーションを分割するか」「ドメインをどのように表現するか」など、設計に関する問いを常に意識してみてほしいと思います。 いきなり完璧な設計を目指す必要はありませんが、考え抜かれた構造のメリットを肌で感じ、必要に応じてドキュメントやコードを改善していく姿勢こそが、これからのエンジニアに求められる重要な資質だと考えます。