此前,58 同城的技术委员会执行主席沈剑在 OneAPM 的技术公开课上分享过一个主题,「好的架构不是设计出来的,而是演技出来的」。由于对不少创业公司而言,随着业务的发展,网站流量或者移动端用户都会经历不一样的阶段。前期的时候,很难去设计一个百万或者千万级并发的架构,因此后期每每不断对架构进行更新迭代。java
固然,在这里也推荐一篇文章《移动开发中的痛点》,本文是 infoQ 举办线下聚会的一次讨论整理,当时参与的讨论者包括唐巧、郭亮、郭虹宇、邓宇光、代码家等国内知名移动开发者。其中就谈及了 MVC 架构的痛点,以及 React Native 所表明的 Web 开发 Native App 技术,相信会对你们有所启发。移动精英开发社群的第8期,也是围绕「架构」这个话题进行讨论。本文系滴滴出行的刘佳达整理。ios
如下为讨论内容整理:web
主持人韩兵:「架构」对开发者而言就是「高大上」,固然也不是每位 coder 都能搞定。对不少菜鸟而言就更陌生了,基本只能停留在理论层次。实践才能出真知,一个好的架构也是这样产生的。本次咱们但愿结合实际开发中遇到的问题,来聊聊移动端的架构设计。shell
李文杰:咱们的项目划分红了:数据层、UI 层、逻辑层。编程
上海-李博:咱们使用的是 MVVM(Model-View-ViewModel),而后使用了一些 React Native。设计模式
韩兵:MVC 这样的模式能够代替我们移动端架构吗?数组
攻城狮:MVC、MVVM 只是一种设计模式而已。浏览器
Wallace:我的认为, MVC 这种经典结构已经知足不了如今的需求了。缓存
Rory:MVC 这样的模式改进一些,可能会更适合移动端架构。从业务逻辑的角度看,架构应该服从业务逻辑。安全
王威特-明道-ios:基于团队、服务于团队的代码基础规范包含开发模式,代码规范等等。
Draven-ios:我认为,MVVM + React Native 能让开发变得轻松不少。
李文杰-上海数云-ios:特别但愿有一套成熟的架构,UI 和逻辑都写好了。只要写写数据就能够用了。我针对的是超快速的简单需求 APP 开发,就像不少建站技术同样,「拖一拖」就能够完成。
攻城狮:功能模块化也是架构中很重要的一环。
小龙:万变不离其宗,天下武功出一家! 移动端各路设计不也是围绕着 MVC 控制显示数据,而后再作各类拆分吗?
露露:模块与模块之间,应该能快速拆分而后移植到新的项目中吧?
蜂鸟:用 React 基于响应式函数编程是能够简化实现过程,省不少代码。
刘玉娇-小邻小里-ios:问下你们网络层搭建用的是 delegate 仍是 block ?咱们后来用的,发现好像 delegate 会好一点。
Draven-ios:block 比较灵活。
王宇-陆金所-ios:可是 block 写的太随意了。
Draven-ios:delegate 看起来比较规范。
小龙:block 是方便,但别忘了它是一个结构体。
蜂鸟:昨天碰到一个问题,就是一个 App 有100多我的共同开发,怎么设计架构?才能让100我的协同开发不出问题?
A-困惑:通常用 block。
Icocos:以前有人讨论过,说用 MVP 比较好。
小龙:若是东西多了很重的,delegate 传的时候只是一个指针。
进击的小比克:一部分作网络层,一部分作业务逻辑,一部分作 UI。
王威特-明道-ios:delegate 书写规范,也能够避免循环引用的问题。block 书写流畅,可是会把网络的代码分散在各处,最终维护不必定好。建议在网络业务种的结构内用 delegate,反之block更方便。
露露:若是几个实例用一个 delegate,须要判断。
上海-李博:我以为,进行工程性的管理,仍是比较好。各作各的业务,淘宝就是采用这种模式。至关于每一个业务维护一个工程。
潘卫杰:可使用插座式的模块开发。分红多个小 Team ,负责相对独立的业务功能开发,每一个 Team 配一个测试,经过了就提交,随时能够打包出成品。
韩兵:以前也有人说了,架构是不只仅是为了方便业务,还有一个是为了咱们 coder 快速开发。那架构解决了咱们项目开发中的什么问题?
露露:如今 block 用的不少,可是怎么才算使用的好呢?
小龙:delegate 是指针,block 是结构体,一个传递的时候轻,但写着麻烦,一个写着方便传递的时候比较重。
潘卫杰:以前咱们公司移动端的大项目就是「插座式」开发的,批量出各个行业的 App。
Rory:移动架构设计和选型根据个人经验应该遵照如下几个原则吧:
刘玉娇:还有个问题,你们 VC 的分层是 base 而后下边分为 baselist 和 baseentity 而后往下继承吗?
上海-李博:我感受上面说的继承这样下去会愈来愈痛苦
潘卫杰:前年的时候,行业内有一个说法:各个行业扁平化,去中心化,不少行业老板也都想有本身的电子商务平台。咱们以前就给他们解决这个问题,可是咱们又不能每家都出一个,就用这种方式出一个不少功能的,各家用的时候在后台自定义组合。
小龙:高内聚低耦合!
Noark9:之前公司作一个 Windows 上应用的以为思路能够借鉴:咱们有一个比较大的,咱们称为 shell(壳程序),而后,壳程序提供了接口请求的框架,用户信息的接口,发送通知,以及一些公共的功能。而后,每一个小功能,都做为一个动态库接入,壳程序负责加载下载下来的动态库,而后打开到界面上。
王宇-陆金所-ios:具体怎么和业务模块拆分方法呢?
韩兵:服务端都是重架构,通常移动端都偏轻架构。
王威特:是,继承的耦合性过重。用组合的方式更好,前几天的一篇文章就很是推荐阅读。
http://blog.yongfengzhang.com/cn/blog/write-code-that-is-easy-to-delete-not-easy-to/
Rory:理论上,架构不必定要多复杂。可是至少简明的能够区分组件、组件的逻辑、业务逻辑、数据层。让组件的逻辑和业务逻辑分离,减小代码耦合;方法的适量重载和重写;在项目的维护期,抽离项目特有的组件。
蜂鸟:具体到写代码,就是多用接口,定义个协议来实现后使用它。
小龙:面向协议就是看接口定义的怎么样了。能够把各行业一些特性归类为某一类属性,统一处理,最后用的时候换个皮,换套文案就能够。
蜂鸟:API 接口定义的好,说明模块分离,边界定义的很清楚。
小龙:面向协议的变成是否是给 ViewController 暴露的都是 id <某个协议> ?这种形式的,而不须要 import 具体的类?求解答。
你该休息了:Android 架构中热部署你们常采用的多吗 ?
李哲-京东:我重写的时候,就遵循的就是各个模块的拆分。将业务,功能,包括很小的通知名,颜色,缓存路径都搞成了宏定义。将网络,数据,业务,功能都剥离了出来。
王威特:宏定义写起来有些难堪,用 const string 不是更好吗?
韩兵:能够推荐一些架构设计比较好的来源代码
阿尘:我的感受,要深刻移动架构,必须了解企业应用架构。开源的完整 App 应该比较少。为何要有架构?根本缘由仍是在于复杂性。头一次看到就五体投地,以前用 NimbusKit 搭架构,如今打算转向 YYKit 。简单的 App 是不须要架构的。
李哲:将一些业务的解决方法,使用模型思想去解决,尤为是那个微博列表的设计。要写易删除,而不易扩展的代码。
阿尘:我的感受,合理的分层设计很关键。
哈哈:好比微信 SDK,集成了登陆、分享、支付三个大的功能,不支持单独拆分使用,若是以前已经使用了友盟、shareSDK 等,只想接入微信支付功能,就会出现冲突问题。
阿尘:架构的构建是一个不断权衡的过程。
有一个道理:架构的构建是一个不断权衡的过程?这个有点不一样意。
蜂鸟:我以为架构之因此须要,就是要保持一个基本的稳定架构,别变来变去的。再变也是细节和模块功能的补充,跳不出已经设定好的架构。
韩兵:好的东西都不是不断改,不断优化的。
小龙:响应式编程思想:不须要考虑调用顺序,只须要知道考虑结果,相似于蝴蝶效应,产生一个事件,会影响不少东西,这些事件像流同样的传播出去,而后影响结果,借用面向对象的一句话,万物皆是流。
而函数式编程思想是把操做尽可能写成一系列嵌套的函数或者方法调用。函数式编程特色:每一个方法必须有返回值(自己对象),把函数或者 Block 当作参数,block 参数(须要操做的值)block 返回值(操做结果)。
表明:ReactiveCocoa。
李哲-京东:而一个好的架构也老是在业务不断变化中慢慢变好的。
小龙:链式编程思想:是将多个操做(多行代码)经过点号(.)连接在一块儿成为一句代码,使代码可读性好。a(1).b(2).c(3)
链式编程特色:方法的返回值是 block,block 必须有返回值(自己对象),block 参数(须要操做的值)
表明:masonry 框架。
蜂鸟:若是架构老是变来变去,偏偏证实了架构设计的不合理。
攻城狮:如今好多大公司有个技术平台部,把一些功能抽象出来模块化,这样业务线开发就简单不少,效率也高了。
阿尘:架构是一组决策的组合,作每一个决策的过程都是一次取舍和权衡,这样理解吗?我以为,实践出真知,从0开始打造一个复杂 App 的过程,会让你受益不浅。
王威特:这回到主持人说的,架构是经验积累出来的,慢慢来。即便作了一个坏架构,之后和别人的对比下就收获颇丰了。
攻城狮:架构不是一下就有的,走过才知道捷径。
蜂鸟:赞成你说的决策的取舍平衡,个人见解是这种决策取舍越少越好。好的架构应该能有空间适应这种业务的变化,预见到也许会有的改动,有点理想化了。
王威特:一个长期迭代的 App 作的就是架构和业务,架构能力也是慢慢磨出来的。若是在外包公司工做,更要作好架构,才能快速开发。
攻城狮:有些公司 iOS 页面跳转是统一的一个管理类来管理的,在座各位有这么作的吗?
进击的小比克:如今的项目既按功能模块分,又分业务逻辑、网络层、数据层,分得有点乱啊!和网络服务器框架同样。
高山:好比一个页面,须要 abcd 四个页面才能过来,如今一个 url ,不少前置条件都没有,可能致使错误。这就对架构解耦提出更高的要求。
王威特:最先 ABRouter ,你给 viewController 写个 category 就好了。这里说的是iOS,用 router 实现跳转,一个极大的极大的便利就是之后你的 App 须要实现从 safari 浏览器打开 App ,发现你都搞定了。
韩兵:好像我们讨论组作服务端的人很少。什么是服务端架构?服务端涉及的东西太多。只有亲自设计过和处理过数量级比较大的系统,才可能会对架构有所体悟。要否则极可能是「纸上谈兵」。
Wallace:其实好的架构,无非是能在你现有的状况下,能解决实际中存在的问题。有些很牛逼的架构不必定适用于如今的具体场景。
韩兵:自己架构包含的知识就不少,不只仅一门编程语言。
攻城狮:Java 比较成熟,可是提供的架构还有一些并非很成熟。
柠檬:从头看了下,都是偏于理论,对于架构仍是没什么印象,好比说 MVC,这也是最基本的。可是如何作到架构师级别?求指教。
柠檬:最近在整理一些知识,我的感受,想能为架构师,就是把基本的东西包「打包」在一个项目中。
Wallace:其实写的时间长了,很天然的就能时刻考虑到「高内聚低耦合」的思惟了。尤为是,写完一个模块后也能够锤炼本身。
韩兵:设计一个 App,首先应该考虑的就是它的架构。先把结构搭建起来,网络层封装好,第三方控件封装好,而后最快速度支撑起业务层。其实在实际开发中,没有那么多时间成本,仍是须要优化一些东西。
丁建龙:模块化,最少的暴露参数和接口。
柠檬:目前所面临的代码质量问题,绝大部分不是技术问题,不是 coding 能力问题,是节奏把控,是质量观念的问题,如何平衡 scope 、quality、schedule,这不是自下而上的变革,是自上而下的思想改变,每个技术 leader 都须要去权衡把控。
一切质量问题,本质上就是技术 leader 的问题,不少人可能会说,业务需求太多,工做量太大,跑得太快,这些都是事实,事实的背后是,咱们技术有没有真正去理解业务,理解产品的思路和想法,理解业务的核心诉求和难点,你们必定能够平衡好这三方面的关系。
韩兵:你们的项目都是怎么搭建起来的?
柠檬:咱们是初版确定是快速出原形,看用户的功能,两周一个迭代。成型后重构。
Rory:初期:简易架构,实现基础功能,组件;开发过程当中:迭代丰富组件,抽离业务,造成模块化。像初期选型,我能够用诺远目前1.0->1.1的版本发展历程举个例子。后期维护扩容,能够用365日历的 Android 客户端举个例子。
韩兵:这个只有实践过,才可能会有一些感悟。说说你们 App 从无到有的构建过程。从这个过程当中理解架构的造成和运做。我的以为从这点入手,会容易理解一些。
柠檬:架构看功力,架构师的路很长,不断的被指责,改进的过程,这是漫长的过程。我如今的想法是把几乎全部项目都用到的东西,整理在一个项目下,之后独立开发能够直接运用。还能够把整个项目底层作一个基类。
Rory:目前互联网行业主要仍是敏捷开发,因此初期选型的时候,其实架构细分显得不是很重要,却是架构上为后期模块化,可扩展性的方面考虑更多。好比,小诺理财 Android 客户端,初期架构只作了网络层,数据解析,activity 基类封装,图片缓存,和一些经常使用的 UI 组件。
露露:我以为你能够整合,可是若是用了某一个功能,能快速拆分。
Wallace:我曾经最开始工做的时候,觉得把见过的东西都存下来,到时候用上,但其实都没用上。
Rory:总体上业务结构初期都是在 Activity 中处理的,没有作业务逻辑的抽离。从1.0-1.1的过程当中,这边的 Android 技术团队进行了一些重构和业务抽离,构建基础。造成目前定制的 UI组件库(目前 UI 组件的逻辑仍然未进行细致抽离)、业务逻辑 control 单元(目前是依据业务模块的不一样,抽离不一样模块的 control。)这么作,主要的目的是为了后续新加入的技术,能够快速熟悉项目,了解业务。
韩兵:若是这个项目越作越大,我们就暂定理财项目,是否是要考虑底层框架对现有业务的支持?若是团队愈来愈大,是否是还要考虑对n多个团队的支持?
Rory:理财和支付同样,对数据安全和通讯安全比较重视。
阿尘:横向业务模块化,竖向低耦合,作到单向依赖。
Rory:曾经参与过,365日历 Android 客户端的后期维护。当时客户端项目到了后期,模块划分会愈来愈多,项目会变得愈来愈臃肿。这时候在 java 层面和 Android framework 层的优化其实更少。
多数组件这时候都已经很成熟,这时候须要集成性能测试,针对某一点上进行细节优化。架构上也是抽离出更多的库,进行细分支持。365日历实际上是典型的 MVC 向 MVP 的过渡。固然,我离职的时候这个过渡还未完成。基本上雏形能够看到,UI 层和业务层已经进行深度划分,经过 control 控制数据传递和通讯。
MVP,我的经验更适合移动端,移动端开发的主要难点是两个,业务逻辑和界面效果。
韩兵:因此移动端和服务端考虑的点也是不同的!
Rory:把 UI 和业务逻辑区分,这样控制单元更有针对性,对原有业务或者UI的修改更有针对性,迭代过程当中产生错误理解和错误逻辑致使 bug 的可能性也更小。
可能由于这样抽离后,新技术的加入,理解项目须要更长的时间。代码阅读性会随着项目的臃肿变得愈来愈差。因此必要的抽离就是保证代码的可读性。
过渡重构举个很简单的例子,一个 View 的 UI 逻辑非要强行适应整个项目全部的 View,创造 n 个构造,传入多个控制参数。那么逻辑理解起来是否是很困难?最简单的断定标准,代码的创造者若是隔一段时间都很难读得懂本身写的代码,算不算一种过分?
简单的总结下,架构应该随着项目发展不断发展,一成不变的架构是行不通的!
国内 ITOM 管理平台 OneAPM 致力于帮助企业用户提供全栈式的性能管理以及 IT 运维管理服务,经过一个探针就可以完成日志分析、安全防御、APM 基础组件监控、集成报警以及大数据分析等功能。想阅读更多优秀文章,请访问 OneAPM 官方技术博客
本文转自 OneAPM 官方博客