💬

AngularのProjectにDialogっていうディレクトリ構成を入れる理由

2022/07/12に公開

2022年7月現在、Angularを2つの企業で開発しています。
pages, layoutsディレクトリを追加した記事の延長としてもう一つのviewに関するdirectoryとして、Projectの性質に応じてdialogsというディレクトリを追加している理由を記載しようかと思い記事に記載します。


TL;DR

dialogディレクトリを作成する理由は2つ。
1つ目は、dialogのよびだしまたは、閉じる際にdialogにまつわる情報で必要なものは、DialogIdDialogComponentになるので、両方を同一のDirectory(またはFile)内部で管理をする。
2つ目は、現状のdirectory構成がpresentational-componentcontainer-componentになるため呼び出しもとでcontainer or presentationalなのかの意識をもたない設計を実施したい。
の2つの理由で採用する時がある。(container/presentationalは、現状の最適解ではないのは理解していますが、design systemを持たず、のりで開発をするCDRはスタートしたプロジェクトでA以降壊滅する光景をみてきいるので、序盤戦の開発はcontainer.presentaional推しです)


table of contents

  1. dialog directoryを扱う前に
  2. dialogs directoryを作成理由
  3. dialgos directoryの性質

0. dialog directoryを扱う前に

2022年7月現在、Angularを利用して2つの企業のAppliationを開発しています。
利用しているLibraryは,ngrx, nx(nrwl), angular/component(material)を中心に開発をしています。
基本のディレクトリ設計は、下です。また、Atomic DesignでいうAtom, Molecules相当なものはAngularComponentまたは、nx libに切り出して開発を実施しているケースが多いです。

feature-module
|- components
|- containers  // NOT angular default
|- { reducers, actions, effects, resolvers, guards }
|- { pages, layouts } // NOT angular default
|- feature{.routing}.module.ts

今回、話をするdialogは下のようなディレクトリ設計を意図しています。

feature-modules
|- components
|- containers // NOT angular default
|- dialogs    // dialos directory
|- { reducers, actions, effects, resolvers, guards }
|- { pages, layouts } // NOT angular default
|- feature{.routing}.module.ts

1. dialog directoryを作成理由

1. dialogにまつわる情報をカプセル化させたかった
2. 呼び出し元が参照する際に、dialogの性質によって変更されるディレクトリを意識させたくなかった

dialog directoryを作成した理由としては、2つあります。
1つ目は、dialogの呼び出しまたは、閉じる際にdialogにまつわる必要な情報は、DialogIdDialogComponentになるので、両方を同一のDirectory(またはFile)内部で管理を実施したい。
2つ目は現状のProjectで採用しているdirectory設計がcontainer-componentpresentational-componentになるので、dialogの性質によって呼び出し元がcontainerなのか、componentなのかを気にしたくないのが理由です。

1-1. dialogにまつわる情報をカプセル化させたかった

effects、containers、component-store、serviceでdialogを扱う(開く、閉じる)際に利用したい情報としては、DialogComponentDialogId(refもあるが、、、)の2つの情報がメインになるため、DialogIdDialogComponentを同一のディレクトリまたは、ファイルでカプセル化を実施し、Dialogにまつわる関心ごとを集約させたかったため、以下のディレクトリ構成を作成した。

feature/dialogs
|- foo-dialog
    |- foo-dialog.component{.spec}.ts
    |- foo-dialog.component.html
    |- foo-dialog.component.scss
// imports
export cosnt FOO_DIALOG_ID = `${MODULE_NAME}:FooDialog`

@Component()
export class FooDialog {}

feature/dialogs/foo-dialog.component.tsをimportすれば、DialogIDを同時に扱うことができるため、FooDialogにまつわる情報を集約的に扱うことができる。(index.tsを加えてもServiceを加えてもfoo-dialogというディレクトリ内部で完結することができる。)

2. 呼び出し元が参照する際に、dialogの性質によって変更されるディレクトリを意識させたくなかった

{presentational, container}-componentを採用しているため、

  • data(store)にまつわる情報を利用する際に、 container-components
  • viewだけの情報を利用する際に、presentational-components
    になるためdialogの性質よりcontainer directoryにいれるか、component directoryにいれるかの判断や変更の必要性が生じていた(auto importすればいいけど気持ち悪い)。
    利用する側がcontainercomponentsの関心を持つことにメリットが開発の側面から薄かったため、この関心を意識させないようなディレクトリ構造を作成したかった。

上記2つの理由をもとにdialog directoryの作成をする場合がある。。。


2. dialgos directoryの性質

dialog-directoryは、dialogID@Componentを保持することを制約におきました。

また、presetatinal,containerのどちらでも利用可能としました(dialogの性質上どちらもあり得る)。
また、呼び出し元ではafterClosedを利用せずに、データの作成や編集、削除などでは、dialogで状態を管理できるように、Service(component-store)を利用して関心の分離をはかる。

制約

- dialogIdと@Componentをexportする
- 可能な限りdialogにまつわる状態は、dialog内部で完結をする(component-store, serviceを推奨)
- afterClosed, afterOpendを利用してstoreの更新は実施しない

憂慮

- presentational-component, container-componentも可
- consts.tsで,`dialogId`や`dialogConfig`をexportして対応も可

特性

- dialog内部の関心はdialog内部で実施する
- dialogにまつわる情報は、directory内部で管理を実施する

1. ベース構成

feature/dialogs
|- foo-dialog
    |- foo-dialog.component{.spec}.ts
    |- foo-dialog.component.html
    |- foo-dialog.component.scss

2. constを利用したファイル構成

feature/dialogs
|- foo-dialog
    |- foo-dialog.component{.spec}.ts
    |- foo-dialog.component.html
    |- foo-dialog.component.scss
    |- foo-dialog.config.ts
export const FOO_DIALOG_ID = `${MODULE_NAME}:FooDialog`

export const FOO_DIALOG_CONFIG = {}

3. index.tsを利用したexport管理

feature/dialogs
|- foo-dialog
    |- foo-dialog.component{.spec}.ts
    |- foo-dialog.component.html
    |- foo-dialog.component.scss
    |- foo-dialog.config.ts
    |- index.ts
export { FooDialog } from "./foo-dialog.components.ts"
export { FOO_DIALOG_ID, FOO_DIALOG_CONFIG } from "./foo-dialog.config"

記載はしませんが、dialogがかなりFatな場合は、libとかmoduleに切り出して、Openなど管理するServiceを突っ込むこともありますが、その際にはデザイナーに「マジ!?」ってわざとらしくききます。

Discussion