一个app的初始阶段,必然是先满足各种业务需求。然后,经过多次版本迭代之后,先前的由于急于满足需求而导致的杂乱代码则会充斥整个项目。而此时,项目有了一定的规模,有了一定数量的开发人员,那么为了达到快速迭代版本的需求,则是需要有一个强大的架构来支撑。

在开始谈app架构之前,曾经我一度认为,一个好的app就是需要有好的架构,如果没有一个我所认为的“好架构”,那么这个app就是很low。

直到去年参加北京ArchSummit时,听了无数的公司他们对于产品的架构之后,我陷入沉思,因为我总在自己的认知里选出一个自己认为最好的架构,然后觉得其他架构都是垃圾。

静下心来想想,每个产品都有自己不同的定位,如果抛开它们的定位,抛开它们的业务需求去谈如果给它们设计一个良好的架构,这简直是扯淡。

更何况很多优秀的app架构也是由一开始很弱而慢慢变得越来越强。

所以没有最好的架构,只有适合自己的业务的架构才是最好的架构,并且它是逐步地变强变大。


本文将举一个例子来演示这个过程。


那么,到底什么是架构?

架构,又名软件架构,是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。

以我的理解,它就像是人的骨架一般,一个人从小生长到大,围绕着整个骨架去发展,变高变胖。

可以把app开发看成一个汽车工厂的流水线,造车身->喷漆->组装等等。即把整个开发流程切成一个个模块,每个模块相互独立,并发工作。这就是所谓app架构。

 


没有架构的“架构”

某天,一个叫Jim的开发者,他打算开发一个app,当然有一定计算机基础的他知道采用MVC的设计模式来构造app,于是一个星期后,终于能跑起来一个app,但是此时,看一下项目的目录结构:

v1.0

嗯,不错,我们不但能run,还能看出这个app用了MVC的设计模式耶。

但是随着开发的页面越来越多,一个月后,app有了10个页面,此时,打开Controller、View、Model这三个文件夹之后,发现每个文件夹里面竟然有几十个文件,它们杂乱无章的洒落在一起。此时不断有用户向Jim反映,xxx地方怎么按钮位置不对,xxx位置网络请求不成功。

头痛的Jim才知道,当初应该把粒度分的更细,于是又了接下来的架构。


分模块的架构

Jim把不同的功能模块放在一块儿,于是得到了如下的架构:

v2.0

但是不对,一些工具类,公用类该放哪呢?Jim仔细思索了一番,于是又将上述架构进行改进,得到以下的架构:

v2.1

嗯,这看起来才像样嘛。


Cocoapods

慢慢地,Jim发现网上有很多可以现成拿来用的第三方框架,而他同时也学习了Cocoapods这个神器。

什么是Cocoapods:

CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. It has over eighteen thousand libraries and can help you scale your projects elegantly.

它是一个能让你方便地管理第三方库的一个工具

于是,项目变成了这样:

v2.2

此时的架构已经满足了个人开发者,或者说是小型开发团队的需求了。


多人开发的架构

但是在一个初具规模的公司,上述的架构模式是远远不行的,试想一下,如果有20个人同时开发一个app,而此时大家就算各自负责自己的模块,如果同时有不同模块的同学添加或者删除文件,对于.xcodeproj文件来说,会有严重的冲突。

那么,怎么办呢?


想一下cocoapods的作用吧,其实利用它能做很多很多事,我们完全可以把Home、Detail、Login等模块抽出来,也把它视为“第三方库”(实际上可以算是二方库)。初期阶段可以这么做:

v3.0

可以看到我们把Home这个模块抽出来了。

这么做有什么好处?


如果我们把各个业务模块都抽出来,首先来说,可以解决冲突的问题,并且业务团队之间的工作不受影响,并且可以并行开发,也无需再等待其他兄弟业务团队的进度了。
当其他业务团队的任务完成时,我们只需pod update,将代码升级到最新就可以了。
并且当一个公司有多个app时,如果有公用的模块,用这种方式会更优雅。
当然,如果你觉得直接指定git地址太low,你完全可以搞一个私有Spec,专门存放业务模块代码。


子project模式的架构

很多人会说上述方式很复杂,还不如采用在主工程下中放子工程(业务模块)来实现抽象:

不合理的架构

但是我觉得这个方式管理起项目很麻烦,更新模块代码、不同app间复用模块代码都会没上述的方式优雅,所以我觉得这种方式没有上述的好。

 


对各个模块进行解耦

 

现在虽然我们对各个模块进行了抽象,但是业务模块间还是互相引用,对于开发来说,虽然解决了代码的耦合问题,对于代码的引用关系却没有改变:

v3.0

上图才只有4个模块,如果有上百个模块的话,这个关系可以复杂成一个庞大的蜘蛛网,这对于后期维护来说,成本是巨大的。

 

所以我们想,有木有好的方式来解耦呢,当然是有的,我觉得以下两个方式是很好的:

  • middleman

  • urlRoute

先来介绍middleman(中间人模式)

middleman

如图所示,我们只需将所有的模块依赖这个middleman,让middleman来处理各个模块的关系,模块A如果需要依赖模块B,完全可以考middleman来处理,并且返回模块A所需要的模块B的内容,这样就解决了解耦

再来说说urlRoute,其实这个方式类似于Facebook很早前的320结构了。

思路就是将每个页面看成是一个url,设置一套路由规则,在页面打开时将url进行路由查找,然后这样一来,只要模块A按照既定的规则写好url,那么模块B依赖模块A时,只需根据url打开就行了。

urlRoute


middleman VS urlRoute

两种方式各自有自己的优点和缺点,他们主要的区别在于:

  • 传参的方式

  • 所需维护的具体内容不同

我更倾向于urlRoute,为什么这么说呢?

由于本文讲的是app架构,这里就简单介绍下:

如果一个页面出现了问题,我们可以用各种patch的方式来打补丁。但是,如果一个页面出现了致命的错误,打patch的成本过于高的话,此时如果用urlRoute,则有个妙招。

我们可以更改appConfig(app的配置,可以从服务端动态更新),更改页面所对应的url,并且改成在路由规则里跳到webview的规则。

这样之后,当跳到此模块时,则会打开对应的H5页面,而不是原来的有问题的页面。
当然middleman也可以处理成这样,但是从实现的角度来说,显然是urlRoute更为优秀。

 


总结

架构远远不是一篇文章能讲清楚的,也不仅仅只是结构层次方面的内容,还有例如push、hotpatch、动态化、appConf、Service中间件模块的具体实现,MVCMVVMMVCS设计模式等等。本文只是从最基础的地方展现具体业务模块的解耦方式,希望能起到抛砖引玉的作用。

iOS移动端架构的那些事!(转载)的更多相关文章

  1. 服务端高并发分布式架构演进之路 转载,原文地址:https://segmentfault.com/a/1190000018626163

    1. 概述 本文以淘宝作为例子,介绍从一百个到千万级并发情况下服务端的架构的演进过程,同时列举出每个演进阶段会遇到的相关技术,让大家对架构的演进有一个整体的认知,文章最后汇总了一些架构设计的原则. 特 ...

  2. iOS 移动端生成工具开发

    代码地址如下:http://www.demodashi.com/demo/11284.html 一.准备工作 编译环境 xcode 用于生成冗余架构代码, 实现生成零耦合架构 二.程序实现 上个月的一 ...

  3. iOS开发:iOS的整体架构以及API介绍

    iOS的整体架构分为4层——Cocoa Touch层.Media层.Core Services层和Core OS层,下面概要介绍一下这4层. Cocoa Touch:构建iOS应用的一些基本系统服务, ...

  4. 关于H5在移动端架构的优化设计总结

    各大互联网公司采取的策略 一.百度移动前端首页 1. 对于首屏的静态文件css/js,在上线前全部编译直出到HTML文件中:整个首页的渲染只需要一次请求: 2.使用缓存:把不变的js/css/html ...

  5. 1年内4次架构调整,谈Nice的服务端架构变迁之路

    Nice 本身是一款照片分享社区类型的应用,在分享照片和生活态度的同时可以在照片上贴上如品牌.地点.兴趣等tag. Nice从2013.10月份上线App Store到目前每天2亿PV,服务端架构经过 ...

  6. iOS 音频视频图像合成那点事

    代码地址如下:http://www.demodashi.com/demo/13420.html 人而无信不知其可 前言 很久很久没有写点什么了,只因为最近事情太多了,这几天终于闲下来了,趁此机会,记录 ...

  7. iOS and JAVA 的 RSA 加密解密 (转载整理 )

    参考原文地址:http://www.cnblogs.com/makemelike/articles/3802518.html (至于RSA的基本原理,大家可以看 阮一峰的网络日志 的 RSA算法原理( ...

  8. 苹果iOS操作系统整体架构层次讲解

     iOS的系统架构分为四个层次:核心操作系统层(Core OS layer).核心服务层(Core Services layer).媒体层(Media layer)和可触摸层(Cocoa Touch ...

  9. ele.me在IOS浏览器端启动APP的技巧分析

    ele.me在IOS浏览器端启动APP的技巧分析 巧妙利用后台重定向,在schemes启动时提示用户打开,启动不了APP时能够及时跳转至下载页面. 避免报错页面的出现以及用户还没来的及选择就跳转到下载 ...

随机推荐

  1. BZOJ 1023 仙人掌图

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回 ...

  2. Delphi判断文件是否正在被使用(CreateFile也可以只是为了读取数据,而不是创建)

    首先,我们先来认识下CreateFile函数,它的原型如下   HANDLE CreateFile( LPCTSTR lpFileName,    //指向文件名的指针 DWORD dwDesired ...

  3. Spring: DispacherServlet和ContextLoaderListener中的WebApplicationContext的关系

    在Web容器(比如Tomcat)中配置Spring时,你可能已经司空见惯于web.xml文件中的以下配置代码: <context-param> <param-name>cont ...

  4. 【HDOJ】2425 Hiking Trip

    优先级队列+BFS. #include <iostream> #include <cstdio> #include <cstring> #include <q ...

  5. Linux日志文件系统(EXT4、XFS、JFS)及性能分析

    Ext4 ReiserFS Btrfs 等七种文件系统性能比拼 自上一篇<Ext2 v.s. Ext3 v.s. Ext4 性能比拼> 发布以来,社会各界纷纷来电来函,给出了“Ext4 我 ...

  6. 【模拟】NEERC15 A Adjustment Office (2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: 一个N*N的矩阵A,Ai,j=i+j,Q次操作,每次分两种,R r取出第r行还未被取的所有数,并输出和.C c ...

  7. 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 题目大意: T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何 ...

  8. bzoj 2324 [ZJOI2011]营救皮卡丘(floyd,费用流)

    2324: [ZJOI2011]营救皮卡丘 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1777  Solved: 712[Submit][Stat ...

  9. Hibernate学习笔记(一):级联删除

    一对多的关系映射 在一的一方配置文件中将会配置set节点信息: *.hbm.xml配置文件中set节点的属性: Lazy:默认是true 即使用延迟加载,false表示即时加载: Order-by:一 ...

  10. css倒三角的几种实现方式

    在网页中,你在很多地方都能看到倒三角,比如tooltips,下拉菜单等.大家有几种方式来实现呢? 1.BASE64编码 图片 假如你已经有了三角形的图片,并且减少HTTP请求,那么将这个图片转换成一个 ...