mcpField
F
flutter-apply-architecture-best-practices

flutter-apply-architecture-best-practices

github.com/dhruvanbhalara开发3060 次安装9 周前更新
代码仓库

关于 flutter-apply-architecture-best-practices

flutter-apply-architecture-best-practices 是一项提供 Flutter 与 Dart 实践指导的技能,采用 Clean Architecture 和按功能组织的结构。它规定分层边界、数据模型约定、错误处理方式及新增功能的步骤。

主要功能

  1. 01Clean Architecture 分层边界
  2. 02按功能组织目录结构
  3. 03三层数据模型约定
  4. 04Dart 3 错误处理模式
  5. 05新增功能的分步清单

适用场景

  1. 01规划新的 Flutter 功能结构
  2. 02分离 API、领域和 UI 模型
  3. 03检查数据访问与依赖边界

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dhruvanbhalara/skills --skill flutter-apply-architecture-best-practices

安装后在 Claude Code 中输入/flutter-apply-architecture-best-practices确认已加载。

详细介绍

技术栈

  • 使用 Flutter 进行跨平台开发
  • 使用 Dart 作为主要编程语言
  • 使用 bloc 进行状态管理
  • 使用 injectable 进行依赖注入
  • 使用 Dart Mappable 定义不可变数据模型
  • 使用 Dio 进行 HTTP 网络通信
  • 使用 isar 作为本地数据库
  • 使用 Firebase 提供后端服务

整洁架构

  • 领域层纯净:domain 层必须是纯 Dart。禁止导入 package:flutter。
  • 层级依赖:Presentation -> Domain <- Data。Data 层实现 Domain 接口。
  • 以功能为先 2.0:严格区分 DataSources(外部/原始数据)与 Repositories(领域抽象)。

目录结构

  • 按照基于功能的整洁架构模式组织代码(featureA/bloc、featureA/models、featureA/views)
  • 将跨功能组件放在 core 目录中
  • 在 core/views/widgets 中按类型对共享组件进行分组

三层数据模型模式

  1. API 层(ItemApiModel)

    • 表示从服务器接收的原始数据结构
    • 包含 API 提供的所有字段
    • 应与 API 契约完全一致
  2. 领域层(Item)

    • 表示内部数据模型
    • 仅包含业务逻辑所需的字段
    • 剔除不必要的 API 字段
  3. UI 层(ItemUiState)

    • 表示为 UI 渲染优化的数据模型
    • 包含已解析和格式化、可直接显示的数据
    • 处理所有 UI 特定的转换

数据模型规则

  • 使用 Dart Mappable 定义不可变的 UI 状态
  • 每一层都应有自己的类型定义
  • UI 层应使用 UI 状态数据模型,绝不能直接使用领域模型或 API 模型
  • UI 状态模型应从领域模型派生,而不是从 API 模型派生
  • 领域模型应从 API 模型派生,而不是从 UI 状态模型派生

Repository 与 DataSource 模式

  • Repository 在数据源之间协调(返回领域模型)
  • 数据源访问原始数据(返回 API 模型)
  • Repository 应作为事实来源,并返回领域模型
  • DataSources 必须仅包含原始 SDK/API 调用。不得包含映射或业务逻辑。
  • DataSources 以外不得直接调用后端 SDK/API

数据流

UI Event → BLoC (emit Loading) → Repository → DataSource (API/SDK)
    ↓
Response → Repository (map to Domain Entity) → BLoC (emit Success/Error) → UI

Dart 3 语言特性

  • 密封类:对领域故障使用 sealed class,以便在各层进行穷尽式模式匹配。
  • 记录:在定义完整类显得过于繁琐时,使用记录进行轻量级多值返回(例如 (String name, int age))。
  • If-Case 模式:进行带绑定的空值检查时,优先使用 if (value case final v?),而不是 if (value != null)。
  • 类修饰符:使用 final、interface、base 和 sealed 类修饰符来表达 API 意图。

错误处理

  • 函数式错误处理:使用 Either<Failure, T> 或 Result<T> 密封类。绝不要跨层边界抛出异常。
  • 模式匹配:在 UI 和 BLoC 中使用 Dart 3.x switch 表达式,穷尽处理所有密封类状态。
  • 在需要时抛出错误,并在适当的边界处捕获
  • 在日志中记录错误上下文
  • 在 UI 中向用户显示易于理解的错误消息
  • 避免静默失败;始终处理或传播错误

平台通道与原生集成

  • 使用 MethodChannel 执行一次性原生代码调用(例如读取设备信息、触发原生 API)
  • 使用 EventChannel 接收从原生端到 Flutter 的持续数据流(例如传感器数据、连接状态变化)
  • 将所有通道代码放在相关功能下专用的 platform/ 目录中
  • 将通道名称定义为常量:static const channel = MethodChannel('com.app.feature/method')
  • 将所有通道调用封装在 DataSource 中:绝不要直接从 BLoC 或 UI 调用 MethodChannel
  • 对于未实现该通道的平台,妥善处理 MissingPluginException
  • 使用 defaultTargetPlatform 检查来保护平台特定行为

FFI(外部函数接口)

  • 使用 dart:ffi 处理对性能要求较高的原生 C/C++ 代码
  • 在单独的类中定义绑定,并提供清晰的文档说明
  • 跨多个软件包共享原生代码时,优先使用 Federated Plugins

特定平台的代码

  • 使用 Platform.isAndroid / Platform.isIOS 进行运行时检查(导入 dart:io)
  • 对于 Web,使用 package:flutter/foundation.dart 中的 kIsWeb
  • 尽可能优先使用自适应组件(Switch.adaptive、Slider.adaptive),而不是手动进行平台检查

编码指南与维护

  • 简洁性:文件保持在 300 行以内,函数保持在 50 行以内。每个类的公开方法少于 10 个。
  • 强类型:严格禁止使用 dynamic。请使用 Object? 或显式类型。
  • 守卫子句:使用提前返回(例如,if (user == null) return;)减少嵌套并提升可读性。
  • 可释放对象的生命周期:TextEditingController、ScrollController、FocusNode、StreamSubscription、AnimationController 等,必须在 initState() 中使用 late 初始化,并在 dispose() 中释放。
  • 禁止使用打印语句:严格禁止使用 print()。所有日志记录都使用 AppLogger。
  • 复用:将多次使用的组件或代码块提取到 core/views/widgets 或工具类中。

文档

  • 说明原因,而非内容:注释必须解释设计依据(意图),而非代码的功能。
  • 公开 API:使用三斜线(///)注释为公开类和方法编写文档。
  • 历史记录:不要添加版本历史或“修复者”注释。Git 才是事实来源。

工作流:实现新功能

为应用添加新功能时,请按顺序遵循以下工作流。复制此检查清单以跟踪进度。

任务进度
  • 步骤 1:定义领域模型。 使用 Dart Mappable 为该功能创建不可变数据类。
  • 步骤 2:实现数据源。 创建或更新 DataSource 类,以处理原始 SDK/API 调用(Dio、Isar、Firebase)。
  • 步骤 3:实现仓库。 创建 Repository 以使用数据源并返回纯领域模型。
  • 步骤 4:实现 BLoC/Cubit。 创建状态管理。注入所需的 Repository。公开不可变 UI 状态。
  • 步骤 5:实现 UI。 创建 View 组件。使用 BlocBuilder 或 BlocConsumer 监听状态变化。
  • 步骤 6:注入依赖项。 在依赖注入容器(injectable)中注册新的 DataSource、Repository 和 BLoC。

评论

支持 Markdown