Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Angular Webアプリケーションの最新設計手法.pdf

kou
November 25, 2018
11k

Angular Webアプリケーションの最新設計手法.pdf

Angularを使用したWebアプリケーションの設計手法について、周辺ライブラリやトレンドを踏まえてお話します。近年複雑化しつつあるWebアプリケーション開発に対して、コンポーネントやデータ構造をどのように設計し開発することができるか、最新の技術を紹介しながら解説します。

kou

November 25, 2018
Tweet

Transcript

  1. 4 設計 拡張性 保守性 信頼性 - 設計とは、アプリケーションの柔軟性や堅牢性の基盤 - 設計とは、開発者同士の実装に対する共通意識 -

    良い設計は、アプリケーションの信頼性と拡張性、開発効率の向上を生み出す なぜ設計を考える必要があるのか ?
  2. 7 Component - based Architecture <!doctype html> <html> <head> ...

    </head> <body> <app-root></app-root> </body> </html>
  3. 8 Component - based Architecture App Component Component Component Component

    Component Component - 最上位に AppComponentがあり、その下に子 Component がツリー構造で存在 - アプリケーションのそれぞれの機能は 1つ1つの Component で表現される
  4. 9

  5. 17 Component の分類 App Component Page Component Container Component Presentational

    Component Component Design Application そのものを表す、トップレベルの Component Web Pageを表す、URL単位の Component Serviceを使用して状態管理を行う Component 状態を持たない、表示専用の Component
  6. 24 App Component Application そのものを表す、トップレベルの Component @Component({ selector: 'app-root', template:

    ` <router-outlet></router-outlet> `, }) export class AppComponent implements OnInit { ngOnInit(): void { // アプリケーション初期化処理など } } Component Design
  7. 25 App Component How should we use App Component ?

    - アプリケーションの全体の設定や、各 Serviceの初期化処理などを行う - 例)APIからの初期データの取得、WebSocketの接続処理など - 初期化処理は基本的に Service に移譲し、シンプルに保つ Component Design
  8. 29 Page Component @Component({ template: ` <app-header></app-header> <app-hero [heroId]="heroId"></app-hero> <app-footer></app-footer>

    `, }) export class PageComponent implements OnInit { constructor( private route: ActivatedRoute, ) {} ngOnInit(): void { // RouterからURL情報を取得し、Componentの状態を設定 this.heroId = this.route.paramMap... } } Web Pageを表す、URL単位の Component Component Design
  9. 30 Page Component - 1 URLにつき、1 Page Componentを作成する ( 再利用はしない

    ) - テンプレートは Container Component、Presentational Componentで構成する - Router、ActivatedRoute などの Router関連の機能はこの Componentでのみ使用する Component Design How should we use Page Component ?
  10. 33 Container Component @Component({ selector: 'app-heroes', template: ` <app-hero-detail *ngFor="let

    hero of heroes" [hero]="hero" ><app-hero-detail> `, }) export class HeroesComponent implements OnInit { constructor(private heroService: HeroService) {} ngOnInit(): void { // Serviceを使用してComponent内のデータを初期化 this.heroes = this.heroService.getHeroes()... } } Serviceを使用して状態管理を行う Component Component Design
  11. 34 Container Component - Service と Presentational Component のデータの受け渡しに専念し、ロジックを持たせない -

    表示については Presentational Component を使用し、この Componentでは行わない - テストが不要になるレベルでシンプルに保つ Component Design How should we use Container Component ?
  12. 37 Presentational Component @Component({ selector: 'app-hero-detail', template: ` <div>{{ hero.name

    }}</div> <button (click)="buttonClick.emit()"> Delete </button> `, }) export class HeroesComponent implements OnInit { @Input() hero: Hero; @Output() buttonClick = new EventEmitter(); } 状態を持たない、表示専用の Component Component Design
  13. 38 Presentational Component - シンプルな HTML のみで構成する - Serviceを使用せず、@input のみを使用してデータを受け取る

    - テンプレート内のイベントは @Output を使用して上位 Component へ伝播させる - この Component でアプリケーションの大部分を構成するようにする Component Design How should we use Presentational Component ?
  14. 39 Component の分類のコツ - Component の分割は、開発規模に応じて柔軟に行う - 例え冗長であっても、適切に分割することが重要 - 表示専用の

    Presentational Component をなるべく多く作成する - Container Component が複雑にならないよう、Serviceに処理を寄せる Component Design App Component Page Component Container Component Presentational Component
  15. 40 Component のテスト粒度 App Component Page Component Container Component Presentational

    Component Component Design E2Eテストでページ表示のテストを行う E2Eテストでページ表示のテストを行う Serviceに対してのメソッドコールをユニットテストで確認する @Input、@Outputが適切に処理されているかユニットテストを行う
  16. 42 Module - Module は 機能単位での Component の集合 - Service

    なども含めることができるが、アプリケーション用の Module は Component 群のカプセル化と考えるのが良い Module Structure Module is a set of Components has Module Components
  17. 43 @NgModule({ imports: [ CommonModule, MaterialModule, ... ], declarations: [

    HeroPageComponent, HeroListComponent, HeroComponent, ], }) export class HeroModule {} Module Module Structure
  18. 44 Module App Module Feature Module Feature Module Feature Module

    Feature Module Feature Module Module 設計 - Moduleは Component と同様に、ツリー構造を持つ - Module はそれだけで完結する機能の単位として分割する - App Module の子となる機能単位でカプセル化された Module のことを Feature Module と呼ぶ Module Structure
  19. 45 Module - 小規模なアプリケーションではルートとなる AppModule だけで十分 - 大規模な開発では、機能毎に開発担当者が異なるため Feature Module

    が必要 - ( 一部の変更が他の Module に影響を与えないためのカプセル化 ) Module 設計 Module Structure Why should we use Module ?
  20. 46 Core & Shared Module - Angular の公式で紹介されている特殊な Module -

    これらの Module は複数の Feature Module で共有して使用される - Core Module は Serviceや関数を、Shared Module は Componentや Pipe を管理する Core Module Shared Module Module Structure
  21. 47 Core & Shared Module - Core Module は Service

    などのロジックに関する共通の機能を提供 - Shared Module は Component などの View に関する共通の機能を提供 - 全ての Feature Module はこの 2つの Module を共有して使用する Module Structure
  22. 48 Feature ModuleとComponentのディレクトリ構造 - Feature Module は feature-modules というフォルダに配置 -

    Feature Module 内に機能単位でサブフォルダを作成 - Feature Moduleは、他の Feature Module に影響を与えない (1部のFeature Moduleが壊れても他の箇所は動作する) Module Structure
  23. 50 State Management State Management - State とは、移り変わるアプリケーションの状態を表す - State

    Management とは アプリケーションのデータ管理方法 - Angularでは、主に Component と Service の連携方法 Component Component State Service
  24. 51 2種類の State Management Component Single Data Service Data Service

    Global Store Store Data Service Data Service Component Component Component Component Component State Management
  25. 53 Single Data Service - 1つのデータタイプ (モデル) につき、1つの Serviceを作成し状態管理する -

    Service はデータを Stream として提供し、 Component はそれらを subscribe する形で、リアルタイムにデータを受け取る Data Service Component Component update subscribe State Management
  26. 54 Single Data Service @Injectable({ providedIn: 'root', }) export class

    HeroDataService { private _data$ = new BehaviorSubject([]); getData(): Observable<Hero[]> { return this._data$.asObservable(); } update(data: Hero[]): void { this._data$.next(data); } } @Component({ ... }) export class HeroListComponent implements OnInit { private heroes$: Observable<Hero[]>; constructor( private heroDataService: HeroDataService, ) {} ngOnInit(): void { this.heroes$ = this.heroDataService.getData(); // データの種類に対して 1つのDataServiceを使う // this.villains$ = this.villainDataService.data$; } } State Management
  27. 55 Single Data Service Data Service Component Component - 小さく始められる

    - シンプルで仕様理解が簡単 Pros - Serviceの数が増えた時に急激に複雑化 - どのデータがどの Service にあるのか分かりづらい - 各 Service毎に仕様が異なる可能性がある Cons update subscribe State Management
  28. 56 Single Data Service - 小規模なアプリケーション (1-3人程度の開発者) - 仕様が開発と同時に進むような、スピードの求められる開発 -

    ある程度の大規模なアプリケーションが予定される場合は、 後述の Global Storeを使用すべき State Management When should we use Single Data Service ?
  29. 58 Global Store - 1つの Store が全てのデータを管理 (Databaseとなる) - Component

    は Actionを使用して Store を更新 - Data (State) の更新処理には reducer という関数を使用 Store reducer dispatch Action subscribe Component Component State Management
  30. 60 Global Store - 決まった形式での統一的な実装 - Storeの拡張性が高く、大規模な状 態管理に強い Pros -

    小規模なアプリケーションに対してはやや複雑 - どの Action がどの状態を変更するか分かりづらい Cons State Management Store reducer subscribe Component Component dispatch Action
  31. 63 Action Design - Data Service と違い、Store はアプリケーションの中央 Database そのもの

    - 直接 Database の書き換えができないように、 Store の直接の更新はできない - Action / Reducer は、Database に対しての更新クエリと見なせる State Management Why should we use Action ?
  32. 65 Action Design Login Load Users Update User Detail Load

    User Detail Reload Users Login後、User一覧ページから指定のUser情報を閲覧、アップデートする一連の処理 State Management
  33. 66 Action Design Login後、User一覧ページから指定のUser情報を閲覧、アップデートする一連の処理 [ Login Page ] Login [

    User List Page ] Load Users [ User Detail Page ] Update User Detail [ User Detail Page ] Load User Detail [ User List Page ] Reload Users Login Load Users Update User Detail Load User Detail Reload Users State Management
  34. 67 Action Design Login後、User一覧ページから指定のUser情報を閲覧、アップデートする一連の処理 [ Login Page ] Login [

    User List Page ] Load Users [ User Detail Page ] Update User Detail [ User Detail Page ] Load User Detail [ User List Page ] Reload Users [ Login API ] Login Success [ Router ] Move Page [ User API ] Load Users Success [ User API ] Load User Detail Success [ Router ] Move Page [ User API ] Update User Detail Success [ User API ] Reload Users Success [ Router ] Move Page State Management
  35. 69 Component Design Module Structure State Management Conclusion - Component

    分割を適切に行う - 表示に重点を置き、ロジック をシンプルにすること - 機能、URL単位で適切に分ける - 他機能に影響を与えないように カプセル化を利用する - アプリケーション、開発チームの 規模に応じた適切な状態管理を 採用する