Skip to content

GitHub API を利用して GitHub のリポジトリを検索するアプリです。株式会社ゆめみのFlutterエンジニアコードチェックの要件を満たすよう実装しています。

License

susatthi/github-search

Repository files navigation

Flutter CI codecov MIT

GitHub Search

⚠️ 制限事項

  • 現在 Web 版がビルドできません。Isar 3.0.2 が Web をサポートしなくなったためです。詳細は Issue をご参照ください。
  • 現在テストが通りません。ディレクトリ構造を変更したことにテストが追従できていません。対応中です。

GitHub API を利用して GitHub のリポジトリを検索するアプリです。株式会社ゆめみのFlutterエンジニアコードチェックの要件を満たすよう実装しています。

本アプリを通して自分なりの最適なアーキテクチャを確立し、リファレンスコードにすることを目的にしています。

⚠️ 注意
このアプリは GitHub API を利用するために GitHub の アクセストークン をアプリの内部でハードコーディングして保持する構成になっています。このアプリを公開すると悪意のある者に アクセストークン を抜き取られ悪用される恐れがありますのでお控え下さい。もちろん、手元でビルドして動かすことは問題ありません。

一覧(Light) 一覧(Dark)
index-light index-dark
デスクトップ タブレット
desktop tablet
詳細 0件 エラー
view empty error

github_search_0_9_0_demo

ビルド方法

ソースコードを clone

git clone https://github.com/susatthi/github-search.git

GitHub の個人アクセストークンを取得

本アプリで使用する GitHub の個人アクセストークンを取得して、カレントディレクトリで次のコマンドを実行してください。

# 引数で与えられた環境変数を基にビルドに必要な `lib/util/env/env.dart` を作成してくれます。
# 作成された `lib/util/env/env.dart` を直接編集しても大丈夫です。

bin/flutter_env -g [GitHub 個人アクセストークン] -s [検索文字列の初期値]
パラメータ 説明
-g Must 値には GitHub 個人アクセストークン を設定してください。
-s Optional 値には好きな文字列を設定してください。指定しない場合は空文字が設定されます。
-h ヘルプを表示します。

ビルド

Configurations を選択してビルドしてください。

Configurations 名 説明
app-debug アプリ向けデバッグビルド
app-release アプリ向けリリースビルド
web-debug Web 向けデバッグビルド
web-release Web 向けリリースビルド

技術スタック

  • アプリの機能
    • GitHub リポジトリの検索と詳細表示
    • 検索結果の並び替えと hive を使ったデータの永続化
    • Sliver を使った無限スクロール対応
    • isar を使った検索履歴の保存とサジェスト
  • go_routergo_router_builder を使ったルーティング
  • http を使った REST API の実装
  • fast_i18n を使った多言語対応(日本語/英語)
  • カスタムフォント対応
  • mocktail を使った Unit / Widget テスト
  • flutter_launcher_icons を使ったアプリアイコン
  • flutter_native_splash を使ったスプラッシュ画面
  • responsive_framework を使ったレスポンシブ対応
  • GitHub Actions によるCI(自動テストと自動ビルド)
  • ダークモード対応
  • サポートするプラットフォーム
    • iOS / Android / Web / macOS / Windows

今後対応予定

  • Integration テスト
  • Riverpod 2 対応

対応しないこと

  • Firebase 連携
  • Flavor 対応(develop / staging / production などの環境分け)

アーキテクチャ / パッケージ

アーキテクチャ図

Presentation 層

ユーザーとの I/F を担う層。Application 層と Domain 層に依存する。Infrastructure 層に依存してはいけない。

Widget

ページや UI 部品の Widget クラス群。State を監視( watch / listen )して UI に表現する。ユーザーイベントを検知して Service のメソッドを呼び出す。キャッシュが効かなくなるので直接 Repository Interface を呼び出してはいけない。画面遷移の実装は Widget のイベントハンドラー内で行ってよい。

Application 層

アプリケーションのロジックや状態を定義する層。Domain 層に依存する。Presentation 層と Infrastructure 層に依存してはいけない。

State

アプリのあらゆる状態。Domain 層の Entity そのものでもよいし、複数の Repository をまたいだ Entity を統合するクラスでもよい。State は StateProvider 等でラップされ Widget や他の State から参照される。

Service

ユーザーイベントを受け付けて、複数の Repository Interface を呼び出して Entity を受け取って State を更新するサービスクラス。Widget からのメソッド呼び出しや、依存する State の更新を契機に発火する。

Domain 層

ドメインロジックやドメインオブジェクト(エンティティ)を定義する層。どの層にも依存してはいけない。

Entity

Repository Interface で扱うドメインオブジェクト(データの構造体)。入力値のバリデーションは Entity のコンストラクタで実装する。Infrastructure 層が投げる例外はドメイン層で定義する。

Repository Interface

データの永続化や外部サービス連携を担う Repository のインターフェース。集約毎に定義する。

Infrastructure 層

データの永続化や外部サービス連携を担う層。Domain 層に依存する。Presentation 層と Application 層に依存してはいけない。

Repository Implements

Repository Interface の実装。Data Source を利用してデータの永続化を行う。

Data Source

様々なデータソース。Firebase だったり、API だったり、Hive だったり、SharedPreferences だったり、Isar だったりする。

フォルダ構成

├── application                              アプリケーション層
│   └── <関心事>
│       ├── <state>                          状態クラス群
│       └── <関心事>_service.dart             サービスクラス
├── domain                                   ドメイン層
│   ├── exceptions.dart                      例外クラス
│   └── repository
│       └── <集約>
│           ├── <集約>_repository.dart        リポジトリのインターフェースクラス
│           └── entity                       集約単位のエンティティ
├── infrastructure                           インフラストラクチャ層
│   └── <データソース>
│       └── <集約>
│           └── <集約>_repository.dart       リポジトリの実装
├── presentation
│   ├── app.dart                             アプリケーション
│   ├── router.dart                          ルーティング
│   ├── theme.dart                           テーマ
│   ├── component                            プレゼンテーション層で共通の Widget
│   └── page
│       └── <関心事>
│           ├── component                    画面単位の Widget
│           └── <関心事>_<CURD>page.dart      画面Widget
└── util                                     どの層からもアクセス可能な便利クラス(ロガー、拡張メソッドなど)

ファイル分割の方針

基本的に 関心事 毎にファイルを分割しています。例えば、Controller と State を別々のファイルに分けることはしません。ファイル名は 関心事.dart とします。ファイル名 = クラス名とはしません。

環境

Version
Flutter 3.3.10
Dart 2.18.6

コードの自動生成

  • util/localization/*.json ファイルを変更した場合や freezed を使った dart ファイルを変更した場合は次のコマンドを実行してください。
make build-runner

単体テスト(UnitTest / WidgetTest)

  • ローカルで単体テストを行うためには事前に次のライブラリをインストールしてください。
# lcov のインストール
brew install lcov

# dart_dot_reporter のインストール
flutter pub global activate dart_dot_reporter
  • 次のコマンドで単体テスト(静的解析 => テスト => カバレッジの結果を表示 )を実行します。
# 言語設定が英語のテスト
make test-en

# 言語設定が日本語のテスト
make test-ja

API ドキュメント

  • API ドキュメント で公開しています。

  • 生成する場合は次のコマンドを実行してください。

make dartdoc

CI

  • GitHub Actions を利用して CI を構築しています。
    • プルリクエストが作成や更新された時、もしくは main または develop ブランチに push されたときに CI が発火します。
%%{init:{'theme':'base','themeVariables':{'primaryColor':'#f0f0f0','primaryTextColor':'#2f2f2f', 'lineColor':'#2f2f2f','textColor':'#2f2f2f','fontSize':'16px','nodeBorder':'0px'}}}%%
flowchart LR
    Start((開始)) --> AnalyzeUbuntu(Ubuntu静的解析)
    Start --> AnalyzeMacosEn(macOS英語静的解析)
    Start --> AnalyzeMacosJp(macOS日本語静的解析)
    Start --> AnalyzeWindows(Windows静的解析)
    Start --> BuildAndroid(Androidビルド)
    Start --> BuildiOS(iOSビルド)
    Start --> BuildWeb(Webビルド)
    Start --> BuildMacOS(macOSビルド)
    Start --> BuildWindows(Windowsビルド)

    AnalyzeUbuntu ---> TestUbuntu(Ubuntu単体テスト)
    AnalyzeMacosEn ---> TestMacosEn(macOS英語単体テスト)
    AnalyzeMacosJp --> TestMacosJp(macOS日本語単体テスト)
    TestMacosJp --> UploadCoverageMacosJp(Codecovに結果を送信)
    AnalyzeWindows ---> TestWindows(Windows単体テスト)
    UploadCoverageMacosJp --> NotifySlack(Slackに結果を送信)
    TestUbuntu --> NotifySlack
    TestMacosEn --> NotifySlack
    TestWindows --> NotifySlack
    BuildAndroid ----> NotifySlack
    BuildiOS ----> NotifySlack
    BuildWeb ----> NotifySlack
    BuildMacOS ----> NotifySlack
    BuildWindows ----> NotifySlack
    NotifySlack --> End((終了))

    classDef anchor fill:#4063DD, color:#ffffff;
    classDef testJob fill:#4063DD, color:#ffffff;
    classDef buildJob fill:#d32f2f, color:#ffffff;
    classDef reportJob fill:#437C40, color:#ffffff;
    %% class Start,End anchor;
    class AnalyzeUbuntu,TestUbuntu,UploadCoverageMacosJp,AnalyzeMacosEn,AnalyzeMacosJp,TestMacosEn,TestMacosJp,AnalyzeWindows,TestWindows testJob;
    class BuildAndroid,BuildiOS,BuildWeb,BuildMacOS,BuildWindows,CreateApiDoc,DeployGitHubPages buildJob;
    class NotifySlack reportJob;

ライセンス

MIT

About

GitHub API を利用して GitHub のリポジトリを検索するアプリです。株式会社ゆめみのFlutterエンジニアコードチェックの要件を満たすよう実装しています。

Topics

Resources

License

Stars

Watchers

Forks