1. webのマイクロフレームワーク採用と設計の課題
最近は、10年前とは異なり、フロントはJavascript/Typescriptで開発して、サーバサイドはAPIに特化することが増えてきました。
画面(ビュー)を作らないので、PythonのFlask、PHPのSlimなど有名なマイクロフレームワークでも十分対応できると思います。
特に、Flask、Slimのルーティング処理は、GoやRustの有名なWebフレームワークでも同じような設計がされています。
(METHODに応じて、関数を割り当てていくスタイル)
では、マイクロフレームワークでAPIを作ってみようとすると、「アーキテクチャ(構造)設計」という問題が出てきます。
RailsやLaravelのようなフルスタックは、MVCを含め、ある程度アーキテクチャは設計されていて、そこに従ってモジュールを配置していきます。
ただ、マイクロフレームワークはそのあたりの縛りがないので、よく言えば「自由に」、悪く言えば「無秩序に」モジュールを配置できます。
ある程度、設計に慣れている人ならフルスタックフレームワークに則ったり、プロジェクトに合わせた設計ができるかもしれないですが、なれていないと色々悩みがあります。
悩むぐらいならフルスタックでいいのではという意見も意味があると思います。
とはいえ、マイクロフレームワークで設計する簡単な指針をメモ程度に記載します。
2. 有名な手法を踏襲しつつ、無駄を省く
設計をするときプログラマーが直感的に読めるものが望ましいと思います。
直感的といっても、ある程度、「専門家」であることを前提としていますので、プログラマーとしての「知見」を期待したものでよいと思います。
MVC、ドメイン駆動、コンポーネント指向、RESTful、テスト駆動、アスペクト指向、DI(依存性注入)、クリーンアーキテクチャ、などなどそれらの要素を踏まえつつ、それでいながら、マイクロフレームワークなのでできるだけライトにモジュールのレイアウトをしたいと思います。
3. 階層を分ける
モジュールの階層(ディレクトリ・パッケージ)を以下の4つに分けます。その際に、プログラマー視点(内部設計)とユーザー視点(外部設計)を意識するのがよいと思います。
(1) 汎用ライブラリ
プロジェクトに特化しない、プログラム一般における便利ツール。文字列、日付、配列の操作など。
プロジェクトをまたいで利用できるぐらいの粒度で作成する。
(2) ミドルウェア
ユーザー視点ではなく、プログラマー視点でプロジェクトに特化した汎用ライブラリを組み合わせたモジュールを配置。
たとえば、認証処理、ファイルやDB周りでプロジェクトでよく行う処理。
プロジェクト固有の設定情報などを絡めてもよい。
(3) ドメイン
ユーザー視点でパッケージ分けをしていく。
RESTfulの視点であれば、テーブル名と同じようなユーザーが分かる名称でパッケージ名を付けていく。
マスタ情報やプロジェクト固有の定義情報などもここに配置。
Railsでいえば、Modelの情報がここに配置される。
(4) UI(ユーザーインターフェース):実行起点
ここは、ユーザーが利用するインターフェースに応じてパッケージを分けるといいと思います。
たとえば、API、CLIなど。
Controller的な振る舞いをします。入力を受けて、ドメインの処理を呼び出す。
ここに具体的な処理実装は記載しません、ドメインの処理を呼び出すだけ。
4. パッケージ、ソースファイルを細かく分ける
パッケージ名は処理対象・関心事にする
よく「FatClass」、クラスの肥大化ということがいわれ、一つのソースにいろいろな処理を詰め込み、可読性の低下、機能の共通化の阻害、修正の困難化を招くことがあります。
また、「-Utils」、「-Helpers」などと一つのソース・クラスに処理を詰め込み、上記の問題を引き起こすことがあります。
まず、オブジェクト指向に従い、処理する対象や関心・テーマでパッケージから順番に細かく分けていくのがよいと思います。
たとえば、汎用ライブラリに配置する「文字列」の処理であれば、「StringUtils」というクラスファイルをつくるのではなく、「string」というパッケージ名をつくる。
そして、各処理ごとにクラス名を分けた方が読みやすくなります。
util -
|
- string
|
- splitter.xx
- checker.xx
- editor.xx
汎用ライブラリのパッケージ分けは、言語の標準ライブラリを参考にして分ければいいと思います。
ドメインやUIでは処理対象・関心事はユーザー視点のものを上位に置く
処理対象・関心事をパッケージ名にするにしても、立場・視点によってその上下の位置が変わります。
汎用ライブラリやミドルウェアでは、プログラマー視点の関心事を上位に持ってきます。
一方、ドメインやUIにおいては、ユーザーの関心事を上位に持ってきます。
# 汎用・ミドル
db - selector.xx
# ドメイン・UI
product - selector.xx
product - db - selector.xx
- csv - selector.xx
さいごに
以上、マイクロフレームワークを使う際の簡単なアーキテクチャ、モジュールわけです。
その他色々技巧的なことをしたいのであれば、素直にフルスタックのフレームワークを使えばよい気がします。
とはいえ、ある程度のモジュール分けをしておかないと、処理の共通化、修正が大変になってきます。
その参考になればと思います。
備考:内部設計と外部設計
プログラムをしていると内部設計(詳細設計)と外部設計(基本設計)をすると思います。
内部設計はプログラマー視点の設計。
外部設計はユーザー視点の設計。
本投稿で扱ったドメインやUI部分は外部設計に即して設計することになると思います。
そして、外部設計はプロジェクト固有なもののため省くこともできません。
外部設計はとても大切な過程になります。
一方、内部設計は広範囲で多岐にわたったり、OSSなど外部のライブラリを使うことになります。
外部のライブラリを使うとすれば、ここはある程度省くことができます。外部ライブラリのリファレンスが設計書の一部になるでしょう。
設計作業を行う上で大切なのは、外部設計で、内部設計はできるだけ外部のライブラリをつかったり、汎用的にしてドキュメントもプロジェクトで共有するのがよいと思います。