$30 off During Our Annual Pro Sale. View Details »

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

kou
November 25, 2018
9.9k

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

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

kou

November 25, 2018
Tweet

Transcript

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

    View Slide

  2. 2
    @kou

    View Slide

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

    View Slide

  4. 4
    設計
    拡張性 保守性 信頼性
    - 設計とは、アプリケーションの柔軟性や堅牢性の基盤
    - 設計とは、開発者同士の実装に対する共通意識
    - 良い設計は、アプリケーションの信頼性と拡張性、開発効率の向上を生み出す
    なぜ設計を考える必要があるのか ?

    View Slide

  5. 5
    Angular
    - Web Applicationのためのフレームワーク
    - TypeScript / One Frameworkの堅牢なアプリケーション基盤
    - Component - based Architecture

    View Slide

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

    View Slide

  7. 7
    Component - based Architecture



    ...





    View Slide

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

    View Slide

  9. 9

    View Slide

  10. 10
    App
    Component

    View Slide

  11. 11
    Component

    View Slide

  12. 12
    Component

    View Slide

  13. 13
    Component

    View Slide

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

    View Slide

  15. Component Design

    View Slide

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

    View Slide

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

    View Slide

  18. 18
    App
    Component

    View Slide

  19. 19
    Page
    Component

    View Slide

  20. 20
    Container
    Component

    View Slide

  21. 21
    Presentational
    Component

    View Slide

  22. App Component

    View Slide

  23. 23
    App
    Component

    View Slide

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

    `,
    })
    export class AppComponent implements OnInit {
    ngOnInit(): void {
    // アプリケーション初期化処理など
    }
    }
    Component
    Design

    View Slide

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

    View Slide

  26. Page Component

    View Slide

  27. 27
    Page
    Component

    View Slide

  28. Page
    Component

    View Slide

  29. 29
    Page Component
    @Component({
    template: `



    `,
    })
    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

    View Slide

  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 ?

    View Slide

  31. Container Component

    View Slide

  32. 32
    Container
    Component

    View Slide

  33. 33
    Container Component
    @Component({
    selector: 'app-heroes',
    template: `
    *ngFor="let hero of heroes"
    [hero]="hero"
    >
    `,
    })
    export class HeroesComponent implements OnInit {
    constructor(private heroService: HeroService) {}
    ngOnInit(): void {
    // Serviceを使用してComponent内のデータを初期化
    this.heroes = this.heroService.getHeroes()...
    }
    }
    Serviceを使用して状態管理を行う Component
    Component
    Design

    View Slide

  34. 34
    Container Component
    - Service と Presentational Component のデータの受け渡しに専念し、ロジックを持たせない
    - 表示については Presentational Component を使用し、この Componentでは行わない
    - テストが不要になるレベルでシンプルに保つ
    Component
    Design
    How should we use Container Component ?

    View Slide

  35. Presentational Component

    View Slide

  36. 36
    Presentational
    Component

    View Slide

  37. 37
    Presentational Component
    @Component({
    selector: 'app-hero-detail',
    template: `
    {{ hero.name }}
    Delete
    `,
    })
    export class HeroesComponent implements OnInit {
    @Input() hero: Hero;
    @Output() buttonClick = new EventEmitter();
    }
    状態を持たない、表示専用の Component
    Component
    Design

    View Slide

  38. 38
    Presentational Component
    - シンプルな HTML のみで構成する
    - Serviceを使用せず、@input のみを使用してデータを受け取る
    - テンプレート内のイベントは @Output を使用して上位 Component へ伝播させる
    - この Component でアプリケーションの大部分を構成するようにする
    Component
    Design
    How should we use Presentational Component ?

    View Slide

  39. 39
    Component の分類のコツ
    - Component の分割は、開発規模に応じて柔軟に行う
    - 例え冗長であっても、適切に分割することが重要
    - 表示専用の Presentational Component をなるべく多く作成する
    - Container Component が複雑にならないよう、Serviceに処理を寄せる
    Component
    Design
    App
    Component
    Page
    Component
    Container
    Component
    Presentational
    Component

    View Slide

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

    View Slide

  41. Module Structure

    View Slide

  42. 42
    Module
    - Module は 機能単位での Component の集合
    - Service なども含めることができるが、アプリケーション用の Module は
    Component 群のカプセル化と考えるのが良い
    Module
    Structure
    Module is a set of Components
    has
    Module Components

    View Slide

  43. 43
    @NgModule({
    imports: [
    CommonModule,
    MaterialModule,
    ...
    ],
    declarations: [
    HeroPageComponent,
    HeroListComponent,
    HeroComponent,
    ],
    })
    export class HeroModule {}
    Module
    Module
    Structure

    View Slide

  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

    View Slide

  45. 45
    Module
    - 小規模なアプリケーションではルートとなる AppModule だけで十分
    - 大規模な開発では、機能毎に開発担当者が異なるため Feature Module が必要
    - ( 一部の変更が他の Module に影響を与えないためのカプセル化 )
    Module
    設計
    Module
    Structure
    Why should we use Module ?

    View Slide

  46. 46
    Core & Shared Module
    - Angular の公式で紹介されている特殊な Module
    - これらの Module は複数の Feature Module で共有して使用される
    - Core Module は Serviceや関数を、Shared Module は Componentや Pipe を管理する
    Core Module Shared Module
    Module
    Structure

    View Slide

  47. 47
    Core & Shared Module
    - Core Module は Service などのロジックに関する共通の機能を提供
    - Shared Module は Component などの View に関する共通の機能を提供
    - 全ての Feature Module はこの 2つの Module を共有して使用する
    Module
    Structure

    View Slide

  48. 48
    Feature ModuleとComponentのディレクトリ構造
    - Feature Module は feature-modules というフォルダに配置
    - Feature Module 内に機能単位でサブフォルダを作成
    - Feature Moduleは、他の Feature Module に影響を与えない
    (1部のFeature Moduleが壊れても他の箇所は動作する)
    Module
    Structure

    View Slide

  49. State Management

    View Slide

  50. 50
    State Management
    State
    Management
    - State とは、移り変わるアプリケーションの状態を表す
    - State Management とは アプリケーションのデータ管理方法
    - Angularでは、主に Component と Service の連携方法
    Component Component
    State
    Service

    View Slide

  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

    View Slide

  52. Single Data Service

    View Slide

  53. 53
    Single Data Service
    - 1つのデータタイプ (モデル) につき、1つの Serviceを作成し状態管理する
    - Service はデータを Stream として提供し、
    Component はそれらを subscribe する形で、リアルタイムにデータを受け取る
    Data
    Service
    Component
    Component
    update
    subscribe
    State
    Management

    View Slide

  54. 54
    Single Data Service
    @Injectable({
    providedIn: 'root',
    })
    export class HeroDataService {
    private _data$ = new BehaviorSubject([]);
    getData(): Observable {
    return this._data$.asObservable();
    }
    update(data: Hero[]): void {
    this._data$.next(data);
    }
    }
    @Component({
    ...
    })
    export class HeroListComponent implements OnInit {
    private heroes$: Observable;
    constructor(
    private heroDataService: HeroDataService,
    ) {}
    ngOnInit(): void {
    this.heroes$ = this.heroDataService.getData();
    // データの種類に対して
    1つのDataServiceを使う
    // this.villains$ = this.villainDataService.data$;
    }
    }
    State
    Management

    View Slide

  55. 55
    Single Data Service
    Data
    Service
    Component
    Component
    - 小さく始められる
    - シンプルで仕様理解が簡単
    Pros
    - Serviceの数が増えた時に急激に複雑化
    - どのデータがどの Service にあるのか分かりづらい
    - 各 Service毎に仕様が異なる可能性がある
    Cons
    update
    subscribe
    State
    Management

    View Slide

  56. 56
    Single Data Service
    - 小規模なアプリケーション (1-3人程度の開発者)
    - 仕様が開発と同時に進むような、スピードの求められる開発
    - ある程度の大規模なアプリケーションが予定される場合は、
    後述の Global Storeを使用すべき
    State
    Management
    When should we use Single Data Service ?

    View Slide

  57. Global Store

    View Slide

  58. 58
    Global Store
    - 1つの Store が全てのデータを管理 (Databaseとなる)
    - Component は Actionを使用して Store を更新
    - Data (State) の更新処理には reducer という関数を使用
    Store
    reducer
    dispatch
    Action
    subscribe
    Component
    Component
    State
    Management

    View Slide

  59. 59
    Global Store
    NGRX
    Reactive State for Angular
    State
    Management
    ngrx.io

    View Slide

  60. 60
    Global Store
    - 決まった形式での統一的な実装
    - Storeの拡張性が高く、大規模な状
    態管理に強い
    Pros
    - 小規模なアプリケーションに対してはやや複雑
    - どの Action がどの状態を変更するか分かりづらい
    Cons
    State
    Management
    Store
    reducer
    subscribe
    Component
    Component
    dispatch
    Action

    View Slide

  61. 61
    Global Store
    - 大規模なアプリケーション (5人以上の開発者)
    - 適切な Action 設計を考えてアプリケーション開発が可能な開発チーム
    State
    Management
    When should we use Global Store ?

    View Slide

  62. Action Design

    View Slide

  63. 63
    Action Design
    - Data Service と違い、Store はアプリケーションの中央 Database そのもの
    - 直接 Database の書き換えができないように、 Store の直接の更新はできない
    - Action / Reducer は、Database に対しての更新クエリと見なせる
    State
    Management
    Why should we use Action ?

    View Slide

  64. 64
    Action Design
    - Actionはアプリケーションの状態変更を示す
    - 分かりやすい Actionの設計は、アプリケーション仕様の理解を簡単にする
    - Global Store を使う上で、Actionの設計が最も重要になる
    State
    Management
    How should we use Action ?

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  68. Conclusion

    View Slide

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

    View Slide

  70. ありがとうございました

    View Slide