26
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

わたしのFlutterお勉強用Advent Calendar 2020

Day 15

FlutterでClean ArchitectureとTDDをやってみる その1 - 概要

Last updated at Posted at 2020-12-13

最近お世話になっているReso CoderさんのFlutter TDD Clean Architecture Courseをやってみます。

GitHubに上がっているコードが問題なく動いたので安心して学習できそうです。

このチュートリアルで作るアプリは、数字に関するトリビアを表示するというものです。具体的にはこのページの一部をアプリで再現します。
全14回あり少し長いですが学習しながら学んだことをアウトプットします。


第1回 プロジェクトの構造

  • 今回はコーディングはしません
  • 構成の説明となります

TDDとClean Architectureを使う理由

  • コードをクリーンに保ちテストすることは重要だから
    • プロジェクトが大きくなりにつれビジネスロジックが散在しがちだから
  • ビジネスロジック(Entities)がUIやDBの変更の影響を受けないようにしたいから
    • 特にビジネスロジックのUse CasesはDBからデータを取得し処理するため、DataSourceのコードに依存しがちである
      • これを依存性逆転の法則により依存方向を変えたい

Clean Architectureの構造

CleanArchitecture.jpg

  • 図のように階層になっている
    • コードを分離する
      • 実装でなくインターフェイスに依存する
      • 実オブジェクトは依存性注入(DI)する
    • 内側方向にのみ依存する
      • Entitiesは何にも依存せず、UseCasesはEntitiesのみに依存する
      • しかし赤色のUse CasesがControllersに依存してしまいがちである
        • これを依存性逆転の法則により反転させるのがClean Architectureの狙いである

このチュートリアルで作るもの

  • Numbers APIを利用して、数字の説明を表示するアプリを作る
  • 以下のような構成で作る
  • 自然に実装するとCall Flowの方向に依存するが、DomainがDataに依存するのは好ましくない
    • これを解決するのがCleanArchitectureの大きな目的の1つと言っていい

Clean-Architecture-Flutter-Diagram.png

  • 次のようなフォルダ構成を持つ
    • /lib
      • /core
      • /features
        • /number_trivia
          • /data
            • datasources
            • models
            • repositories(Implementations)
          • /domain
            • entities
            • repositories(Contracts)
            • usecases
          • /presentation
            • /bloc
            • /pages
            • /widgets

Presentation

  • Blocパターンを使う
  • Widgetsがeventsを送って、Blocからstatesを受け取る
  • CleanArchitectureではBlocはPresentationにあたる

Domain

  • DomainはCleanArchitectureの内側の層である
    • Business logic(use cases)とBusiness objects(entities)を含む
    • 他のレイヤーには依存しない

Use Cases

Repositories

domain-layer-diagram.png

  • RepositoriesはDomain層とData層にまたがっている
    • Repositoriesビジネスロジックとデータ操作のロジックを分離して、データ操作を隠蔽する
      • Repositoryは永続化ストレージが何かについて関知しない
      • Repositoryを利用するクラスはビジネスロジックに集中する
    • Domain層にRepositoryのインターフェイスが位置する
    • Data層にRepositoryの実装が位置する
  • RepositoryのインターフェイスがDomain層に、実装がData層にまたがる構成よってUseCaseがData層に依存することを回避する
    • これが依存性逆転の原則の実現となっている
依存性逆転の原則
  • 設計をすすめる上で以下の問題があり、それを解決するための原則
  • 問題点: 自然に実装する依存の方向性と設計上合理的な依存の方向性が逆になってしまう
    • 例:
      • Use Caseがデータを取得するため、Repositoryに依存するコードを書いてしまうが
      • Repositoryは変更される可能性が高く、変更した場合に修正点が多くなりすぎる
  • 解決方法:
    • Use CaseがRepositoryの実装ではなくインターフェイスに依存する
    • DI(依存性の注入)等の手法を用いて、Use CaseがRepositoryの実装を読み込む
      • DI以外だとFactoryを使う方法がある。

Entity

  • NumberTriviaという名のEntityファイルを持ちます
    • ここで作成するアプリは単純なものなので、Entityは一つです
      • 一般的なアプリは複数のEntitiyを持ちます
  • Entityはほとんど変化しません
    • だから何にも依存せず、他のオブジェクトから依存される設計とします
      • 変化するものが変化しないものへ依存するというのが、CleanArchitectureの依存方向の理由になります
  • APIから取得する情報はEntityではありません
    • Data層のDataSourceでAPIにより情報を取得しますが、これはEntityを継承したModelになります。

Data

  • Data層はRepositoryの実装とData Sourcesを持ちます

Repositoryの実装

  • Repositoryのインターフェイスは前述のようにDomain層に持ちます

Data Sources

data-layer-diagram.png

  • Data Sourcesは以下の2つがあります
    • APIを呼ぶRemote Data Sources
    • キャッシュしたデータを読み込むLocal Data Sources
  • Data SourcesはEntityではなくModelを返します
    • ModelはEntityを拡張した子クラスになります
      • ModelはDataSourcesから受け取るJSONを処理します。JSON操作に特化した機能をDomain Entityに持ちたくないので子クラスのModelを使います
        • CleanArchitecture図の中央に位置するEntityは他のレイヤーに依存せず、DataSourcesが扱うデータ形式について関知しません
  • RepositoryはRemoteとLocalの2つのDataSourcesを組み合わせます
    • RemoteDataSource: Numbers APIに対するHTTP GETリクエストを処理します
    • LocalDataSource: shared_preferencesパッケージを用いてキャッシュデータを処理します
      • キャッシュはオフラインのときに前回通信で取得したキャッシュデータを返すというような使い方をします

感想と学んだこと

  • Flutter TDD Clean Architecture Course[1]の説明をしました。
  • Clean Architectureの概要を学びました。
    • Layerで分ける
    • 外側から内側方向にのみ依存する
      • Use Case(内側)がRepository(外側)を利用する際はRepositoryのContract(Interface)にのみ依存する
        • この部分が依存性逆転の原則の適用となる
    • Repository層を利用してData Sourcesを隠蔽化する
    • RepositoryがDataSourcesから取得するものはEntityを継承したModelとする
      • Entityは何にも依存しないため、JSON処理をしないため
    • Blocはビジネスロジックという名前だがDomainでなくPresenterとなる
      • ただしこの記事ではBlocがビジネスロジックとなっている
        • CleanArchitectureの実装方法は複数あるということだと思う
  • Clean ArchitectureはSOLIDを実現する手法だと感じた
  • 次回から実装に入ります
26
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?