フロントエンドシステムにおけるデータ永続化のためのクラス・ディレクトリ構成を考える
MVC アーキテクチャ
古くは Struts からあるような、サーバサイドも含めた MVC アーキテクチャのシステムの場合、大抵は DB アクセスを行う DAO クラスが存在し、それ向けの構成が大体決まっている。
- View
- 一番表は HTML。
form
要素が Form クラスと対応づいていたりする。
- 一番表は HTML。
- Controller
- Action クラスと呼んだり。
- Form クラスの値を、ビジネスロジッククラスが扱う DTO (Data Transfer Object) クラスに移し替えたり。
- Model
- ビジネスロジッククラス。サービスクラスと呼んだりも。
- DTO の内容を、DB のテーブル定義と対応づいている Entity クラスに移し替えたりする。
- DAO (Data Access Object) クラスが Entity クラスを受け取り、DB アクセスに使ったりする。
もしくは、Rails のような場合は、ActiveRecord というアプローチで、Model に相当するクラスが最初から DB のテーブル定義と対になっていて、Model クラス自身が「DTO / Entity 兼 DAO」な作りになっていたりする。
データ永続化のアプローチにはこんなやり方が一般的だ。
- 参考 : Data Access Object - Wikipedia
- 参考 : ビジネスオブジェクト - Wikipedia
- 参考 : Data Transfer Object - Wikipedia
-
Data Transfer Object とビジネスオブジェクトや Data Access Object との違いは、DTO が自身のデータの格納と取り出し機能(アクセサメソッドとミューテータメソッド)しか持たない点である。
-
- 参考 : Active Record - Wikipedia
MVC のディレクトリ構成
MVC デザインパターンのプロジェクトのディレクトリ構成は、以下の2種類に大別できるであろう。
1. 種類別
Model
・View
・Controller
という種類のディレクトリを切り、その下にクラスが連なる作り。大規模なシステムをこのやり方で作ると、ディレクトリの往来が大変になる。
MyProject
┣models
┃┣HogeModel
┃┗FugaModel
┣views
┃┣HogeView
┃┗FugaView
┗controllers
┣HogeController
┗FugaController
2. 機能別
まず機能ごと (hoge
・fuga
) にディレクトリを分け、その中で Model
・View
・Controller
といった種類を分ける。このやり方だと、特定の機能を切り出したりする時にディレクトリごと移動・削除するだけで対応できて分かりやすい。
MyProject
┣hoge
┃┣models
┃┃┗HogeModel
┃┣views
┃┃┗HogeView
┃┗controllers
┃ ┗HogeController
┗fuga
┣models
┃┗FugaModel
┣views
┃┗FugaView
┗controllers
┗FugaController
最近は後者の機能別の構成が多いかな?
- 参考 : javascript - Web project's folders/directories structure - Best practices - Stack Overflow
- 参考 : angular-styleguide/ja-JP.md at master · johnpapa/angular-styleguide · GitHub
フロントエンドシステムにおけるデータ永続化
さて、本題に近付いてきた。
バックエンドシステムを含まない、フロントエンドオンリーのシステムにおいても、フロントエンドの中でデータ保持が必要な場合は存在する。SessionStorage や LocalStorage の他、SQLite を利用してローカル DB を持つ場合などがあり得る。
こんなシステムにおいて、どのようなクラス分けを行い、どのようなディレクトリ構成でクラスを管理すると、データ永続化が綺麗にできるだろうか、というのが今回の課題。
いくつか調べてみた感じだと、React.js や Angular のようなライブラリ・フレームワークだと、それ単体で構成するクラスの種類別にディレクトリを作る話しか出てこない。
- 参考 : React-Reduxを使った開発でのディレクトリ構成をどうしたらいいのか的なことから、こうやって組んだらいいんじゃないか的なお話 ~ 適当な感じでプログラミングとか!
- 参考 : Angular Folder Structure – Tom Cowley – Medium
これはつまり、データ永続化が必要なパターンが少なく、JavaScript なので型を意識することも少ないので、コンポーネント内に適当に混ぜ込んでおいてなんとかなる、ということなのだろうか。
TypeScript を使う Angular の場合は型に対するアプローチはどうなるだろう、とか、Cordova で作るハイブリッドアプリの場合は永続化が必要だよな、とか、色々気になるので、もう少し調べてみた。
- GitHub - smithad15/angular2-folder-structure-example: File and Folder Structure Example for an Angular 2 App with Redux
- Angular2 系のディレクトリ構成のサンプル。
- そうそう、機能のディレクトリは複数形 (families)、ページコンポーネントは単数形 (family-list・family-details)。
app/families/shared/types/
で DTO 的なインターフェースの定義をしている。- ユーザ登録は
registration
と表現している。
- Angular Docs
- Angular4 公式のスタイルガイド。イマイチデータ永続化に関する資料なし。DTO チックな
hero
は居る。
- Angular4 公式のスタイルガイド。イマイチデータ永続化に関する資料なし。DTO チックな
- ecmascript 6 - DTO Design in TypeScript/Angular2 - Stack Overflow
- Angular アプリにおける DTO のデザインに関する話。
private
プロパティを除いた DTO オブジェクトを返す方法としてデコレータを使ったサンプルなどがある。 - そもそも Angular アプリに DTO クラスが出て来ること自体は不自然ではない様子。
- Angular アプリにおける DTO のデザインに関する話。
- ionic 2 | Tech Blog
- Ionic-Native の少し古いバージョンを使った、Angular 内にローカル DB サービスを作るサンプル。
- DB 接続から User 情報の Insert や Select を行う1つの DatabaseProvider クラスが出てくるだけ。User 以外の情報を扱う時もこのクラスが膨れていくだけなのだろうか…?
- メソッド名は
openDatabase
・createUserTable
・insertIntoUser
・fetchFromUser
・dropDatabase
。SELECT
ではなくFetch
なのね。
- Use SQLite In Ionic 2 Instead Of Local Storage
- コンポーネントから DB サービスを直接叩いているし、SQL 文をコンポーネントクラスに書いている。サンプルだから仕方ないか。
- Ionic 2 SqlStorage with SQLite and Cordova • techiediaries
- こちらも同様。サンプルだとディレクトリ構成とか無視してコンポーネントに書いてるものしかない…。
- How to Use Ionic SQLite Queries & Pre-Populated Database - Devdactic
- これは DB サービスクラスを作っている。複数のテーブルを管理するようなサンプルがない…。
…ということで、複数のモデルを扱うようなサンプルがイマイチ見当たらず。これといった解が得られなかった。
最近のアプリは API サーバと RESTful にやり取りして、ローカル DB とか要らないんだろうか。いやでもしかし…必要な場合はあるし…そんなロジックを適当に1つの DB クラスに混ぜ込んだりとか…気持ち悪いし…。
誰か良いサンプルがあったら教えてください。