はじめに
2020年5月17日にZoomにてFlutterもくもく会を実施したので、
そのレポートになります。個人的所感メインです。
何かご意見などありましたらよろしくお願いします。
話題になった内容をトピックとして記載します。
もし良ければ過去のものもご覧ください。
トピック
多言語対応について
各言語の情報の管理方法で議論になりました。
アプリのローカルで管理するよりも、locizeのようなサービスを使ってリモートコンフィグの操作感で管理するのがアプリの不要なアップデートもせずに済むので、将来的には幸せになりそうという結論にはなりました。参考: locizeのAPIドキュメント
現状の多言語対応そのものについては
参加していただいた@muscle_pandasanさんが
Flutterでの多言語対応をするに書いていただいたので、そちらをご確認ください。
とても勉強になりました
ローカルDBについて
ローカルのデータベースに何使うかの話題になりました。
この3つのライブラリが選択肢と考えています。
個人的にはそのうちSQLite推しで採用しています。
参考: Dart/FlutterのローカルDBの比較
- [Hive] (https://pub.dev/packages/hive)
- Shared preferences
- SQLite(推し)
Hiveについて
処理速度的にはHive
が一番期待大なんですが、v2を控えてる現状手を出しづらい印象を個人的に持っています。
また、ローカルDBのパフォーマンスの差より、ネットワークIOなどの他の要因の方がパフォーマンスのボトルネックになるケースが多いと考えていることも理由です。
Shared preferencesついて
Shared preferences
は全データがカジュアルにデータの扱いがKey, Value
になってしまうので、設定項目ぐらいはいいかなと思います。
しかし、本格的なデータは、小回りが効かないので辞めておくのが無難だと思います。Key
でしかデータが取ってこれないので配列的なデータは全部メモリロードする羽目になります。
SQLiteについて
以下の理由で個人に推しています。
- 公式に紹介されており世の中に知見が豊富である点、
- SQLiteそのものがわりと枯れているのでクライアントツールがごまんとあるのでDBファイルを生成してDB単体で色々こねくり回せる点が個人的には好みで採用しています。
-またSQLiteのプラグインはテスト用のモックも用意されているので、
+またSQLiteのプラグインはテスト用のモックも用意されているので、
下記で設定しておけばテストでも使えるようになるので、絶賛開発で重宝しています。
dev_dependencies:
…
sqflite_common_ffi:
テストについて
個人にはFlutter自体はUIに関心が強いフレークワークの認識なので、そこまでテストは必要でない認識です。
特に、プラグイン呼び出しがある箇所は現状flutter test
で呼び出せなかかったりするので、これからに期待ですね。Firebase系がわりとテストしずらい印象を持っています。
一方で、ビジネスロジックはFlutterのエコシステムから切り離して、Dartで表現できるならユニットテストはありだと考えています。(個人的に意見なので、コメントなどでつっこみ待ちです)
テストのサンプル(Blocを使った例)
最近人気のない気のするBlocアーキテクチャですが、
個人的にはBlocのTestが書きやすいのでそれで書いています。
参考までに現状開発中のアプリにタグ管理機能をつけているのですが、そのタグ管理のテストを貼っておきます。
act
でボタンをクリック時などで発行されるイベントを列挙しておいて,
act: (TagBloc bloc) async {
bloc.add(const TagCreateEvent());
bloc.add(const TagCreateEvent());
bloc.add(const TagSelectEvent(id: 1));
},
expect
で状態がどう変化していくかを確認する流れになります。
expect: <Tag>[
Tag(id: 1, value: "デフォルト名", enable: false),
Tag(id: 2, value: "デフォルト名(1)", enable: false),
Tag(id: 1, value: "デフォルト名", enable: false),
],
副作用のある内容に関してもモックを注入しておき、verify
で検証することもできます。
verify: (_) async {
verify(tagListBloc.add(const TagFetchEvent())).called(2);
},
イベントとオブジェクトの関係はイミュータブルなオブジェクトをイベントに応じて発行して、それを検証している感じです。
発行しているイベントや、確認しているオズジェクトの詳細に関してはBlocライブラリの仕様と関係しているので、詳しくは説明しません。
Blocのテストに関しては、後日記事を書く予定なので、ご了承ください。
せっかくなので、関連するソースコードのスニペットを記載しておきます。
String getTestDBPath(String path) {
String dir = Directory.current.path;
if (dir.endsWith('/test')) {
dir = dir.replaceAll('/test', '');
}
return join(dir, '.dart_tool', 'test', path, 'test.db');
}
Future<Database> setUpTestDatabase(String path) async {
return _openDatabase(getTestDBPath(path));
}
group('タグBlocのテスト', () {
Database db;
TagRepository tagRepository;
MockTagListBloc tagListBloc;
setUp(() async {
db = await setUpTestDatabase('bloc/tag');
tagRepository = TagRepository(database: db, listBloc: tagListBloc);
tagListBloc = MockTagListBloc();
});
tearDown(() async {
await tearDownTestDatabase('bloc/tag');
});
blocTest("タグが作成後選択可能",
build: () async {
return TagBloc(repository: tagRepository);
},
act: (TagBloc bloc) async {
bloc.add(const TagCreateEvent());
bloc.add(const TagCreateEvent());
bloc.add(const TagSelectEvent(id: 1));
},
expect: <Tag>[
Tag(id: 1, value: "デフォルト名", enable: false),
Tag(id: 2, value: "デフォルト名(1)", enable: false),
Tag(id: 1, value: "デフォルト名", enable: false),
],
verify: (_) async {
verify(tagListBloc.add(const TagFetchEvent())).called(2);
},
wait: const Duration(seconds: 1));
}
Firebaseのあれこれ
Firebaseのトラブルに遭遇してる方がいたので、公式のマニュアルに沿って、Analyticsから始めるとシンプルでいいよとアドバイスをさせていただきました。
たまにバージョンの依存関係でトラブル感じがあるので、早くバージョン1になることに期待ですね。
公式リポジトリのissueに上がってることもあるので、そこも要チェックですかね。
その他
今回もちょっとした話を画面共有しながら花を咲かせることができました。
困ってることは意外と言語化が難しいので、リモート時代に画面共有しながらすすめる場が用意できてよかったです。
おわりに次回開催と宣伝
こちらで定期的にもくもく会を隔週の頻度で実施予定です。次回は6月14日を予定しています。
LTなど発表したい方いましたら @glassmonekeyにご連絡いただけますと嬉しいです。LTの練習とかも大歓迎です。
下記のコンパスも良ければ登録お願いします。これを機に一緒に始めましょう
https://flutter-okurayama.connpass.com/
感想というかメモ
画面共有しながらわいわいできるのは、初心者にとっても、自分たちにとってもいい体験なのかもしれないと思いました。
言語化せずに気軽にできる場にしていきたいですね。