当前位置: 首页 > 编程日记 > 正文

6年iOS开发程序员总结组件化—让你的项目一步到位

纯个人学习笔记分享, 不喜勿喷,自行取关! 技术不缺乏缔造者,网络不缺乏键盘侠,但缺乏分享技术的源动力!

近几年组件化大家吵的沸沸扬扬的,它其实也不是什么黄金圣衣,穿上立马让你的小宇宙提升几个档次,也不是海皇的三叉戟,入手就能呼风唤雨,它不过就是一种app的架构思路。其实真的很简单,如果你的项目从发布之初就是用组件化,那么在开发的过程当中势必会少很多麻烦,难点其实是对我们庞大古老的工程进行组件化的改造。

一.下面我们来谈谈组件化到底是什么

其实组件化说白了就是将一个单一的工程分解为各个独立的组件,然后按照某种方式任意组织成为一个拥有完整业务逻辑的工程。

举个例子大家就明白了,一辆完整的汽车从来都不是由一个工厂将所有的零部件生产完成的,而是轮胎厂生产轮胎,发动机厂生产发动机,玻璃厂生产玻璃等等,然后再组装成为一辆完整的汽车。我们的各个组件或者说模块就是汽车的各个零部件,我们的整个工程我们也把它叫做宿主工程就是我们的汽车,我们按照一定的规则把他们拼装起来就是一个业务逻辑完整的工程。

二.组件化产生的原因

那么组件化为何应运而生,其实在我们的开发过程中,如果本身项目的规模不大,业务线比较少,人员也比较少,我们使用一般的单一开发模式就好了。但是随着我们的项目不断的迭代更新,业务线越来越多,发开人员也组件增多,这个时候就会暴露各种各样的问题

  • 耦合性严重

  • 编译速度慢

  • 测试不独立

  • 无法使用自己擅长的设计模式 ......

  • 耦合性严重 关于耦合性严重这点举个大家深有体会的例子,我们对接手二手甚至N手项目的时候都是深恶痛绝的,因为我们不知道以前的开发人员的思路和架构,这个时候我们往往面临着三类问题 1.代码的重构 2.增加新功能 3.改bug 就拿我们改bug来说,我们由于不了解人家的思路,我们把面前的bug改掉了,结果我们出了更多得bug,越改越多,头疼至极,因为我们可能将眼前bug改掉的同时,其他同样依赖改动地方的代码却不适用了,这就非常尴尬了。 同样地对我们的新功能开发和代码重构也是如此,我们好不容易将自己的功能模块搞定的时候,由于对老模块有依赖,一旦老模块中存在某些bug,会导致我们整个工程都跑不起来,我们不但测试不了自己新写的功能模块,而且我们可能连bug在哪都不是一时半会儿就找到的,再加上解决的时间我们将耗费大量的时间和精力,大大降低了我们的发开效率。

小编给大家推荐一个iOS技术交流群:551346706!群内提供数据结构与算法、底层进阶、swift、逆向、底层面试题整合文档等免费资料!

  • 编译速度慢 随着工程的业务线越来越多,发开人员不断增加,我们的项目越来越庞大,往往项目编译少则一两分钟多则几分钟,虽然并不影响我们的开发工作,但是我们使用组件化的开发配合二进制化,我们完全可以提高整个项目的编译时间。

  • 测试不独立

从这张图我们能看到我们在发开完毕我们自己的模块之后,我们需要对自己的模块进行测试,但是主工程里面的其他模块存在一个bug,导致我们的工程编译不了,那么我们开发的模块势必也是测试不了的,真的很尴尬。

  • 无法使用自己擅长的设计模式 这个我们稍微说一下大家应该能明白,如果你的公司主要是使用MVVM的架构模式进行开发的,而你只会使用MVC进行开发,是不是很尴尬,当然我们可以按照MVC去套用MVVM进行开发,但是我给大家画一张图大家就明白了

假设说我们的设计模式按照模块划分的话,我们没法使用MVC去套用我们的MVVM,这样我们除了去学习MVVM之外别无他法,可关键是你真的有足够的时间在短时间内上手吗? 当然如果我们按照功能模块来划分的话,我们的MVC倒是可以套用我们的MVVM,但是你能保证不出问题吗?

三.组件化的优势

那么我们使用组件化之后到底能达到什么样的效果呢?

  • 组件的独立 我们终于可以独立编写我们的模块,独立编译而不用漫长的等待主工程长达数分钟的编译,我们再也不用担心因为各种非自己功能模块中的bug让我们寸步难行无法单独测试了。
  • 资源的重用 我们项目中各种分类,宏定义,基础配置这些基础的代码,以及我们的轮播器,选项卡等等这些功能性的自定义UI组件再也不用重复的拖取或者重写,我们只需要以pod库的形式直接导入到工程中就OK啦。
  • 高效的迭代 当我们需要增加或者删除某些模块,我们只需要将对应的路径删除掉,就可以一次性将整个模块增加或者移除又不会影响宿主工程的正常运行,十分高效。 ※配合二进制,可大大提高项目的编译速度 我们把业务性、功能性、基础性的模块拆分成组件以后,可以采用静态库打包,framework库的形式二进制化组件,这样将大大提高我们的编译速度。

四.组件化应该考虑的问题

  • 组件的划分 我们一般将组件划分为三类 基础组件: 包含基本配置(常量,宏)、分类(各种系统类的扩展)、网络(AFN、SDWebImage封装)、工具(日期时间处理、文件处理、设备信息等)

功能组件: 包含控件(弹幕、轮播器、选项菜单、图文菜单等)、功能(断点续传、音频处理等)

业务组件: 业务线一(子业务线一,子业务线二.....) 业务线二(子业务线一,子业务线二.....)

  • 组件层级之间的关系

从这张图我们可以看出来,我们三大组件类,其实是有层级关系的,我们的业务组件既要使用我们的基础组件也要使用我们的功能组件,它属于我们基础组件和功能组件的上一层,而我们的基础组件和功能组件属于同一层级,他们之间是不能互相产生依赖关系的。

如果说我们的功能组件的弹幕需要使用到基础组件中的有关布局View的分类,我们这个时候最好的做法并不是将让我们的功能组件依赖于我们的基础组件,这样的话别人要使用我们的弹幕却要将我们整个基础组件都下载下来,那么我们的组件化就失去了原有的意义。我们在这里推荐的做法是讲我们所需要的那块代码直接拷贝到我们的功能组件当中去,这样做的好处在于我们的功能组件不需要依赖我们的基础组件。

同样在我们三大组件类的内部,组件之间也不能产生依赖关系,好比我们的弹幕不能依赖于我们的播放器,总不能别人要使用我们的弹幕还得把播放器给下载下来把,这样也是不合理的,对我们业务组件也是一样的,我们要增加或者删除某个业务线,结果导致其他的业务线没法正常的使用了,这都是不可取的。

但是某些时候我们确实需要使用其他组件里面的内容,但是他们之间又不能产生依赖关系,这个时候我们就要使用到组件间的通讯,这个在后面会讲到组件间如何通讯。

  • 组件的存在形式 组件内部:根据设计模式划分文件夹结构 组件形式(对外):每个组件都是以pod库的形式存在 组件测试:单独的测试工程(这里我们可以通过创建pod模板库形式,直接拥有测试工程)

  • 我们是以Cocoapods的形式安装各个组件的

这张图我们可以看到,我们的业务组件是可以依赖我们的基础组件和我们的功能组件的,而我们的业务组件都是以pod库的形式借助我们Cocoapod安装到我们宿主工程中去,我们的宿主工程面向的都是我们的业务组件。

  • 组件间的通讯 上面提到了我们同层次间的组件或者是我们三大组件内部的组件之间是不能有依赖关系的,但是确实有些时候我们一个组件内部发生了一些事件想要告诉其他组件,或者需要调用某些组件的服务,这个时候我们就需要用到组件之间的通讯。 这里我们来讲讲其中的一种方式--中间件,我们用一张示意图来描述一下

在这里我们看到我们组件都是通过中间件来进行交互的,组件将内部发生的变化告诉给中间件,中间件在通知其他组件。我们组件把各自的服务给中间件,需要对应服务的组件就会去找中间件拿,这样的话我们组件之间不会产生依赖关系,同时又能进行通讯。

五.分离组件的难点--解耦

一般在组件化的分离各个组件的时候,解耦这个话题我们是回避不了的,但是其实我们一般会遇到两种情况 1.组件里面依赖其他公共功能 2.组件内部需要对接某个服务

组件里面依赖其他公共功能 对于这种情况,我们一般最快的方式就是直接copy代码,虽然这个过程比较恶心,但是好处就是不会有额外的依赖,对于一些不重要的工具方法,我们都可以拷贝到内部来使用。 举个例子大家都明白了,我们使用获取屏幕尺寸的方法,而这个方法我们一般写成宏定义放在我们的基础组件中,我们的业务组件中要用到这个方法没这个时候我们没必要把我们基础组件也整个下载下来,我们直接复制粘贴这短代码就好了。 我们也可以把组件依赖的代码先做成一个pod库,然后依赖这个pod库就好了,这样我们的问题就迎刃而解了。 组件内部需要对接某个服务 比如我们控件的内部涉及到加载网络图片,我们一般会用到我们的SDWebImage的框架,虽然我们可以在使用远程私有索引库的时候添加依赖,那么我们在下载我们的私有库里面组件的时候我们可以将SDWebImage一并集成到我们的宿主工程中。如果开发过程中,公司用得不是SDWebImage不是会很尴尬吗? 所以我们使用的方式就是使用block或者代理把这部分职责丢出去,那么我们就可以自用的选择我们所需要使用的第三方框架或者公司内部写的框架,不用再纠结了。

小编给大家推荐一个iOS技术交流群:551346706!群内提供数据结构与算法、底层进阶、swift、逆向、底层面试题整合文档等免费资料!

转载于:https://juejin.im/post/5c20f56ce51d452baa77cc6d

相关文章:

处理问题的方法--抽象和特例化

事实上我们在软件开发的过程中总是:遇到问题,解决问题,这么一个 简单的过程。处理一般类似问题的时候,我们经过抽象,有的提取算法,有的提取结构,有的提取流程等等,这样的过程可以简单…

121-Best Time to Buy and Sell Stock

题目: Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum p…

控制行输入以下两句命令16倍速播放青年大学习

//得到视频标签 playRate document.getElementsByTagName(video); //改变播放速率 playRate.Bvideo.playbackRate 16;

ios 8+ (xcode 6.0 +)应用程序Ad Hoc 发布前多设备测试流程详解

我们开发的程序在经过simulator以及自己的iOS设备测试后,也基本完成应用程序了,这时候我们就可以把它发布出去了更更多的人去测试,我们可以在iOS平台使用ad hoc实现。 你在苹果购买的开发者会员账号,允许100台设备和你的账号关联。…

SHELL训练营--day5__shell脚本(1)

shell脚本意义 shell是一种脚本语言,具备计算机语言的基本特点:逻辑判断、循环、自定义函数等。shell脚本 主要使用 linux系统的命令,来实现特定目的。可用于自动化运维,提长运维效率。 shell脚本基本结构和运行方法 shell脚本名字…

让程序主窗口不显示在任务栏中

// 这样一句就能搞定了 在Form创建是调用 procedure TfrmWaitWindow.FormCreate(Sender: TObject); begin SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW); end; 相关方法1 Application.Initialize; Application.CreateForm(TForm1, Form1); Application.S…

查缺补漏 | Python控制结构

1. if 表达式的简介写法 x if E else y 意思是如果条件表达式E成立,执行x,否则执行y 等价于 if E:x else:y 2. Python的while循环和其他语言相似(只是少了大括号),但是for循环区别大很多 for iter_var in iterable_object: sui…

Android学习——R文件丢失异常原因汇总

Console报错:R.java was modified manually! Reverting to generated version! 引言: R文件丢失异常在java开发中是个比较常见的异常,造成这个异常的原因可能非常微小,但是给Android开发者们造成的麻烦可是巨大的,当程序员们费尽千…

举个栗子看如何做MySQL 内核深度优化

2019独角兽企业重金招聘Python工程师标准>>> 本文由云社区发表 作者介绍:简怀兵,腾讯云数据库高级工程师,负责腾讯云CDB内核及基础设施建设;先后供职于Thomson Reuters和YY等公司,PTimeDB作者,曾…

Ubuntu--开启TELNET服务

1 sudo apt-get install xinetd telnetd 安装成功后,系统也会有相应提示, 测试安装完之后就可以Telnet,要是还不行继续 2 sudo vi /etc/inetd.conf 并加入以下一行 telnet stream tcp nowait telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd …

Python的range()函数

如果想产生一个等差数列,用range()函数再合适不过。 range()函数可以有起始值、终值、步长三个参数。 range(start 0,end,step 1) 但是起始值和步长是可以缺省的。起始值的缺省值是0,步长的缺省值是1。 起始值被包含,终值不包含。 为了方…

C++链式继承

继承,对于学习C的每一个人来说,都不会陌生。在Qt的开发中,如果你需要对一个无边框的界面支持move操作,那么你就得通过继承重写虚函数来实现,这并不难,但如果我还需要对一个按钮支持移动,一般情况…

调度框架学习笔记(3)—— 集群调度框架的架构演进过程

本章是 The evolution of cluster scheduler architectures 文章的学习笔记。这篇文章讨论了这些年调度架构是如何发展的以及为什么会这样发展。 首先介绍一下这篇文章的作者:Malte Schwarzkopf,他目前在 MIT 的 PDOS实验室 作博士后,说起作者…

查缺补漏 | Python自定义函数

1 默认参数要放在自定义函数参数列表的最后,也就是说下面的定义是不允许的 2 调用函数时熟悉的是位置参数,但是也可以用关键字参数,也就是调用时把参数名写出来(可以通过它来改变参数的顺序)。不过貌似系统定义的函数不能用关键字参数&#x…

ZBar与ZXing使用后感觉

[原]ZBar与ZXing使用后感觉(上) 2014-3-18阅读2011 评论1 最近对二维码比较感兴趣,还是那句老话,那么我就对比了一下zxing和zbar 如果对于这两个的背景不了解的话,可以看我以前的文章,介绍了几个比较基础的…

X-UA-Compatible

X-UA-Compatible是IE8的一个专有<meta>属性&#xff0c;它告诉IE8采用何种IE版本去渲染网页&#xff0c;在html的<head>标签中使用。可以在微软官方文档获取更多介绍。 在IE8刚推出的时候&#xff0c;很多网页由于重构的问题&#xff0c;无法适应较高级的浏览器&a…

[转]【 视频 】PAR、DAR和SAR都是啥

原地址:http://blog.yikuyiku.com/?cat3 PAR —— Pixel Aspect Ratio 像素纵横比DAR —— Display Aspect Ratio 显示纵横比SAR —— Sample Aspect Ratio 采样纵横比 16&#xff1a;9和4&#xff1a;3指的是DAR&#xff0c;DAR和SAR之间没有必然联系。横向上的像素数目/纵向…

登高自卑 | 我的NumPy笔记

注&#xff1a;以下内容来自NumPy中文网 1 NumPy的矢量化和广播两个特征是大部分功能的基础。 矢量化让代码更接近标准的数学符号&#xff0c;更Pythonic&#xff0c;隐藏了所有的显示循环(幕后是C在做显示循环)。 广播即操作的隐式逐元素行为&#xff0c;不仅仅局限于算数运…

TI IPNC Web网页之网页修改教程

web网页程序修改 打开gStudio之后&#xff0c;点击菜单栏中Help->Contents。先把这个诡异的编程语言看一遍吧。这里搬一些东西出来。 GoDB简介 从第一副图片中&#xff0c;我们可以看出&#xff0c;从源文件到可执行文件的过程。 从第二幅图我们可以了解到GoDB是如何跨平台的…

Spring Cloud构建分布式电子商务平台:服务消费(基础)

使用LoadBalancerClient在Spring Cloud Commons中提供了大量的与服务治理相关的抽象接口&#xff0c;包括DiscoveryClient、这里我们即将介绍的LoadBalancerClient等。对于这些接口的定义我们在上一篇介绍服务注册与发现时已经说过&#xff0c;Spring Cloud做这一层抽象&#x…

OPENGL ES 对象的拾取

时间&#xff1a;19:51 2010-12-14 用户问题的说明 响应鼠标操作&#xff0c;其当中有一个非常重要的知识&#xff1a;使用鼠标点取&#xff0c;达到对三维模型对象的捕捉。 对象的拾取&#xff0c;这是3D当中的一个专业术语。也就是在二维屏幕当中选择三维对象。 我们要使用之…

如何禁止NumPy自动跳过数组的中心部分并仅打印角点

import numpy as np import sys np.set_printoptions(thresholdsys.maxsize)

用C#创建Windows服务(Windows Services)

转载自 hyslove最终编辑 hysloveWindows服务在Visual Studio 以前的版本中叫NT服务&#xff0c;在VS.net启用了新的名称。用Visual C# 创建Windows服务不是一件困难的事&#xff0c;本文就将指导你一步一步创建一个Windows服务并使用它。这个服务在启动和停止时&#xff0c;向一…

JS判断滚动条到底部

form:http://www.uphtm.com/js/269.html判断滚动条到底部&#xff0c;需要用到DOM的三个属性值&#xff0c;即scrollTop、clientHeight、scrollHeight。 scrollTop为滚动条在Y轴上的滚动距离。 clientHeight为内容可视区域的高度。 scrollHeight为内容可视区域的高度加上溢出…

docker容器网络 - 同一个host下的容器间通信

2019独角兽企业重金招聘Python工程师标准>>> 对于复杂的应用&#xff0c;不可避免需要多个服务部署在多个容器中&#xff0c;并且服务间存在相互间通信的情况。比如服务A需要连接mysql的容器。本文将介绍docker的容器网络&#xff0c;并通过实践解决在同一个docker …

登高自卑 | 我的PyTorch入门与实践笔记

1 函数名后带下划线会修改函数本身。如y.add_(x)会改变张量y。 2 PyTorch的Tensor和NumPy中的ndarray是可以互相转换的&#xff0c;转换后的对象共享内存(一个变另一个也跟着变)。

234. Palindrome Linked List - Easy

Given a singly linked list, determine if it is a palindrome. Example 1: Input: 1->2 Output: false Example 2: Input: 1->2->2->1 Output: true Follow up:Could you do it in O(n) time and O(1) space? 找中点&#xff0c;反转后半部分&#xff0c;再一一…

Hibernate 获取某个表全部记录时 奇怪现象 (重复出现某个记录)

我用Hibernate连接access的mdb 列出某个表全部记录的时候&#xff0c;发现有一个记录重复了。而直接用jdbc连接&#xff0c;就可以正确列出来。 本来还以为mdb不稳定&#xff0c;还吓了我一跳。毕竟打算用它作为长久数据库嘛~~ 分析了一下&#xff0c;发现正好重复的数据的主键…

iOS7导航栏和状态栏的定制

http://www.cocoachina.com/applenews/devnews/2013/1104/7287.html 转载于:https://www.cnblogs.com/luningning0901/p/4437190.html

2021年浙软夏令营预推免面经

夏令营 时间&#xff1a;七月中旬 参加人工智能分营&#xff0c;为期两周&#xff0c;评分标准&#xff1a;简历上课参与情况项目完成情况(具体占比不明)。 项目是完成三个深度学习模型&#xff0c;系统根据测试用例的通过情况评分。 预推免 时间&#xff1a;九月下旬 评…