Flutter & Dart Code Reviewer
Улучшите разработку на Flutter с помощью Claude Code. Аудируйте Dart-код на производительность, управление состоянием, безопасность и доступность, используя чек-листы уровня эксперта.
Этот навык предоставляет Claude универсальный, профессиональный чек-лист для аудита кодовых баз Flutter и Dart. Он позволяет агенту выявлять архитектурные недостатки, подводные камни языка Dart (включая современные возможности Dart 3, такие как паттерны и записи), узкие места производительности виджетов и уязвимости безопасности. Независимо от того, используете ли вы BLoC, Riverpod или GetX, этот навык обеспечивает соответствие вашего кода производственным стандартам доступности, тестирования и лучшим практикам для конкретных платформ.
Ключевые особенности
| name | flutter-dart-code-review |
|---|---|
| description | 库无关的Flutter/Dart代码审查清单,涵盖Widget最佳实践、状态管理模式(BLoC、Riverpod、Provider、GetX、MobX、Signals)、Dart惯用法、性能、可访问性、安全性和整洁架构。 |
| origin | ECC |
适用于审查 Flutter/Dart 应用程序的全面、与库无关的清单。无论使用哪种状态管理方案、路由库或依赖注入框架,这些原则都适用。
- 项目遵循一致的文件夹结构(功能优先或分层优先)
- 关注点分离得当:UI、业务逻辑、数据层
- 部件中无业务逻辑;部件纯粹是展示性的
-
pubspec.yaml是干净的 —— 没有未使用的依赖项,版本已适当固定 -
analysis_options.yaml包含严格的 lint 规则集,并启用了严格的分析器设置 - 生产代码中没有
print()语句 —— 使用dart:developerlog()或日志包 - 生成的文件 (
.g.dart,.freezed.dart,.gr.dart) 是最新的或在.gitignore中 - 平台特定代码通过抽象进行隔离
- 隐式动态类型:缺少类型注解导致
dynamic—— 启用strict-casts,strict-inference,strict-raw-types - 空安全误用:过度使用
!(感叹号操作符)而不是适当的空检查或 Dart 3 模式匹配 (if (value case var v?)) - 类型提升失败:在可以使用局部变量类型提升的地方使用了
this.field - 捕获范围过宽:
catch (e)没有on子句;应始终指定异常类型 - 捕获
Error:Error子类型表示错误,不应被捕获 - 未使用的
async:标记为async但从未await的函数 —— 不必要的开销 -
late过度使用:在可使用可空类型或构造函数初始化更安全的地方使用了late;将错误推迟到运行时 - 循环中的字符串拼接:使用
StringBuffer而不是+进行迭代式字符串构建 -
const上下文中的可变状态:const构造器类中的字段不应是可变的 - 忽略
Future返回值:使用await或显式调用unawaited()来表明意图 - 在
final可用时使用var:局部变量首选final,编译时常量首选const - 相对导入:为保持一致性,使用
package:导入 - 暴露可变集合:公共 API 应返回不可修改的视图,而不是原始的
List/Map - 缺少 Dart 3 模式匹配:优先使用 switch 表达式和
if-case,而不是冗长的is检查和手动类型转换 - 为多重返回值使用一次性类:使用 Dart 3 记录
(String, int)代替一次性 DTO - 生产代码中的
print():使用dart:developerlog()或项目的日志包;print()没有日志级别且无法过滤
- 没有单个部件的
build()方法超过约 80-100 行 - 部件按封装方式以及按变化方式(重建边界)进行拆分
- 返回部件的私有
_build*()辅助方法被提取到单独的部件类中(支持元素重用、常量传播和框架优化) - 在不需要可变局部状态的地方,优先使用无状态部件而非有状态部件
- 提取的部件在可复用时放在单独的文件中
- 尽可能使用
const构造器 —— 防止不必要的重建 - 对不变化的集合使用
const字面量 (const [],const {}) - 当所有字段都是 final 时,构造函数声明为
const
- 在列表/网格中使用
ValueKey以在重新排序时保持状态 - 谨慎使用
GlobalKey—— 仅在确实需要跨树访问状态时使用 - 避免在
build()中使用UniqueKey—— 它会强制每帧都重建 - 当身份基于数据对象而非单个值时,使用
ObjectKey
- 颜色来自
Theme.of(context).colorScheme—— 没有硬编码的Colors.red或十六进制值 - 文本样式来自
Theme.of(context).textTheme—— 没有内联的TextStyle和原始字体大小 - 已验证深色模式兼容性 —— 不假设浅色背景
- 间距和尺寸使用一致的设计令牌或常量,而不是魔法数字
-
build()中没有网络调用、文件 I/O 或繁重计算 -
build()中没有Future.then()或async工作 -
build()中没有创建订阅 (.listen()) -
setState()局部化到尽可能小的子树
这些原则适用于所有 Flutter 状态管理方案(BLoC、Riverpod、Provider、GetX、MobX、Signals、ValueNotifier 等)。
- 业务逻辑位于部件层之外 —— 在状态管理组件中(BLoC、Notifier、Controller、Store、ViewModel 等)
- 状态管理器通过依赖注入接收依赖,而不是内部构造它们
- 服务或仓库层抽象数据源 —— 部件和状态管理器不应直接调用 API 或数据库
- 状态管理器职责单一 —— 没有处理不相关职责的“上帝”管理器
- 跨组件依赖遵循解决方案的约定:
- 在 Riverpod 中:提供者通过
ref.watch依赖其他提供者是预期的 —— 仅标记循环或过度复杂的链 - 在 BLoC 中:bloc 不应直接依赖其他 bloc —— 优先使用共享仓库或表示层协调
- 在其他解决方案中:遵循文档中关于组件间通信的约定
- 在 Riverpod 中:提供者通过
- 状态对象是不可变的 —— 通过
copyWith()或构造函数创建新实例,绝不就地修改 - 状态类正确实现
==和hashCode(比较中包含所有字段) - 机制在整个项目中保持一致 —— 手动覆盖、
Equatable、freezed、Dart 记录或其他方式 - 状态对象内部的集合不作为原始可变的
List/Map暴露
- 状态仅通过解决方案的响应式 API 进行修改(MobX 中的
@action,Signals 上的.value,GetX 中的.obs)—— 直接字段修改会绕过变更跟踪 - 派生值使用解决方案的计算机制,而不是冗余存储
- 反应和清理器被正确清理(MobX 中的
ReactionDisposer,Signals 中的 effect 清理)
- 互斥状态使用密封类型、联合变体或解决方案内置的异步状态类型(例如 Riverpod 的
AsyncValue)—— 而不是布尔标志 (isLoading,isError,hasData) - 每个异步操作都将加载、成功和错误建模为不同的状态
- UI 中详尽处理所有状态变体 —— 没有静默忽略的情况
- 错误状态携带用于显示的错误信息;加载状态不携带陈旧数据
- 可空数据不用于作为加载指示器 —— 状态是明确的
// BAD — boolean flag soup allows impossible states
class UserState {
bool isLoading = false;
bool hasError = false; // isLoading && hasError is representable!
User? user;
}
// GOOD (immutable approach) — sealed types make impossible states unrepresentable
sealed class UserState {}
class UserInitial extends UserState {}
class UserLoading extends UserState {}
class UserLoaded extends UserState {
final User user;
const UserLoaded(this.user);
}
class UserError extends UserState {
final String message;
const UserError(this.message);
}
// GOOD (reactive approach) — observable enum + data, mutations via reactivity API
// enum UserStatus { initial, loading, loaded, error }
// Use your solution's observable/signal to wrap status and data separately- 状态消费者部件(Builder、Consumer、Observer、Obx、Watch 等)的范围尽可能窄
- 使用选择器仅在特定字段变化时重建 —— 而不是每次状态发射时
- 使用
const部件来阻止重建在树中传播 - 计算/派生状态是响应式计算的,而不是冗余存储的
- 所有手动订阅 (
.listen()) 在dispose()/close()中被取消 - 流控制器在不再需要时关闭
- 定时器在清理生命周期中被取消
- 优先使用框架管理的生命周期,而不是手动订阅(声明式构建器优于
.listen()) - 异步回调中在
setState之前检查mounted - 在
await之后使用BuildContext而不检查context.mounted(Flutter 3.7+)—— 过时的上下文会导致崩溃 - 在异步间隙后,没有在验证部件仍然挂载的情况下进行导航、显示对话框或脚手架消息
-
BuildContext绝不存储在单例、状态管理器或静态字段中
- 临时 UI 状态(复选框、滑块、动画)使用本地状态 (
setState,ValueNotifier) - 共享状态仅提升到所需的高度 —— 不过度全局化
- 功能作用域的状态在功能不再活跃时被正确清理
- 不在根部件级别调用
setState()—— 将状态变化局部化 - 使用
const部件来阻止重建传播 - 在独立重绘的复杂子树周围使用
RepaintBoundary - 使用
AnimatedBuilder的 child 参数处理独立于动画的子树
- 不在
build()中对大型集合进行排序、过滤或映射 —— 在状态管理层计算 - 不在
build()中编译正则表达式 -
MediaQuery.of(context)的使用是具体的(例如,MediaQuery.sizeOf(context))
- 网络图像使用缓存(适用于项目的任何缓存解决方案)
- 为目标设备使用适当的图像分辨率(不为缩略图加载 4K 图像)
- 使用带有
cacheWidth/cacheHeight的Image.asset以按显示尺寸解码 - 为网络图像提供占位符和错误部件
- 对于大型或动态列表,使用
ListView.builder/GridView.builder代替ListView(children: [...])(对于小型、静态列表,具体构造器是可以的) - 为大型数据集实现分页
- 在 Web 构建中对重量级库使用延迟加载 (
deferred as)
- 在动画中避免使用
Opacity部件 —— 使用AnimatedOpacity或FadeTransition - 在动画中避免裁剪 —— 预裁剪图像
- 不在部件上重写
operator ==—— 使用const构造器代替 - 固有尺寸部件 (
IntrinsicHeight,IntrinsicWidth) 谨慎使用(额外的布局传递)
- 单元测试:覆盖所有业务逻辑(状态管理器、仓库、工具函数)
- 部件测试:覆盖单个部件的行为、交互和视觉输出
- 集成测试:端到端覆盖关键用户流程
- Golden 测试:对设计关键的 UI 组件进行像素级精确比较
- 业务逻辑的目标行覆盖率达到 80% 以上
- 所有状态转换都有对应的测试(加载 → 成功,加载 → 错误,重试等)
- 测试边缘情况:空状态、错误状态、加载状态、边界值
- 外部依赖(API 客户端、数据库、服务)已被模拟或伪造
- 每个测试文件仅测试一个类/单元
- 测试验证行为,而非实现细节
- 存根仅定义每个测试所需的行为(最小化存根)
- 测试用例之间没有共享的可变状态
-
pumpWidget和pump被正确用于异步操作 -
find.byType、find.text、find.byKey使用得当 - 没有依赖于时序的不可靠测试——使用
pumpAndSettle或显式的pump(Duration) - 测试在 CI 中运行,失败会阻止合并
- 使用
Semantics小部件在自动标签不足时提供屏幕阅读器标签 - 使用
ExcludeSemantics处理纯装饰性元素 - 使用
MergeSemantics将相关小部件组合成单个可访问元素 - 图像设置了
semanticLabel属性
- 所有交互元素均可聚焦并具有有意义的描述
- 焦点顺序符合逻辑(遵循视觉阅读顺序)
- 文本与背景的对比度 >= 4.5:1
- 可点击目标至少为 48x48 像素
- 颜色不是状态的唯一指示器(同时使用图标/文本)
- 文本随系统字体大小设置缩放
- 没有无操作的
onPressed回调——每个按钮都有作用或处于禁用状态 - 错误字段建议更正
- 用户输入数据时,上下文不会意外改变
- 在适当的地方使用平台自适应小部件
- 返回导航处理正确(Android 返回按钮,iOS 滑动返回)
- 通过
SafeArea小部件处理状态栏和安全区域 - 平台特定权限在
AndroidManifest.xml和Info.plist中声明
- 使用
LayoutBuilder或MediaQuery实现响应式布局 - 断点定义一致(手机、平板、桌面)
- 文本在小屏幕上不会溢出——使用
Flexible、Expanded、FittedBox - 测试了横屏方向或明确锁定
- Web 特定:支持鼠标/键盘交互,存在悬停状态
- 敏感数据(令牌、凭证)使用平台安全存储存储(iOS 上的 Keychain,Android 上的 EncryptedSharedPreferences)
- 从不以明文存储机密信息
- 对于敏感操作考虑使用生物识别认证门控
- API 密钥 NOT 硬编码在 Dart 源代码中——使用
--dart-define,.env文件从 VCS 中排除,或使用编译时配置 - 机密信息未提交到 git——检查
.gitignore - 对真正的秘密密钥使用后端代理(客户端不应持有服务器机密)
- 所有用户输入在发送到 API 前都经过验证
- 表单验证使用适当的验证模式
- 没有原始 SQL 或用户输入的字符串插值
- 深度链接 URL 在导航前经过验证和清理
- 所有 API 调用强制使用 HTTPS
- 对于高安全性应用考虑证书锁定
- 认证令牌正确刷新和过期
- 没有记录或打印敏感数据
- 检查 pub 分数(目标 130+/160)
- 检查 点赞数和流行度作为社区信号
- 验证发布者在 pub.dev 上已验证
- 检查最后发布日期——过时的包(>1 年)有风险
- 审查维护者的未解决问题和响应时间
- 检查许可证与项目的兼容性
- 验证平台支持是否覆盖您的目标
- 对依赖项使用插入符语法(
^1.2.3)——允许兼容性更新 - 仅在绝对必要时固定确切版本
- 定期运行
flutter pub outdated以跟踪过时的依赖项 - 生产
pubspec.yaml中没有依赖项覆盖——仅用于带有注释/问题链接的临时修复 - 最小化传递依赖项数量——每个依赖项都是一个攻击面
- 内部包仅从公共 API 导入——没有
package:other/src/internal.dart(破坏 Dart 包封装) - 内部包依赖项使用工作区解���,而不是硬编码的
path: ../../相对字符串 - 所有子包共享或继承根
analysis_options.yaml
- 一致使用一种路由方法——不混合命令式
Navigator.push和声明式路由器 - 路由参数是类型化的——没有
Map<String, dynamic>或Object?转换 - 路由路径定义为常量、枚举或生成——没有散布在代码中的魔法字符串
- 认证守卫/重定向集中化——不在各个屏幕中重复
- 为 Android 和 iOS 配置深度链接
- 深度链接 URL 在导航前经过验证和清理
- 导航状态是可测试的——可以在测试中验证路由更改
- 在所有平台上返回行为正确
- 重写
FlutterError.onError以捕获框架错误(构建、布局、绘制) - 设置
PlatformDispatcher.instance.onError处理 Flutter 未捕获的异步错误 - 为发布模式自定义
ErrorWidget.builder(用户友好而非红屏) - 在
runApp周围使用全局错误捕获包装器(例如runZonedGuarded,Sentry/Crashlytics 包装器)
- 集成了错误报告服务(Firebase Crashlytics、Sentry 或等效服务)
- 报告非致命错误并附上堆栈跟踪
- 状态管理错误观察器连接到错误报告(例如,BlocObserver、ProviderObserver 或适用于您解决方���的等效项)
- 为调试目的,将用户可识别信息(用户 ID)附加到错误报告
- API 错误导致用户友好的错误 UI,而非崩溃
- 针对瞬时网络故障的重试机制
- 优雅处理离线状态
- 状态管理中的错误状态携带用于显示的错误信息
- 原始异常(网络、解析)在到达 UI 之前被映射为用户友好的本地化消息——从不向用户显示原始异常字符串
- 配置了本地化解决方案���Flutter 内置的 ARB/l10n、easy_localization 或等效方案)
- 在应用配置中声明了支持的语言环境
- 所有用户可见字符串都使用本地化系统——小部件中没有硬编码字符串
- 模板文件包含翻译人员的描述/上下文
- 使用 ICU 消息语法处理复数、性别、选择
- 使用类型定义占位符
- 跨语言环境没有缺失的键
- 在整个项目中一致使用本地化访问器
- 日期、时间、数字和货币格式化具有语言环境感知能力
- 如果目标语言是阿拉伯语、希伯来语等,则支持文本方向性(RTL)
- 本地化文本没有字符串拼接——使用参数化消息
- 类在层边界上依赖于抽象(接口),而不是具体实现
- 依赖项通过构造函数、DI 框架或提供者图从外部提供——而非内部创建
- 注册区分生命周期:单例 vs 工厂 vs 惰性单例
- 环境特定绑定(开发/暂存/生产)使用配置,而非运行时
if检查 - DI 图中没有循环依赖
- 服务定位器调用(如果使用)没有散布在业务逻辑中
- 存在
analysis_options.yaml并启用了严格设置 - 严格的分析器设置:
strict-casts: true、strict-inference: true、strict-raw-types: true - 包含全面的 lint 规则集(very_good_analysis、flutter_lints 或自定义严格规则)
- 单仓库中的所有子包继承或共享根��析选项
- 提交的代码中没有未解决的分析器警告
- lint 抑制(
// ignore:)有注释说明原因 -
flutter analyze在 CI 中运行,失败会阻止合并
-
prefer_const_constructors——小部件树中的性能 -
avoid_print——使用适当的日志记录 -
unawaited_futures——防止即发即弃的异步错误 -
prefer_final_locals——变量级别的不可变性 -
always_declare_return_types——明确的契约 -
avoid_catches_without_on_clauses——具体的错误处理 -
always_use_package_imports——一致的导入风格
下表将通用原则映射到流行解决方案中的实现。使用此表将审查规则调整为项目使用的任何解决方案。
| 原则 | BLoC/Cubit | Riverpod | Provider | GetX | MobX | Signals | 内置 |
|---|---|---|---|---|---|---|---|
| 状态容器 | Bloc/Cubit |
Notifier/AsyncNotifier |
ChangeNotifier |
GetxController |
Store |
signal() |
StatefulWidget |
| UI 消费者 | BlocBuilder |
ConsumerWidget |
Consumer |
Obx/GetBuilder |
Observer |
Watch |
setState |
| 选择器 | BlocSelector/buildWhen |
ref.watch(p.select(...)) |
Selector |
N/A | computed | computed() |
N/A |
| 副作用 | BlocListener |
ref.listen |
Consumer 回调 |
ever()/once() |
reaction |
effect() |
回调 |
| 处置 | 通过 BlocProvider 自动 |
.autoDispose |
通过 Provider 自动 |
onClose() |
ReactionDisposer |
手动 | dispose() |
| 测试 | blocTest() |
ProviderContainer |
直接 ChangeNotifier |
在测试中 Get.put |
直接测试 store | 直接测试 signal | 小部件测试 |
🧐 Что это
Это Flutter & Dart Code Reviewer — исчерпывающий, не зависящий от библиотек чек-лист для код-ревью Flutter/Dart-приложений. Он охватывает все ключевые аспекты: от архитектуры и виджетов до производительности, безопасности и тестирования. Чек-лист универсален и подходит для проектов с любым стеком — будь то BLoC, Riverpod, Provider, GetX, MobX или Signals.
⚙️ Как работает
Чек-лист структурирован по 15 разделам, каждый из которых содержит конкретные, проверяемые правила. Ниже — ключевые разделы с пояснениями.
📁 Общее здоровье проекта
Проверяется, что проект имеет чистую архитектуру: разделение на UI, бизнес-логику и данные. В pubspec.yaml не должно быть мусора, а analysis_options.yaml — включать строгие настройки анализатора (strict-casts, strict-inference, strict-raw-types). Запрещены print() в продакшене — используйте dart:developer log().
🎯 Опасные места в Dart
Раздел посвящён типичным ошибкам языка:
- Неявный
dynamic— отсутствие аннотаций типов. Включайте строгие проверки. - Злоупотребление
!— вместо него используйте паттерн-матчинг Dart 3:if (value case var v?). - Ненужный
async— функция помеченаasync, но не содержитawait. - Строковая конкатенация в цикле — используйте
StringBuffer. - Игнорирование
Future— всегдаawaitили явно вызывайтеunawaited(). - Относительные импорты — предпочитайте
package:. - Отсутствие Dart 3 фич — используйте
switch-выражения и записи (records) вместо одноразовых DTO.
🧩 Лучшие практики виджетов
- Декомпозиция:
build()не длиннее 80–100 строк. Вспомогательные_build*методы выносите в отдельные классы виджетов — это улучшает переиспользование и оптимизацию фреймворка. constвезде: конструкторы, коллекции (const []), если поляfinal.- Ключи (
Key):ValueKeyдля списков,ObjectKeyдля объектов, избегайтеUniqueKeyвbuild(). - Тема: цвета и текстовые стили только из
Theme.of(context), никаких хардкодов. - Сложность
build(): никаких сетевых вызовов, файлового I/O или подписок (listen()).
🗂️ Управление состоянием (независимо от библиотеки)
Этот раздел — ядро чек-листа. Он учит правильно проектировать состояние, независимо от выбранного решения.
Архитектура
- Бизнес-логика — вне виджетов, в стейт-менеджере (BLoC, Notifier, Controller и т.д.).
- Стейт-менеджер получает зависимости через DI, а не создаёт их сам.
- Сервисы и репозитории абстрагируют источники данных.
- Один стейт-менеджер — одна ответственность.
Неизменяемость и равенство
- Состояние — неизменяемые объекты с
copyWith(). Реализуйте==иhashCode(вручную, черезEquatable,freezedили записи Dart). - Коллекции не должны быть сырыми
List/Map.
Реактивная дисциплина
- Изменяйте состояние только через реактивное API (
@action,.value,.obs). - Производные значения — через вычисляемые свойства, а не дублирование.
- Очищайте реакции и эффекты.
Дизайн состояния
- Взаимоисключающие состояния — через sealed-классы или встроенные типы (например,
AsyncValue). Никаких флаговisLoading,isError. - Каждая асинхронная операция моделирует три состояния: загрузка, успех, ошибка.
- Ошибка содержит сообщение для UI.
Пример правильного подхода:
// ПЛОХО — флаги допускают невозможные состояния
class UserState {
bool isLoading = false;
bool hasError = false;
User? user;
}
// ХОРОШО — sealed-классы исключают невозможные состояния
sealed class UserState {}
class UserInitial extends UserState {}
class UserLoading extends UserState {}
class UserLoaded extends UserState {
final User user;
const UserLoaded(this.user);
}
class UserError extends UserState {
final String message;
const UserError(this.message);
}
Оптимизация перестроений
- Сужайте область видимости Consumer/Builder/Obx.
- Используйте селекторы (
ref.watch(p.select(...))), чтобы перестраиваться только при изменении нужного поля. const-виджеты блокируют распространение перестроений.
Подписки и очистка
- Все ручные подписки (
listen()) отменяйте вdispose()/close(). - Закрывайте StreamController.
- Проверяйте
mountedпередsetStateпосле асинхронной операции (Flutter 3.7+ —context.mounted). - Никогда не храните
BuildContextв синглтонах или стейт-менеджерах.
Локальное vs глобальное состояние
- Временное UI-состояние (чекбоксы, анимации) — локально (
setState,ValueNotifier). - Общее состояние поднимайте ровно настолько, насколько нужно.
🚀 Производительность
- Избегайте лишних перестроений: не вызывайте
setState()на корне, используйтеRepaintBoundaryиAnimatedBuilderсchild. - Тяжёлые операции не в
build(): сортировку, фильтрацию, компиляцию regex — выносите в слой управления состоянием. - Изображения: кэшируйте сетевые, используйте
cacheWidth/cacheHeightдляImage.asset, давайте плейсхолдеры. - Ленивая загрузка:
ListView.builderдля больших списков, пагинация,deferred asдля тяжёлых библиотек на Web. - Избегайте
Opacityи клиппинга в анимациях — используйтеAnimatedOpacityилиFadeTransition.
🧪 Тестирование
- Unit-тесты покрывают бизнес-логику (стейт-менеджеры, репозитории).
- Widget-тесты проверяют поведение и взаимодействие.
- Integration-тесты — end-to-end сценарии.
- Golden-тесты — для критичных UI-компонентов.
- Цель: >80% покрытия бизнес-логики, все состояния (загрузка, успех, ошибка, пусто).
- Мокируйте внешние зависимости, тестируйте поведение, а не реализацию.
♿ Доступность
- Используйте
Semantics,ExcludeSemantics,MergeSemantics. - Все интерактивные элементы должны быть фокусируемыми и иметь описание.
- Контраст текста >= 4.5:1, цель клика >= 48x48 px.
- Цвет — не единственный индикатор состояния.
📱 Платформенные особенности
- Используйте платформо-адаптивные виджеты, обрабатывайте кнопку «Назад» на Android и свайп на iOS.
SafeAreaдля статус-бара.- Адаптивная вёрстка через
LayoutBuilder/MediaQuery, консистентные брейкпоинты. - На Web — поддержка мыши/клавиатуры и hover-состояний.
🔒 Безопасность
- Храните токены и пароли в безопасном хранилище (Keychain/EncryptedSharedPreferences).
- API-ключи — через
--dart-defineили.env, исключённый из VCS. - Валидируйте пользовательский ввод перед отправкой на сервер.
- Все API-вызовы — только HTTPS.
📦 Зависимости
- Оценивайте пакеты на pub.dev: скоринг, лайки, дата последнего обновления, лицензия.
- Используйте caret-синтаксис (
^1.2.3), фиксируйте версии только при крайней необходимости. - Регулярно запускайте
flutter pub outdated. - В монорепозиториях (melos): импортируйте только из публичного API, используйте workspace-ссылки.
🧭 Навигация
- Единый подход (или декларативный Router, или императивный
Navigator.push). - Типизированные аргументы маршрутов, константы для путей.
- Централизованные guard'ы аутентификации.
- Настройте deep links.
❌ Обработка ошибок
- Переопределите
FlutterError.onErrorиPlatformDispatcher.instance.onError. - Используйте сервисы вроде Sentry/Crashlytics.
- Ошибки API отображайте как понятный UI, а не сырой exception.
- Маппите исключения в пользовательские сообщения.
🌐 Интернационализация (l10n)
- Все строки — через систему локализации (ARB, easy_localization).
- Используйте ICU MessageFormat для плюрализации и выбора.
- Поддерживайте RTL для арабского/иврита.
💉 Dependency Injection
- Зависимости — через абстракции (интерфейсы).
- Внедряйте через конструктор или DI-фреймворк.
- Различайте Singleton, Factory, LazySingleton.
- Никаких циклических зависимостей.
🔍 Статический анализ
analysis_options.yamlсо строгими правилами.- Включите
very_good_analysisилиflutter_lints. - Ключевые правила:
prefer_const_constructors,avoid_print,unawaited_futures,prefer_final_locals,always_declare_return_types,avoid_catches_without_on_clauses,always_use_package_imports. - CI должен запускать
flutter analyzeи блокировать мерж при ошибках.
🎯 Когда использовать
Этот чек-лист — ваш must-have для код-ревью любого Flutter-проекта. Используйте его:
- На каждом ревью — пройдитесь по пунктам, чтобы не пропустить типовые проблемы.
- При онбординге новых разработчиков — как шпаргалку по стандартам команды.
- При аудите существующего проекта — чтобы выявить узкие места и технический долг.
- При выборе стейт-менеджера — сверьтесь с разделом «Управление состоянием».
💡 Важно знать
- Чек-лист не зависит от библиотек — правила применимы к BLoC, Riverpod, Provider, GetX, MobX, Signals и даже к простому
setState. - В конце документа есть таблица соответствия принципов конкретным реализациям — очень удобно для быстрой сверки.
- Не пытайтесь внедрить все правила сразу. Начните с критических: архитектура, безопасность, производительность.
- Регулярно обновляйте чек-лист под новые версии Flutter и Dart — язык и фреймворк активно развиваются.
Какие библиотеки управления состоянием поддерживает этот навык?
Навык не зависит от библиотек, то есть применяет универсальные принципы, применимые к BLoC, Riverpod, Provider, GetX, MobX, Signals и другим.
Даёт ли он рекомендации по тестированию?
Да, он включает всесторонний чеклист для модульного, виджет-, интеграционного и golden-тестирования, чтобы обеспечить высокое покрытие кода и надёжность.
Помогает ли этот навык с миграцией на Dart 3?
Да, он специально проверяет использование функций Dart 3, таких как records, pattern matching и sealed classes, чтобы код был современным и идиоматичным.
Как обрабатывается безопасность при проверке кода?
Навык включает проверки на наличие хардкодных API-ключей, небезопасного локального хранилища и гарантирует, что конфиденциальные данные обрабатываются с использованием платформенно-безопасных решений для хранения.
Может ли он выявить проблемы с производительностью в дереве виджетов?
Безусловно. Он ищет дорогостоящие операции в методах build, ненужные перестроения и даёт рекомендации по использованию const-конструкторов и RepaintBoundary.
Синхронизируйте навыки с Claude Cowork, Claude Code, Codex и другими.
Установка одной командой.
npx skillfish add affaan-m/everything-claude-code flutter-dart-code-reviewИсточник: https://mcpmarket.com/tools/skills/flutter-dart-code-reviewer
Комментарии
Комментариев пока нет. Будьте первым.