flutter - Flutter 中的 Clean Architecture 在哪里执行状态更改?
问题描述
当使用带有 Flutter 的 Clean Architecture 时,我们会看到类似这样的图表:
(我写了 MobX 包作为示例,但它可以是 BLoC、Redux 之类的任何东西......)
我可能对此图有疑问,因为 Store 位于表示层并负责更改状态。
想象一下,该应用程序通过 TodosStore 中名为“getTodos”implementend 的方法加载了一个待办事项列表。“getTodos”实现可能是:
_state = State.loading();
final result = GetTodos();
_state = State.done();
(我把事情过于简单化了)
它首先将状态更新为加载,调用返回列表的用例并将状态设置为完成。
我在这里发现的问题:
- Stores负责调用UC、更新状态、处理错误……
- 用例只是一个桥梁,不处理业务逻辑
这是一个相当简单的例子。但是让我们想象一下,我有一个包含 3 个不同数据列表的视图(这可能是一个荒谬的例子)。该视图与 3 个不同的商店交互。应用栏中有一个按钮。它的目标是清除 3 个列表。
如何实现这种行为?
- 按钮 onPressed 方法将需要为每个商店调用“clearData”
- 每个商店的“清除”方法将简单地更新其属性
问题是视图并不像我们想要的那样愚蠢。商店甚至没有与任何用例进行交互
ClearLists 用例在这里应该合法吗?
由于我不喜欢在表示层中有太多逻辑,所以我倾向于遵循这张图:
每个视图都有自己的 ViewModel。VM 只是与用例交互。这些 UC 可能会也可能不会返回值。例如:我的 UC 是 ValidateNumberRange,我可能不会与商店交互。返回一个布尔值是有意义的。但如果我的 UC 是 ClearTodoList,它可能会与商店交互。成功或失败可以是一个存储值。这样返回值可能没有用。
使用这个新图表,“GetTodos”用例可调用方法实现可能是:
store.set(State.loading());
final result = repo.getTodos();
result.fold(
(failureMsg) { store.set(State.failure(failureMsg)); },
(newList) { store.set(State.done(newList)); },
);
- 用例处理状态管理逻辑
- View 调用一个 VM 方法。VM 调用 UC 并观察 Store 中的变化(此处通过 MobX)
我问自己很多问题:
- 我是否正确理解了 UC 在干净架构中的作用?
- 改变状态(加载、完成、失败)是否考虑了业务逻辑?
- 您会将状态管理解决方案放在您的应用程序的什么位置?
我期待听到你的想法
解决方案
用例封装了业务规则,它们与平台无关,与交付机制无关(例如 UI)。用例基于功能,但没有实现细节。书: https ://dannorth.net/introducing-bdd
改变状态是表示层的责任;表示层!= UI 层
像这样思考:
Domain Layer <= infrastructure layer <= application layer <= presentation layer <= UI Layer
依赖关系总是应该向内的。想象一下:无副作用的业务逻辑(功能核心)始终位于中心,其余的(有状态元素、UI、框架)围绕它。
从您的图表中:AppState 和 ViewModel 始终驻留在表示层中。Flutter 特定的类属于 UI。
推荐阅读
- internationalization - 如何使用 Hugo 和 NetlifyCMS 管理国际化
- javascript - 从 XML 标记中获取文本时如何删除空格?
- python - 我在 ubuntu18.04 上执行了 Python 2,但没有导入“tkinter”
- webpack - webpack - 奇怪的控制台消息(提供输出,404 将回退,提供不是来自 webpack 的内容......等等)
- ios - UIImagePicker 在 Objective c 和 Swift 中给出错误的裁剪图像
- email - 带有气流的电子邮件
- php - Codeigniter facebook 身份验证问题
- compiler-construction - C 编译器如何提供对多个内存的访问?
- typescript - 类型保护过滤后从回调中访问类成员
- c++ - 在 std::pair 的 std::vector 中查找最小值和最大值