如何使用 Flutter 防御性地从 Firestore 请求数据

How to request data from Firestore defensively with Flutter

提问人:Vega180 提问时间:9/30/2021 最后编辑:Vega180 更新时间:9/30/2021 访问量:94

问:

由于 Firestore 是一个 NoSQL 数据库,没有严格的类型规则和定义的文档结构,因此我考虑在我的 Flutter 应用程序中处理损坏的数据。

如果你想知道为什么我想防御性地请求,即使它不是第三方 API - >我可以想到我的应用程序因数据损坏而崩溃的三个原因:

  • 我通过 Firebase 控制台添加了错误的数据,例如将 type 用于本应键入的字段(反复发生)。stringnumber
  • 我的应用中的一个错误将损坏的数据添加到 Firestore。
  • 用户安装了旧版本的应用,该版本无法处理新的 Firestore 数据结构。

我的要求:当请求来自 Firestore 的损坏数据时,应用程序不应崩溃,但应报告损坏的数据,以便可以在 Firestore a.s.a.p 中修复数据。

Flutter Dart google-cloud-firestore nosql 防御性编程

评论


答:

1赞 Vega180 9/30/2021 #1

您如何看待以下方法?

假设我们有一个模型。Movie

Movie {
  final String title;
  final int releaseYear;

  Movie({required this.title, required this.releaseYear});

  Movie.from(Map<String, dynamic> data)
      : title = data['title'],
        releaseYear = data['release_year'];
}

命名构造函数从中解析文档数据并返回我们的模型。只要数据具有 type 字段和 type 字段(在 Firestore 中),这就可以正常工作。fromDocumentSnapshot.data()titleStringrelease_yearintnumber

假设实际数据中缺少该字段。这将使请求崩溃。因此,当前用户无法对相应的电影执行任何操作,而我作为开发人员也不会注意到,因为它在用户的设备上默默地发生。release_year

为了解决第一个问题,我们可以对回退数据使用防御性解析,如下所示: .没有崩溃发生,但我作为开发人员仍然没有注意到并且无法修复数据。data['release_year'] ?? -1

为了解决这个问题,我们可以使用 Firebase Crashlytics。唯一的问题是,如果我们使用防御性解析来防止崩溃,则不会将日志发送到 Firebase。这就是为什么我想出了这个解决方案:

final snapshot = await FirebaseFirestore.instance.collection('movies').doc('123').get();
try {
  return Movie.from(snapshot.data()!);
} catch (e) {
  await FirebaseCrashlytics.instance
      .recordError(e, e.stackTrace(), reason: 'data of movie ${snapshot.id} is corrupt');
  return Movie.fromCorrupt(snapshot.data()!);
}

首先,应用尝试在没有任何回退机制的情况下分析文档数据。如果数据已损坏,则会引发并捕获异常。在 catch 块中,系统会将错误发送到 Firebase,然后调用防御性解析构造函数,让用户继续在应用中处理剩余数据。在每个字段中检查 null 和 type,然后再使用它来创建模型。如果值为 null 或类型错误,则使用回退值。fromCorruptfromCorruptMovie

您如何看待我的方法?我是不是过度设计了?😅