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

A4f3ebc2aec77cf12952f4899907ec34?s=47 kou
November 25, 2018
6k

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

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

A4f3ebc2aec77cf12952f4899907ec34?s=128

kou

November 25, 2018
Tweet

Transcript

  1. Angular Webアプリケーション 最新設計手法 HTML5 Conference 2018

  2. 2 @kou

  3. 3 お話すること Component Design Module Structure State Management

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

    良い設計は、アプリケーションの信頼性と拡張性、開発効率の向上を生み出す なぜ設計を考える必要があるのか ?
  5. 5 Angular - Web Applicationのためのフレームワーク - TypeScript / One Frameworkの堅牢なアプリケーション基盤

    - Component - based Architecture
  6. 6 Component - based Architecture アプリケーションそのものが 1つの Component で表現される Application

    is Component Application Component =
  7. 7 Component - based Architecture <!doctype html> <html> <head> ...

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

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

  10. 10 App Component

  11. 11 Component

  12. 12 Component

  13. 13 Component

  14. - アプリケーションは Component で表現される - アプリケーション設計とは、Componentの分類と設計の手法と言える - 良い Component 設計さえあれば、複雑な設計は必要でない

    14 Component Component Design How should we design Components ?
  15. Component Design

  16. 16 Component の分類 - Component 設計の第一歩は、適切な分類分けをすること - Component は役割に応じて4種類に分類することができる App

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

    Component Component Design Application そのものを表す、トップレベルの Component Web Pageを表す、URL単位の Component Serviceを使用して状態管理を行う Component 状態を持たない、表示専用の Component
  18. 18 App Component

  19. 19 Page Component

  20. 20 Container Component

  21. 21 Presentational Component

  22. App Component

  23. 23 App Component

  24. 24 App Component Application そのものを表す、トップレベルの Component @Component({ selector: 'app-root', template:

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

    - アプリケーションの全体の設定や、各 Serviceの初期化処理などを行う - 例)APIからの初期データの取得、WebSocketの接続処理など - 初期化処理は基本的に Service に移譲し、シンプルに保つ Component Design
  26. Page Component

  27. 27 Page Component

  28. Page Component

  29. 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
  30. 30 Page Component - 1 URLにつき、1 Page Componentを作成する ( 再利用はしない

    ) - テンプレートは Container Component、Presentational Componentで構成する - Router、ActivatedRoute などの Router関連の機能はこの Componentでのみ使用する Component Design How should we use Page Component ?
  31. Container Component

  32. 32 Container Component

  33. 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
  34. 34 Container Component - Service と Presentational Component のデータの受け渡しに専念し、ロジックを持たせない -

    表示については Presentational Component を使用し、この Componentでは行わない - テストが不要になるレベルでシンプルに保つ Component Design How should we use Container Component ?
  35. Presentational Component

  36. 36 Presentational Component

  37. 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
  38. 38 Presentational Component - シンプルな HTML のみで構成する - Serviceを使用せず、@input のみを使用してデータを受け取る

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

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

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

  42. 42 Module - Module は 機能単位での Component の集合 - Service

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

    HeroPageComponent, HeroListComponent, HeroComponent, ], }) export class HeroModule {} Module Module Structure
  44. 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
  45. 45 Module - 小規模なアプリケーションではルートとなる AppModule だけで十分 - 大規模な開発では、機能毎に開発担当者が異なるため Feature Module

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

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

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

    Feature Module 内に機能単位でサブフォルダを作成 - Feature Moduleは、他の Feature Module に影響を与えない (1部のFeature Moduleが壊れても他の箇所は動作する) Module Structure
  49. State Management

  50. 50 State Management State Management - State とは、移り変わるアプリケーションの状態を表す - State

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

    Global Store Store Data Service Data Service Component Component Component Component Component State Management
  52. Single Data Service

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

    Service はデータを Stream として提供し、 Component はそれらを subscribe する形で、リアルタイムにデータを受け取る Data Service Component Component update subscribe State Management
  54. 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
  55. 55 Single Data Service Data Service Component Component - 小さく始められる

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

    ある程度の大規模なアプリケーションが予定される場合は、 後述の Global Storeを使用すべき State Management When should we use Single Data Service ?
  57. Global Store

  58. 58 Global Store - 1つの Store が全てのデータを管理 (Databaseとなる) - Component

    は Actionを使用して Store を更新 - Data (State) の更新処理には reducer という関数を使用 Store reducer dispatch Action subscribe Component Component State Management
  59. 59 Global Store NGRX Reactive State for Angular State Management

    ngrx.io
  60. 60 Global Store - 決まった形式での統一的な実装 - Storeの拡張性が高く、大規模な状 態管理に強い Pros -

    小規模なアプリケーションに対してはやや複雑 - どの Action がどの状態を変更するか分かりづらい Cons State Management Store reducer subscribe Component Component dispatch Action
  61. 61 Global Store - 大規模なアプリケーション (5人以上の開発者) - 適切な Action 設計を考えてアプリケーション開発が可能な開発チーム

    State Management When should we use Global Store ?
  62. Action Design

  63. 63 Action Design - Data Service と違い、Store はアプリケーションの中央 Database そのもの

    - 直接 Database の書き換えができないように、 Store の直接の更新はできない - Action / Reducer は、Database に対しての更新クエリと見なせる State Management Why should we use Action ?
  64. 64 Action Design - Actionはアプリケーションの状態変更を示す - 分かりやすい Actionの設計は、アプリケーション仕様の理解を簡単にする - Global

    Store を使う上で、Actionの設計が最も重要になる State Management How should we use Action ?
  65. 65 Action Design Login Load Users Update User Detail Load

    User Detail Reload Users Login後、User一覧ページから指定のUser情報を閲覧、アップデートする一連の処理 State Management
  66. 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
  67. 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
  68. Conclusion

  69. 69 Component Design Module Structure State Management Conclusion - Component

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