跳至主要内容

架构案例研究

本指南中的代码示例来自指南针示例应用程序,这是一个帮助用户创建和预订旅行行程的应用程序。它是一个功能强大的示例应用程序,具有许多功能、路由和屏幕。该应用程序与 HTTP 服务器通信,具有开发和生产环境,包括特定于品牌的样式,并且具有较高的测试覆盖率。通过这些方式以及更多方式,它模拟了一个真实的、功能丰富的 Flutter 应用程序。

A screenshot of the splash screen of the compass app.

A screenshot of the home screen of the compass app.

A screenshot of the search form screen of the compass app.

A screenshot of the booking screen of the compass app.

指南针应用程序的架构最类似于Flutter 的应用程序架构指南中描述的MVVM 设计模式。本架构案例研究通过介绍指南针应用程序的“主页”功能,演示了如何实现这些指南。如果您不熟悉 MVVM,则应首先阅读这些指南。

指南针应用程序的主屏幕显示用户信息和用户保存的行程列表。从此屏幕,您可以注销、打开详细的行程页面、删除保存的行程以及导航到核心应用程序流程的第一页,该流程允许用户创建新的行程。

在本案例研究中,您将学习以下内容

本案例研究旨在按顺序阅读。任何给定页面都可能引用前面的页面。

本案例研究中的代码示例包含理解架构所需的所有详细信息,但它们不是完整的、可运行的代码片段。如果您希望跟随完整的应用程序,可以在GitHub上找到它。

包结构

#

组织良好的代码更容易让多个工程师协作,最大程度地减少代码冲突,并且更容易让新工程师浏览和理解。代码组织既有利于,也受益于定义良好的架构。

有两种流行的代码组织方式

  1. 按功能 - 将每个功能所需的类组合在一起。例如,您可能有一个auth目录,其中包含auth_viewmodel.dartlogin_usecase.dartlogout_usecase.dart,login_screen.dartlogout_button.dart`等文件。
  2. 按类型 - 将每种“类型”的架构组合在一起。例如,您可能具有repositoriesmodelsservicesviewmodels等目录。

本指南中推荐的架构适合这两种方式的结合。数据层对象(存储库和服务)不绑定到单个功能,而 UI 层对象(视图和视图模型)则绑定。以下是指南针应用程序中代码的组织方式。

lib
|____ui
| |____core
| | |____ui
| | | |____<shared widgets>
| | |____themes
| |____<FEATURE NAME>
| | |____view_model
| | | |_____<view_model class>.dart
| | |____widgets
| | | |____<feature name>_screen.dart
| | | |____<other widgets>
|____domain
| |____models
| | |____<model name>.dart
|____data
| |____repositories
| | |____<repository class>.dart
| |____services
| | |____<service class>.dart
| |____model
| | |____<api model class>.dart
|____config
|____utils
|____routing
|____main_staging.dart
|____main_development.dart
|____main.dart

// The test folder contains unit and widget tests
test
|____data
|____domain
|____ui
|____utils

// The testing folder contains mocks other classes need to execute tests
testing
|____fakes
|____models

大部分应用程序代码位于datadomainui文件夹中。data 文件夹按类型组织代码,因为存储库和服务可以在不同的功能和多个视图模型中使用。ui 文件夹按功能组织代码,因为每个功能都只有一个视图和一个视图模型。

此文件夹结构的其他值得注意的功能

  • UI 文件夹还包含一个名为“core”的子目录。Core 包含多个视图共享的小部件和主题逻辑,例如带有品牌样式的按钮。
  • domain 文件夹包含应用程序数据类型,因为数据层和 ui 层都使用它们。
  • 该应用程序包含三个“主要”文件,它们充当应用程序在开发、登台和生产环境中的不同入口点。
  • 在与lib相同的级别有两个与测试相关的目录:test/包含测试代码,其自身的结构与lib/匹配。testing/是一个子包,包含模拟和其他测试实用程序,这些实用程序可以在其他包的测试代码中使用。testing/文件夹可以描述为您的应用程序的一个版本,您不会发布它。它是测试的内容。

指南针应用程序中还有其他一些与架构无关的代码。有关完整的包结构,请在 GitHub 上查看

其他架构选项

#

本案例研究中的示例演示了一个应用程序如何遵守我们推荐的架构规则,但是可以编写许多其他示例应用程序。此应用程序的 UI 严重依赖视图模型和ChangeNotifier,但它可以轻松地使用流或其他库(例如由riverpodflutter_blocsignals包提供的库)编写。此应用程序层之间的通信使用方法调用处理所有内容,包括轮询新数据。它本可以使用流将数据从存储库公开到视图模型,并且仍然遵守本指南中介绍的规则。

即使您完全遵循本指南,并且选择不引入其他库,您也需要做出决定:您是否会有一个域层?如果是,您将如何管理数据访问?答案在很大程度上取决于各个团队的需求,因此没有一个正确的答案。无论您如何回答这些问题,本指南中的原则都将帮助您编写可扩展的 Flutter 应用程序。

如果您眯着眼睛看,难道所有架构不都是 MVVM 吗?

反馈

#

随着本网站此部分的不断发展,我们欢迎您的反馈