当前位置: 首页 > news >正文

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 语言中&#xff0c;select 是一种用于处理多个通道操作的控制结构。它可以用于在多个通道之间进行非阻塞的选择操作&#xff0c;从而实现并发控制和通信。 select 语句的基本语法如下&#xff1a; go select { case <-channel1:// 当 channel1 可读时执行的代码 cas…...

23款奔驰GLC260L升级小柏林音响 全新15个扬声器

2023年款奔驰GLC260 GLC300升级小柏林之声 3D音效系统 升级小柏林之声音响之后&#xff0c;全车一共有15个喇叭&#xff0c;1台功放&#xff0c;每一首音乐都能在车内掀起激情的音浪&#xff0c;感受纯粹的音乐享受&#xff0c;低频震撼澎湃&#xff0c;让你的心跳与音乐完美契…...

ssh 免密码登录

ssh 免密码登录 1. 原理 1.1 密码登录的通俗解释 把服务器当作一个凤凰社&#xff0c;每次进社公干都需要拿特别的门票入场&#xff0c;门票便是服务器上的账户密码&#xff1b; 1.2 免密登录 对于凤凰社的高级会员&#xff0c;会在社内存储一张高级会员身份&#xff08;id_rsa…...

小程序使用腾讯位置插件获取当前位置

1.小程序后台 设置-第三方设置-插件管理-添加插件 2.进入网站 腾讯位置服务 设置对应的额度 mapPickerPlugin(res) {const key ""; //使用在腾讯位置服务申请的keyconst referer "铅锂运营"; //调用插件的app的名称const category "生活服务,娱…...

零基础学Python怎么学习?我来告诉你

对于IT新手来说&#xff0c;零基础学Python的话&#xff0c;之后可选择的职业方向非常多。Python全栈和爬虫一直以来都是市场的最火的就业岗位之一&#xff0c;它们的薪资回报也算是开发岗里面的顶级了。而且随着大数据和人工智能时代的到来&#xff0c;数据处理和人工智能行业…...

开源软件 FFmpeg 生成模型使用图片数据集

本篇文章聊聊&#xff0c;成就了无数视频软件公司、无数在线视频网站、无数 CDN 云服务厂商的开源软件 ffmpeg。 分享下如何使用它将各种视频或电影文件&#xff0c;转换成上万张图片数据集、壁纸集合&#xff0c;来让下一篇文章中的模型程序“有米下锅”&#xff0c;这个方法…...

Linux Shell 通配符 / glob 模式

1、概念 glob 模式&#xff08;globbing&#xff09;也被称之为 shell 通配符&#xff0c;名字的起源来自于 Unix V6 中的 /etc/glob &#xff08;详见 man 文档&#xff09;。glob 是一种特殊的模式匹配&#xff0c;最常见的是通配符拓展&#xff0c;也可以将 glob 模式设为精…...

深入了解域名与SSL证书的关系

在如今数字化的世界里&#xff0c;网络安全成为我们关注的重要议题之一。为了确保数据在网络上传输的安全性&#xff0c;我们通常会采取各种安全措施&#xff0c;其中最常用的就是SSL证书。然而&#xff0c;很多人并不了解SSL证书是如何与域名相互关联的。 首先&#xff0c;我…...

计算属性与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&#xff0c;点击SharedElement共享元素动画查看大图&#xff0c;Kotlin&#xff08;1&#xff09; <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name"an…...

SELinux零知识学习八、SELinux策略语言之客体类别和许可(2)

接前一篇文章&#xff1a;SELinux零知识学习七、SELinux策略语言之客体类别和许可&#xff08;1&#xff09; 一、SELinux策略语言之客体类别和许可 2. 在SELinux策略中定义客体类别 SELinux策略中必须包括所有SELinux内核支持的客体类别和许可的声明&#xff0c;以及其它客体…...

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可以遵循简单的规则吗?

由于大型语言模型在现实世界中的责任越来越大&#xff0c;因此如何以可靠的方式指定和约束这些系统的行为很重要。一些开发人员希望为模型设置显式规则&#xff0c;例如“不生成滥用内容”&#xff0c;但这种方式可能会被特殊技术规避。评估LLM在面对对抗性输入时遵循开发人员提…...

如何挑选护眼灯?光照均匀度、色温、眩光这3点!

光照环境对我们的生活质量影响深远&#xff0c;尤其在孩子的成长过程中&#xff0c;良好的光照环境对其学习效率、视力保护都至关重要。光照中的很多因素都对视力有着或大或小的影响&#xff0c;本文将从光照均匀度、眩光、色温三个关键点&#xff0c;深入浅出地让消费者了解其…...

python 实验7

姓名&#xff1a;轨迹 学号&#xff1a;6666 专业年级&#xff1a;2021级软件工程 班级&#xff1a; 66 实验的准备阶段 (指导教师填写) 课程名称 Python开发与应用 实验名称 文件异常应用 实验目的 &#xff08;1&#xff09;掌握基本文件读写的方式&#xff1b; …...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...