架构设计,到底是什么呢?基于这段时间的学习和自己的一些思考,我认为架构是基于产品和技术所达成的一种共识。我不是专业的架构师,也不是经验老道的开发者。本文目的有三,一是整理这段时间的架构学习和思考以及总结这一年的开发经验教训,二是希望能够与各位朋友探讨移动端App的架构设计,三是希望我们每一个应用开发者能够拥有架构的意识。个人的水平有限,诸多不对的地方,恳请批评指正。
提示:文中链接需要点击文章末尾处阅读原文才能点击。
前面啰嗦了很多,终于写到这里了。对于一个开发人员来说,怎么做才是我们的关键问题所在。只会Android开发,所以以下只讨论Android。我主要从以下几个方面来谈一谈怎么做这个问题。
1、技术选型
(1)、 开发平台
移动端的开发目前主要是两大阵营Android、IOS,其他的就不多说了。
(2)、 开发工具
编译工具:Eclipse&Ant、AndroidStudio&Gradle,作为Android开发者,目前毫无疑问应该选择AndroidStudio&Gradle;
代码仓库:Git 、SVN ,工具有海龟、AndroidStudio也集成了VCS;
Maven仓库:可以使用nexus创建自己的maven私服;
持续集成:Jinkens、Buildbot、Travis CI、Strider、Integrity;
(3)、 开发语言
Java、Kotin、Grovvy、SQL等等;
(4)、 开发模式
MVC、MVP、MVVM、clean等,各有优缺点,在此不做详细说明;
(5)、 开源框架
都说了不要重复造轮子,因为你造的轮子不一定比人家的好用,对于我们开发者而言,有一件非常好的事情就是我们有太多的开源免费的第三方库供我们使用,这样给我们省去了大量的工作,做到更加高效的开发。但是,如何选择,是否引入使我们需要考虑的一个问题。下面列出一些常用的第三方库,更多请点击。
网络:okhttp、 android-asyn-http、 volley、 Retrofit
事件总线:otto、 EventBus
依赖注入:Dagger、 RoboGuice、 ButterKnife
图片:Fresco、Glide、 picasso
数据库:GreenDao、 Ormlite、LitePal
Json解析: Gson、JackSon、 FastJson
响应式编程: RxJava、 RxAndroid
异常统计平台:腾讯Bugly、Crashlytics
性能优化: blockcanary、 leakcanary
(6)、 新兴技术
软件开发而言,新技术的发展相当迅速,然而我们实际落地到项目中却需要很长的时间,因为新的技术刚出来一是需要学习成本,二是需要承担新技术不够成熟,存在缺陷带来的一些风险。当然,我们应该积极的引入好的新的东西,跟得上时代的步伐才好。下面列举的一些也许都算不上新的东西,但是也是近年来大家所追捧的新技术。
AndroidSupport:DataBinding、MaterialDesign等;
混合开发:ReactNative、Hybrid、Weex等;
编程语言:Java8、Kotlin;
热修复:AndFix、HotFix、Tinker等;
构建:InstantRun、Freeline
2、业务拆分
我们在进行业务拆分的时候,我认为可以将业务分成三类:
(1)、常用基础业务
基础业务主要是我们的app的一些基础功能,像我们公司有BFC团队给我们开发了文件上传下载、网络请求、行为采集、账号系统等SDK,免除我们一些重复的劳动工作。怎么去定义什么业务才是基础业务呢?我觉得可以这么去区分。如果你的业务在行业普通的应用app都有需要,那么这些这些就是具有普遍适用性的基础业务。我们根据不同的功能进行拆分。
(2)、通用技术业务
通用技术业务我觉得是和自己app相关并且有技术性很强的业务,可能是你应用的核心技术部分,比如美颜这一类软件的图片处理,小猿搜题这类的图片识别等就是一项通用技术型业务。通用技术业务的特点就是在和你同一类的app都会有需要使用的技术,我们可以根据不同的技术领域进行拆分。
(3)、特定功能业务
特定功能业务就是属于你自己app的特定功能了,一般可以按照功能进行拆分成不同模块。比如说我目前的一键搜(类似于小猿搜题)主要有搜题、查单词、翻译三大功能。那么就可以分拆为三大块。搜题要经过拍照、框题、图片处理、网络请求等步骤,每个步骤都可以看成一块小业务,以此进行拆分。特定功能业务大部分仅适用于你自身的APP。
以上的说法仅从自身的经验出发来进行描述,在我们实际的开发中可能会有一些特殊情况,或者有不同的拆分分方法。总之,业务的拆分还需要根据实际情况来。
3、架构设计(关注点分离、抽象)
(1)、核心概念
关注点分离
世上本没有架构,关注点一分离就有了架构,我们将一个软件系统的开发从多个维度将我们的工作进行拆分,对于每个领域进行设计,将各个领域有系统的组织起来,这种组织结构就是架构。然而如何将一个复杂的系统将关注点进行合理的分离,这个是非常有挑战的。
抽象
抽象,这是在请教一位前辈时最后给我强调的一点。如果你对app是跟着交互走、一个页面一个页面写的,那么很显然,你没有对你的业务进行抽象,而只是在实现。作为java的设计思想也很强调抽象的概念。那抽象到底是什么呢?抽象就是你要做什么!更简单的理解就是,写interface而不是class。不知道大家有没有这样的经历,在我们的MVP的开发当中,我们有个Model,也有一个IModel,但是我们写完了Model才知道怎么写IModel,最后成了粘贴复制的体力劳动。如果你是这么做的,你可以自己思考下,假如我们先写是IModel,而不是Model,那就是怎么样的体验呢?这就是将你的业务进行抽象。在架构的设计当中,你只需要知道你要做些什么?而不需要去过多的关注你具体怎么去实现它,这才是设计。
(2)、设计思维
面向过程(Procedure Oriented)
众所周知,在C语言的开发中,我们的逻辑大多是根据任务的流程走。这是面向过程的典型例子。面向过程关注的是工作的流程、一步一步的完成任务。
面向对象(Object Oriented)
Java语言作为面向对象开发的典型代表,这是我们所熟知的。我们将计算机按照人的思维来进行设计,每一个对象都持有自己的属性,并且持有自己的操作方法。对象之间有继承,组合等关系,通过组织这些关系来完成我们的程序。就像社会的人和物一样,人与人之间各种复杂的关系组合完成了社会各项活动的运转。
面向切面 (Aspect-Oriented)
面向切面是为弥补面向对象中的一些缺陷而生的,我们将某些功能封装到一起,提供对外的接口,方便在任何地方调用。就如SharedPreferences, Json, Xml, File, Device, System, Log, 格式转换等,这些通常会在until包里边。它就相当于一个横截面,我们可以随时面向这个横截面完成操作,而自己的逻辑里边不再需要重复的设计。
面向服务(Service-Oriented)
面向服务是将系统进行拆分,分成一个个独立的程序或组件,并对外提供某一项服务。每项服务之间通过某种协议进行通信,并进行分开部署,如HTTP,从而达到松耦合的目的。
以上四种思维重点在于看待问题的角度不同,不同的角度解决问题的方案就不一样,当然各种角度各有优劣。那么对于在android开发中是否都只是按照OOP原则来设计呢?很显然不是。面对不同的需求,不同的场景,我们需要及时调整自己的思维,灵活运用,寻找最适合的角度,拿出最优的设计方案,这才是我们所追求的。
(3)、设计原则
高内聚
怎么理解高内聚?我认为我们在拆分时某一细分领域只完成单一的功能,其内部的事情自己处理。从表面来看比如一个model的class,对外提供了一个接口,那么他有一个输入,一个输出。单独看这个接口而言,它是高内聚的。当然,其内部的组织结构有可能千差万别,所以内聚的形式又各有不同。所以我们将他们分类为功能内聚、顺序内聚、时间内聚等等。
低耦合
耦合指的是模块之间存在依赖关系,关系相互依赖就会相互制衡,这是必然的。所以,如果耦合度太高的话,将会导致牵一发而动全身的后果,这个使我们不想看到的,也极大的影响的程序版本的迭代以及bug的修复。根据依赖关系的不同,我们分为了非直接耦合、数据耦合、内容耦合、开关耦合、控制耦合、外部耦合等等。我们要完成一个系统的开发,必须要将各个模块有效的组织起来,这种组织关系便无法避免存在了耦合,我们要做的是尽量减少这些依赖关系,尤其避免交叉依赖,将耦合度降低到最低,把我们的程序设计的更加的灵活。
适度设计
我们在设计的时候如果考虑不周,那么设计不够,不能满足现有或者可预知的需求,从发展的眼光来看,会导致后期的开发中出现很多的问题。如果想的太多,很容易进行过度的设计,从而将一个简单的系统设计的很复杂,那么就给当前的开发将增加了许多无意义的工作,降低了开发效率。那么怎样的设计才是合理的设计呢?我认为能够同时满足现有的需求和可预知的需求,并且面对架构的调整时能够很方便的进行扩展。这样的设计,是非常好的设计。如何才能达到这样的效果呢?我个人觉得在对系统进行设计时,关注点分离的颗粒度需要把握好,系统不过就是将不同单一小模块进行组织而已,那么这些细小的模块就是架构设计的基础,这就好比建房的那些砖头。这些砖头是什么呢?他么可以是是一个对外提供接口的公共方法,也可以是私有的内部方法,也可以是某某持用的成员变量。当然往大里看,他可以是某一个功能模块。在上述行业内各个app的架构演进中,都很强调进行模块化的改造。所以,分离好你的系统,才能够灵活的组织起来,以不变应万变。
(4)、设计方案
指导模型
下图在文中已经提到,这里再次引入,因为这张图对我的启发真的很大,也表达出了我心之所想。面对一个复杂的系统,我们怎么样去分离,怎么样去组织,我认为这张图已经传达出了其中的精髓,所以我认为这是架构设计的指导模型,无论你是什么MVC、MVP、MVVM之类的,都可以从中去理解。
模型分解
根据实践开发中个人的理解,我将此图再次进行了简化如下:
横向分块
根据上图的简化模型,我们可以这么理解,在横向我们根据业务功能进行模块划分。比如主题商店,我们可以分为壁纸、铃声等等模块,每个模块间解耦。同时,在每一层的业务间再次进行分块,比如壁纸在数据层就有图片的请求、加载、缓存、裁剪处理等等。
纵向分层
接下来我们在对每个模块的业务根据职责分为展现层、业务层、数据层。数据层主要负责数据的获取、封装等工作,业务层主要更加上层的需要调配各数据层最终将数据返回给展现层,展现层的工作就是将数据展现在UI界面上,并且响应人的各种指令切换UI,操作新的数据。
理想模型
在横向来看,我们将业务进行了分块,保证块与块之间相互之间没有任何依赖,保证了绝对的解耦。从纵向来看,每个层级之间的依赖很明显是无法避免的,所以我们可以保证上层仅依赖下层的接口,从而达到降低其耦合度的目的。
如上图所示,通过上述横向分块、纵向分层、接口依赖这三大步骤之后,我们可以将一个系统进行了很好的分解,并得到一个理想模型。当然,这是一个理想的模型。在我们的实际开发中可能无法避免一些交叉等特殊情况,我们还需要从实际情况出发。但是有一点,我们可以保证接口的分离,已达到更低的耦合度的目的。
统一管理
统一管理,是对于我们的设计中有一些东西是需要统一管理起来的。通过上述原则,我们将一个复杂的系统进行了拆解,已达到架构设计中将关注点分离的目的。然而在实际的开发中,我们除了要进行业务的分拆,也需要对某些业务进行统一的管理。比如说一些模式的开关管理,比如说我们在进行网络请求时需要在测试环境和正式环境之间的切换,我们可以将这些模式切换的开关放到一个地方,方便我们进行管理,而不要去到各个地方去修改。再比如说我们的请求url地址,是否可以写到一起进行统一的管理。还有在某些应用中会通过一个中间人来进行统一管理数据的流通、页面的跳转,这也是一个可以尝试的方案,详细请看苏宁易购移动端的架构优化实践文中提到的模块管理器、Url跳转管理器。统一管理的意思就是将分拆的某一类小的模块某一些特性放到某一处进行统一的管理。但是这样会存在一个问题,比如前面举例说到的统一开关管理,这造成了开关耦合,如何去避免呢?我觉得可以将开关默认写到自己的模块里边,并公开出修改的接口,方便上层进行统一的修改,以达到统一管理的目的。这样的话,即使这个模块拆离出来,也不会受到影响。但是,这样的话,其安全性受到了一定的影响。架构设计总是这样,你总需要选择一个折中适合自己的方案。
我们通过上述横向分块、纵向分层的方法将一个系统切成不同的小块,这些小块负责某一单一的职责,然后通过接口将块与块之间进行了间接性的连接,依赖的是接口而不是实例,以弱化这种模块间通信造成的耦合。当然,上述模型仅仅只是一个理想状态的模型,如果是一个非常复杂的系统,那么层级之间也能拆分出更多的层级。比如,在数据层,我们在MVP模式的开发下使用Model来完成,当Model层的业务变得非常复杂时,有部分人会考虑拆分出Data层放在最底层,最为最基础的数据操作等。最后,为了方便我们对模块进行组合并进行管理,我们可以考虑在小模块中开放出接口,供上层进行统一的控制管理。最后,我想说的时,我们在进行业务分离拆解时可以考虑按照上述的方案来做,最终还得根据实际情况来进行设计。
4、开发实现
当完成我们的设计工作后,我们进入了开发编码阶段,在这个阶段主要表达我们的设计,并最终取得实实在在的成果。当进入这个阶段之前,我们的设计不能仅仅是一份文档,而应该是开发人员和架构设计者达成的某种共识。再好的设计,也需要获得良好的表达和实现。下面主要谈一谈在实现过程中需要考虑的问题。
(1)、项目分包
项目的分包结构体现一个软件的架构,我们在进行分包的时候总有一种困惑。因为我们存在多种分法,比如我们可以分为根据类的功能分为activity、fragment、adapter、util等,有的时候,我们又根据功能模块分,比如一键搜中有查单词模块、有搜题模块,同时又存在网络请求,软件升级等小的外围通用功能模块。存在的问题就是模块之间又存在一些可以复用的东西,那么我们进行拆分明显出现了代码的冗余。如果按照两种方案同时分,那就肯定存在了架构的混乱。我们该如何达到这两种的平衡?我认为,这个也需要更加项目的大小而来,如果是非常小的项目,也不存业务扩展的可能,我们就可以采用上述的第一种方案,简单的分类就好。但是,对于较大的项目,我建议使用第二种方案。下面,我简单列一个模型仅供参考:
+ app
+main
+com.jfg
+common //常用基础业务
+util
+wedget
+base
+function //通用技术业务
+camera
+sensor
+moudule //特定功能业务
+mouduleA
+model
+presenter
+view
+mouduleB
+model
+presenter
+view
+mouduleC
+demo //主程序
+app
+activity
如上所示,我们根据开始的项目业务拆分分包如上,将常用的基础业务放到common包里边,这个包在大多数情况是不变的,并且为app提供基础性的服务,不过我们尽量不要放到这个common包里边,如果这个common包变得足够大的时候,就一定要思考是不是该拆分了。因为common给人的感觉就是什么都是,那就让我们无法快速认知这个包所担当的职责。我们可以这样理解,common包是面向切面而设计的一些业务,但也不是绝对的。接下来我们先聊module这个包,实际这里是将业务进行了模块化的分拆,如上我们拆分出了moudleA和moudleB,这两者之间要求没有任何的联系。但是,我们会存在一个问题,那就是moudleA和moudleB某些业务是一样的,我们拆开显得重复了许多体力活。这应该是大多数开发者面对的困扰,这种该怎么去平衡呢?我是这么考虑的。如果,moudle和moudleB存在重叠的业务,我们将这些业务提取到function包或者common包中,这样降低了业务的层级。我们允许moudle包的各模块业务依赖于function和common为我们提供的基础服务。为了更好的区分模块A和模块B虽然重叠但在逻辑上是各自属于各自的,我们有两种方法来做。第一种是将两种业务进行一定的抽象,实现的过程还是放到各个moudle业务中。第二种方案定义两个接口类,各自定义各自的接口。在具体的实现类中实现了这两个接口类的方法,内部在进行相同的逻辑操作。这样,对外看来,逻辑上moudleA和moduleB是分离的。总之,如何分包还得权衡利弊,尽量以一种思维来进行划分,以避免设计混乱。
(2)、抽象接口
如果说在架构设计中抽象很重要,你可能有些迷糊,但是如果要你先写interface或者abstract class 而不是class时,你就可能感觉得到抽象的意义。我们将一个系统分解成几个大的模块,一个模块查分成不同的层级,每个层级再次拆分成不同的细节业务。最后,我们很清晰的知道我们要完成某一项功能需要做哪些事?对的,做哪些事就就是一个个接口,我们在编码时先写接口再写实现有利于帮助我们对业务进行拆分和抽象。我们都知道做一件事情一般情况都需要提供一些条件,做完了会有返回结果。这些都可以在接口的设计中完成。我们需要注意是一个接口只做一件事情,如果有两件事非常相似也要尽量拆分而不是合并。在接口命名方面做到见名知意,怎么去评判,就是如果你的接口没有注释也同样能让人知道你的接口是做什么的就好。
(3)、数据存储
数据存储常用的有SQLite、SharedPreference、文件等,缓存是否也可以算是一种。这里想强调的就是要注意数据存储的规范性以及安全性,如果是数据库还有必要考虑其扩展性,如果不满足需求将会需要进行升级。
(4)、性能管理
这里源自于对性能优化的一点体会,对于服务端的开发我们很珍惜服务器资源,应该是看的见的需要银子买的。然而,对于客户端的开发我们常常忽略了这一点。虽然手机设备现在拥有大内存,但是如何写出一个优秀的程序,性能也是一个非常重要的指标。性能优化处理,那是我们在更正错误,那么之后应该是少犯错误。性能体验不够好,无非就是对机器设备的内存、CPU、GPU资源无节制的使用,造成资源的浪费,当机器设备无法承受时就会应用就会出现卡段、死机、异常等不良反应,严重影响了应用的体验。我们要做的就是要有很强的性能管理意识,对于内存、CPU、GPU等资源按需借用,并做到有借有还,即用完后记得释放资源。
(5)、特殊处理
我们在开发的过程中,总有那么多问题并不是按照正常思路出牌的,这些得归功于我们强大的测试团队。不同的手法,就能得到不同的结果,然后就给了我们一堆的bug。所以,我们在软件的开发中需要特别注意一些特殊情况的处理,这些最终往往还是逻辑上的死角。以下简单总结了一些:
功能冲突
功能冲突可以分为两种,一个是应用内部的功能冲突,二是应用之间的功能冲突。应用内冲突比如A功能和B功能都使用了某资源文件,如果在同时使用就会出现问题,我们通常加同步锁来防止这种冲突。应用外的冲突有很多,比如多媒体、闹钟、日历、铃声、电话等都肯能引起这些冲突,比如你正在播放一段视频,这个时候来了一个电话,那我该优先哪一个呢?还有当闹钟响起的时候,弹出一个界面是竖屏的,那么他就会强制将当前的界面变为竖屏,而如果你这个时候如果是横屏的话该怎么办呢?类似于这类还有很多,以后再细细总结。
极限操作
我们的测试人员喜欢对着某一个按钮狂点、或者在机器上安装无数的应用使内存爆满,或者在磁盘里边塞满各种文件。这些场景虽然并不是理性的用户所出现的,但实际也是程序的缺陷。所以,我们要注意对这些问题进行处理。
网络问题
不可用的网络,信号很弱的网络,网路在wifi和流量之间切换,2G网络和4G网络,网络请求超时等都需要我们针对实际情况进行处理,比如切回到流量的时候进行下载是否有提醒用户。这些处理也算是各个应用的标配了,就不再多说了。
为null处理
这应该是最常见的问题了,我们平时改bug或者从后台异常抓取的大多数都是空指针异常。首先,我们得搞清楚为null的原因是什么?然后我们需要进行为null的判断,并警告。
(6)、Log打印
这里把Log打印单独拿出来是应为我觉得很需要重视。Log是用来干嘛的?很显然是用来帮助我们查找问题的,然后我们大多数的情况下是问题来了再去加打印,并且TAG五花八门的,是有错误的地方用Log.d,而只是查看信息却是用的Log.e,我们查问题的时候要去阅读很多的代码逻辑,最后再定位到位置。我们在修复bug的时候花了大量的时候再阅读代码,这个太影响工作效率了。如果我们在编码之初就对Log有了很好的规范设计,有异常的地方就用Log.e,可能出现问题的地方就用Log.w等等,关键点的信息用Log.i,临时调试的用Log.d这样区分不是很好吗?我们在控制台一样就能够分辨自己需要的信息。我们应该充分应用这个工具,帮助我们快速定位问题。
(7)、软件重构
重构是因为业务的需要,也是因为对代码更高的质量要求,重构无处不在。我们不要为了重构而重构,也不要一直停滞不前,该重构时不重构,欠下太多的技术债务。重构有小到一个方法的重构,也有大到整个系统架构的重构。重构是软件迭代升级的一个必要过程,也是我们能够满足当前需要,并且能够适应未来的发展,获得良好的扩展性的必要手段。重构并不难,也不是什么大事,重点在于重构背后的目的、思想、设计是否清晰。
(8)、兼容适配
兼容适配的问题是我们开发一个头疼的问题,Android设备无法八门的屏幕尺寸、层次不齐的Android系统版本。除了进行针对性的处理,还得提醒产品设计人员在设计之初就得考虑兼容性问题。
5、软件测试
软件测试是我们开发中非常重要的一到工序,除了能够客观的感应我们所开发的软件质量水平,最终目的还是在于帮助开发人员修复软件缺陷,提高软件的质量。除了开发人员提交测试之前的自测,我们需要专业的测试人员来进行测试。人工测试的效率相对较低,所以我们应该考虑通过技术手段完成自动化的测试,如单元测试等。这样有利于软件的稳定,也同样的有助于开发人员提高代码质量。
6、开发规范
(1)、设计一致
什么样的设计才是有规范的设计呢?我个人认为一个项目保持一致的设计思想就是有规范的设计。我们可以这样去理解,在某一类的情况下,我们按照某一类似的方案来解决这一类问题。面对复杂的系统,我们一种设计思想也许无法满足架构的需求,但是我们只需要明白,这种事情这么干,那种事情那么干,相互之间灵活的组合却也不存在交叉,给人设计思路清晰的感觉。
(2)、编码清晰
什么样的代码才是高质量的代码?我觉得结构简单,逻辑清晰,一看就懂的代码就是一份高质量的代码。所以,我们可以抛开那些编码规范、命名规范等等,重新去审视自己的代码,看看读起来是不是很舒服。如果来了一个新同事,对你对项目一无所知,是否能够很快速的理解你的思维?最后几点有必要提出,一是慎用设计模式,二是尽量少写文档注释,三是遵循Java的面向对象六大设计原则。我想这三点就是编码的原则,遵守这些原则,形成一种习惯,自然而然就是一种规范。
(3)、文档有效
什么样的文档才是有效的文档,我认为能说明核心问题的文档就是有效的文档。作为软件开发人员,我们没有耐心去阅读一份复杂啰嗦的文档。文档只需要给我们呈现代码无法说明的问题,帮助我们快速理解项目结构,备忘重点问题,追溯历史记录。文档的形式又很多,比如我们git的提交记录、tag,项目结构图、核心功能流程图等。总之,文档是给人看的,以尽量少的文档来说明核心问题就好。
7、日常工作
作为一名合格的软件开发人员,我们有许多的日常工作,如Bug修复、异常处理、Monkey、性能优化、代码质量改善等待。这些事情并一定要求你每天都要做,但是每天都得关注,做到心中有数。如此,才能够培养一个很好的编程习惯,写出优秀的代码,优秀的程序。
1、开发驱动
一个项目的正常运转一定是由某一方主导项目的进行,不断的提出产品需求,并组织项目成员分工合作,完成产品的开发交付,以下是两种驱动开发模型。
TDD:测试驱动开发(Test-Driven Development)
测试驱动开发指的是由测试主导开发的工作,从产品的使用出发,对产品的功能提出测试要求,组织项目中各个角色完成开发任务。
BDD:行为驱动开发(Behavior Driven Development)
敏捷开发便是行为驱动的开发,更加强调产品的设计,鼓励项目中各个角色提出自己对项目开发的观点,已获得更优秀的产品功能,完成产品的开发。
2、敏捷开发
下图引自网络上的一张关于敏捷开发的图片,目前我们团队基本也是根据这个模型进行敏捷开发的。我觉得在敏捷开发中更加强调的各个角色之间的随时沟通和快速响应,我们并不对整个系统进行一份完整而详细的设计,而是进行阶段的设计开发工作,并谋求不断的迭代更新。在敏捷开发的过程中,普遍存在的问题就是沟通不及时、产品变动大,所以如何动态的进行统筹管理变的非常重要。我们通过需求评审、交互评审、视觉评审、Bug评审等由各个有关角色的人员参加评审会议,共同完成决策,以保证软件开发的顺利进行。不得不说,这个过程中还是存在许多的问题,沟通的问题,产品变动的问题,产品功能细节开发过程的中流程性的问题等等,在此不详细说了,后期有时间再进行总结。
3、达成共识
敏捷开发中有一个特点就是,产品开发决策是由项目各个角色成员共同完成的,各个角色领域的问题又是由该角色自身最终拍板。那么随之而来的就出现了一个问题,各个角色所决定的问题又被其他的角色所制衡。比如说,产品经理设计的功能在开发人员而言存在技术难题,交互的设计存在逻辑上的漏洞。我想,这些问题是一个产品不能按照预期时间完成的真实原因。那么,哪一个角色来统筹管理这些问题呢?通常,我们有架构师、项目经理、老板等等角色来对项目进行把控和管理。
软件架构的设计来源于产品的需求,并决定了产品的最终形态。然而处于敏捷开发中的我们而言,产品的需求变化很快,同时要求我们开发人员能够快速响应这种变化。那么,如何保持软件的整体架构和产品的设计同步更新就显的非常重要。
对于开发者而言,我们首先要对项目有一个整体的认知,随时掌握产品的动态。这些包括产品的设计、迭代计划、开发资源、质量要求、交付要求、风险规避方案等。然后根据产品的需求变化,动态调整自己的软件架构,这些工作包括,技术选型、架构设计、代码重构、文档更新等,以适应新的需求,并把这种架构共享给相关人员以达成共识。这种共识,是需要对产品和技术进行统筹规划才能够完成的。也只有项目各个相关利益人员能够达成这种共识,我们的沟通才会更有效,才能做出各方人员都满意的产品。
写到最后,我回过头来看看,才发现对架构的整体认识站在了决策派的一边,即这种共识便是在产品规划、设计、开发阶段一些重要方面所作出的决策的集合。这些决策是我们项目各个角色成员通过计划会、评审会、迭代会等达成的共识,并最终表现在我们的产品上。产品、交互、UI、开发、测试,每个角色对自己所在领域负责的同时也需要随时掌握其他领域的信息,以便自己做出正确的决策。但是在对软件技术实现的架构设计上,我就偏向了组成派,将软件系统的业务进行了拆分和组合,已达成系统运转。我必须承认,此刻我的认识还是不够通透,在本文中各个方面大多还是泛泛而谈,每个问题深入下去还有许多可以去研究的,希望能够在以后的工作能够有更深刻的领悟,在此也恳请各位朋友批评指正。
《小钢的架构思考系列》
饿了么移动APP的架构演进
携程移动App架构优化之旅
糯米移动组件架构演进之路
苏宁易购移动端的架构优化实践
Android App 整体架构设计的思考
android开发一般都使用什么框架?
手机天猫解耦之路
什么是 Agile Software Development(敏捷软件开发)?
从MVC到MVP,记我的两次项目重构实战经历
《架构之美》
《软件架构设计》
《架构之美》
《软件架构设计》
《人件》
《人月神话》
《简单法则》
《Coding Dojo Handbook》
在这一年的项目开发中成长了许多,当然也必须得承认我目前水平远远还不够。这一年里,我的公司给我提供了学习与实践的机会,我的Leader给我思想上的启发,我的同事给我耐心的指导,几位前辈百忙之中解答我的疑惑,许多博客书籍作者的知识分享。在此真心的感谢你们。
经过这段时间对架构的学习和思考,我发现这些理论不仅可以运用在软件架构中,同样也适用于工作、生活当中。试着将我们的工作任务进行分离,减少每项任务之间的交叉,避免东一榔头西一棒子,有条理的完成各项工作。这样一来,你的工作目标是清晰的,也更加容易的完成既定目标。同样的,我们可以通过这一理论还规划自己的人生。将我们的事业、家庭、兴趣爱好分离,再对每一项分离出更细的关注点,每个关注点在不同的阶段定下自己小目标。这样,我们对自己就可以有了更清晰的认识,认识自己已经拥有什么?最终想要什么?计划怎么做?当前怎么做?当然,并不是每一步都是能够按照既定目标走的,我们需要不断的更新对自己的认识,做出更加合适的决策。
在此预祝大家新年快乐,最后来一波广告,欢迎大家关注Open软件开发小组公众号open_dev。
本文版权归Open软件开发小组所有,如需转载请联系主编申请授权。
申请加群交流学习请加主编微信:Jf-1994(井方哥),并备注:姓名-地区-公司-职业-加群。
专注Android开发,欢迎关注open_dev!
本文分享自微信公众号 - Open软件开发小组(open_dev)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
来源:oschina
链接:https://my.oschina.net/u/3735058/blog/4468558