Flutter实践一:package组织
1.架构概览
为了降低Flutter工程里lib的复杂度,应尽量拆分一些代码成为独立的package。如图:

我们将通用的组件、领域模型、API、features、存储、repository等抽取成了单独的package。这时lib只剩下多国语言、基本的页面、路由等代码了:

这样做的好处是:
1.更细粒度的依赖控制。因为每个package有一个单独的pubspec.yaml文件,你无需在主package的pubspec.yaml中添加需要的全部依赖。
2.更清晰的边界。你的团队需要审慎对待应该公开哪些类和函数的问题。
3.更容易避免代码冲突。
4.当修改单个package时,只需要更短的集成测试时间。
2.package管理
接下去的问题是如何组织packages文件夹。常见的package划分策略是按层划分和按功能划分。在不使用package或者不支持package的情况下,可以将package视作文件夹。
2.1按层(layer)划分
按层划分意味着根据代码使用的技术因素来划分代码。例如,数据库相关代码是一个package,网络请求相关代码是一个package,widget在另一个package中。package的层次结构如图所示:

优势:
1.按层划分package符合我们的思维习惯,因此具有更低的学习曲线。
2.按层划分package鼓励代码重用。代码文件属于某一层,而不是某个功能时,你可以不经思考地使用某个组件,尽管它最初可能是为另一个功能开发的。
3.不同的项目最后可能会拥有类似、甚至相同的结构。
劣势:
1.按层划分结构不会立即传达有关应用的最有趣的信息。在浏览代码库时,您不太可能想知道它是否有页面文件,而想知道它具有哪些功能。
2.一切都是公开的。例如,每个页面文件都可以导入所有状态管理器文件,即使大多数页面使用单个状态管理器也是如此。这使得粗心的开发人员更容易导入他们不应该导入的文件。
3.开发人员必须不断地在文件树中跳来跳去。当经常一起更改的文件存储在不同的位置(例如页面和状态管理器)时,就会发生这种情况。这与《干净的代码》一书的著名作者罗伯特·塞西尔·马丁(Robert Cecil Martin)教导我们的单一责任原则背道而驰:“将出于相同原因而变化的事物聚集在一起。”
4.它不能很好地扩展。随着项目中文件数量的增加,包的数量保持不变。无论您的项目有 5 个页面还是 50 个页面,您仍然只有一个 ui 包。
5.这使得新团队成员的加入变得困难。您要么知道所有功能的工作原理,要么不知道任何功能的工作原理---没有中间地带。你觉得你必须了解一切才能参与工作。
2.2按功能(feature)划分
按功能划分就是根据代码的领域关联性对代码进行分组。譬如,ui包下的quote_list_screen.dart和state_managers包下的quote_list_bloc.dart可以都放在quote_list包中。package的层次结构如图所示:

优势:
1.使用按功能划分的方法,查找文件变得轻而易举。代码库的结构反映了应用的设计。
2.扩展性很好。随着文件数量的增加,包的数量也会相应增加。
3.代码库变为自文档化。应用程序的大小及其功能一目了然。
4.可以完全控制可见性。例如,现在 quote_list_bloc.dart 只能在 quote_list 包内可见。
5.为新成员提供更顺畅的开始。你只需要了解你正在使用的功能。
6.可以获得更清晰的小组所有权。每个子团队都确切地知道它负责哪些包。
7.进行试验和迁移很容易。想要尝试一种新的状态管理方法?没关系。将其限制在单个功能包中,其他人不必为此担心。
劣势:
1.它助长了创建所谓的common package,也就是开发者用于存放被多个功能所使用的代码的包。这在理论上似乎看起来不错。但是在实践中common package变成了一个巨大的垃圾箱,里面的文件彼此完全无关。
2.代码重复的风险更高。如果你需要一些已经在另一个功能中实现的东西,那么你有可能要么不知道它,要么不想承担将其移动到common package的重任,所以你选择创建了另一个版本。
3.在决定将文件放置在哪里时,它需要一定的心智负担。“它应该在那个包里吗?我应该为它创建另一个包吗?它应该在公共内部吗?“
2.3混合划分
如你所见,这两种方法都有优点和缺点。按层划分最适合与单个功能无关的文件,例如数据库和网络内容。相比之下,对于很少重用的文件(如页面和状态管理器),按功能划分则大放异彩。那么,为什么不将两者混合使用,并在你觉得需要时创建包呢?package的层次结构如图所示:

注意到有些包是基于功能的,例如quote_list,quote_details和sign_in。相比之下,上面展示的其他包都是基于分层的,例如key_value_storage和component_library。
以下是管理包分发的四条戒条:
1.feature有它们各自的包
何为feature?对于一些人,一个feature就是一个screen(页面)。对于其他人,一个feature是一组相关联的页面。此外,正式定义会告诉您一个页面可以汇集许多功能,例如主页面。同时,一项功能可以跨越不同的页面,例如电商结账流程。听起来很复杂,对吧?幸运的是,你不必那么教条主义。在这里,您可以认为功能是:
1.一个页面
2.一个执行网络或者数据库I/O调用的对话框。
除此之外,如果它只是一个虚拟的 UI 组件,你想在两个或多个页面之间共享,比如搜索栏,你应该把它放在component_library包。
2.feature彼此之间不了解
当页面 A 想要打开页面 B 时,它不会导入页面 B 并直接导航到它。相反,页面 A 的构造函数接收一个函数,当它想要打开页面 B 时,它可以调用该函数。最后,主应用程序包将连接这个过程。
3.repository有它们各自的包
存储库(repository)是负责通过协调不同的来源(如网络和数据库)来获取和发送数据的类。
4.没有common package
当您需要在两个或多个包之间共享某些内容时,您将创建一个更专用的包来处理该问题。您的五个包源自此规则:
component_library:保存正在或有可能跨不同页面重用的 UI 组件。
fav_qs_api:由于user_repository和quote_repository都跟远程quote API通信,为其单独创建一个包是有意义的。
key_value_storage:和fav_qs_api类似,但是它封装了本地存储功能。
domain_models:你可以预期存储库将需要在某个时候开始共享模型或自定义异常。因此,从一开始就为您的域模型提供单独的包是一件好事。
form_fields:包含不同功能共享的字段验证逻辑
参考:
《Real-World Flutter by Tutorials》
相关文章:
Flutter实践一:package组织
1.架构概览 为了降低Flutter工程里lib的复杂度,应尽量拆分一些代码成为独立的package。如图: 我们将通用的组件、领域模型、API、features、存储、repository等抽取成了单独的package。这时lib只剩下多国语言、基本的页面、路由等代码了: 这…...
SpringCloud微服务:Ribbon负载均衡
目录 负载均衡策略: 负载均衡的两种方式: 饥饿加载 1. Ribbon负载均衡规则 规则接口是IRule 默认实现是ZoneAvoidanceRule,根据zone选择服务列表,然后轮询 2.负载均衡自定义方式 代码方式:配置灵活,但修…...
【教程】大气化学在线耦合模式WRF/Chem
查看原文>>>区域气象-大气化学在线耦合模式(WRF/Chem)在大气环境领域实践 随着我国经济快速发展,我国面临着日益严重的大气污染问题。近年来,严重的大气污染问题已经明显影响国计民生,引起政府、学界和人们越…...
GDS 命令的使用 srvctl service TAF application continuity
文档中prim and stdy在同一台机器上,不同机器需要添加address list TAF ENABLED GLOBAL SERVICE in GDS ENVIRONMNET 12C. (Doc ID 2283193.1)编辑To Bottom In this Document Goal Solution APPLIES TO: Oracle Database - Enterprise Edition - Version 12.1.…...
go 语言之 select
在 Go 语言中,select 是一种用于处理多个通道操作的控制结构。它可以用于在多个通道之间进行非阻塞的选择操作,从而实现并发控制和通信。 select 语句的基本语法如下: go select { case <-channel1:// 当 channel1 可读时执行的代码 cas…...
23款奔驰GLC260L升级小柏林音响 全新15个扬声器
2023年款奔驰GLC260 GLC300升级小柏林之声 3D音效系统 升级小柏林之声音响之后,全车一共有15个喇叭,1台功放,每一首音乐都能在车内掀起激情的音浪,感受纯粹的音乐享受,低频震撼澎湃,让你的心跳与音乐完美契…...
ssh 免密码登录
ssh 免密码登录 1. 原理 1.1 密码登录的通俗解释 把服务器当作一个凤凰社,每次进社公干都需要拿特别的门票入场,门票便是服务器上的账户密码; 1.2 免密登录 对于凤凰社的高级会员,会在社内存储一张高级会员身份(id_rsa…...
小程序使用腾讯位置插件获取当前位置
1.小程序后台 设置-第三方设置-插件管理-添加插件 2.进入网站 腾讯位置服务 设置对应的额度 mapPickerPlugin(res) {const key ""; //使用在腾讯位置服务申请的keyconst referer "铅锂运营"; //调用插件的app的名称const category "生活服务,娱…...
零基础学Python怎么学习?我来告诉你
对于IT新手来说,零基础学Python的话,之后可选择的职业方向非常多。Python全栈和爬虫一直以来都是市场的最火的就业岗位之一,它们的薪资回报也算是开发岗里面的顶级了。而且随着大数据和人工智能时代的到来,数据处理和人工智能行业…...
开源软件 FFmpeg 生成模型使用图片数据集
本篇文章聊聊,成就了无数视频软件公司、无数在线视频网站、无数 CDN 云服务厂商的开源软件 ffmpeg。 分享下如何使用它将各种视频或电影文件,转换成上万张图片数据集、壁纸集合,来让下一篇文章中的模型程序“有米下锅”,这个方法…...
Linux Shell 通配符 / glob 模式
1、概念 glob 模式(globbing)也被称之为 shell 通配符,名字的起源来自于 Unix V6 中的 /etc/glob (详见 man 文档)。glob 是一种特殊的模式匹配,最常见的是通配符拓展,也可以将 glob 模式设为精…...
深入了解域名与SSL证书的关系
在如今数字化的世界里,网络安全成为我们关注的重要议题之一。为了确保数据在网络上传输的安全性,我们通常会采取各种安全措施,其中最常用的就是SSL证书。然而,很多人并不了解SSL证书是如何与域名相互关联的。 首先,我…...
计算属性与watch的区别,fetch与axios在vue中的异步请求,单文本组件使用,使用vite创建vue项目,组件的使用方法
7.计算属性 7-1计算属性-有缓存 模板中的表达式虽然很方便,但是只能做简单的逻辑操作,如果在模版中写太多的js逻辑,会使得模板过于臃肿,不利于维护,因此我们推荐使用计算属性来解决复杂的逻辑 <!DOCTYPE html> <html lang"en"> <head><meta …...
2023.11.14 hivesql的容器,数组与映射
目录 https://blog.csdn.net/m0_49956154/article/details/134365327?spm1001.2014.3001.5501https://blog.csdn.net/m0_49956154/article/details/134365327?spm1001.2014.3001.5501 8.hive的复杂类型 9.array类型: 又叫数组类型,存储同类型的单数据的集合 10.struct类型…...
Android Glide照片宫格RecyclerView,点击SharedElement共享元素动画查看大图,Kotlin(1)
Android Glide照片宫格RecyclerView,点击SharedElement共享元素动画查看大图,Kotlin(1) <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name"an…...
SELinux零知识学习八、SELinux策略语言之客体类别和许可(2)
接前一篇文章:SELinux零知识学习七、SELinux策略语言之客体类别和许可(1) 一、SELinux策略语言之客体类别和许可 2. 在SELinux策略中定义客体类别 SELinux策略中必须包括所有SELinux内核支持的客体类别和许可的声明,以及其它客体…...
deepstream-测试发送AMQP
1. 安装库 * glib 2.0 ---------- sudo apt-get install libglib2.0 libglib2.0-dev Install rabbitmq-c library -------------------------- sudo apt-get install librabbitmq-dev If you plan to have AMQP broker installed on your local machine ------------------…...
LLMs可以遵循简单的规则吗?
由于大型语言模型在现实世界中的责任越来越大,因此如何以可靠的方式指定和约束这些系统的行为很重要。一些开发人员希望为模型设置显式规则,例如“不生成滥用内容”,但这种方式可能会被特殊技术规避。评估LLM在面对对抗性输入时遵循开发人员提…...
如何挑选护眼灯?光照均匀度、色温、眩光这3点!
光照环境对我们的生活质量影响深远,尤其在孩子的成长过程中,良好的光照环境对其学习效率、视力保护都至关重要。光照中的很多因素都对视力有着或大或小的影响,本文将从光照均匀度、眩光、色温三个关键点,深入浅出地让消费者了解其…...
python 实验7
姓名:轨迹 学号:6666 专业年级:2021级软件工程 班级: 66 实验的准备阶段 (指导教师填写) 课程名称 Python开发与应用 实验名称 文件异常应用 实验目的 (1)掌握基本文件读写的方式; …...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
02-性能方案设计
需求分析与测试设计 根据具体的性能测试需求,确定测试类型,以及压测的模块(web/mysql/redis/系统整体)前期要与相关人员充分沟通,初步确定压测方案及具体的性能指标QA完成性能测试设计后,需产出测试方案文档发送邮件到项目组&…...
LINUX编译vlc
下载 VideoLAN / VLC GitLab 选择最新的发布版本 准备 sudo apt install -y xcb bison sudo apt install -y autopoint sudo apt install -y autoconf automake libtool编译ffmpeg LINUX FFMPEG编译汇总(最简化)_底部的附件列表中】: ffmpeg - lzip…...
