您好,欢迎访问三七文档
iOS代码实践总结前几个月完成对MVVM/RAC的学习之后,最近一直在默默地对项目代码进行重构,写码比较多,过了一段时间回头发现自己的代码风格还有代码质量都有大大的改善。过去几年在一家小公司负责iOS客户端后来负责客户端的研发工作,被杂乱的事情分神比较多,所以到去年的时候,写码已经不太多了。在新公司待了大半年,目前只是写码的小角色,所以精力基本上在写业务代码和业余学习乱七八糟的技术上面。最近一个月除了专门抽时间和精力重构之外,还有就是遇到需要添加功能的模块的时候,由于项目中的代码历史因素比较多,第一件干的事情往往是重构整理代码,发现很多之前的代码写的时候没有注意的事情特别多,比如全局变量乱用;方法没有层次感,胡乱添加;对业务不了解的情况下,通过打补丁的方式实现功能等等。所以我决定写一篇文章,把自己的觉得实践中需要注意的一些事项,具体总结一下分享给大家。减少对象属性这个是最容易改善代码质量的一个点,很多代码一眼看上去就会让人感觉很凌乱,一上来就是几十个不同的对象变量定义在里面,这让不同逻辑之间莫名其妙没法分开。一个是定义的方式不对,很多莫名其妙的内部变量暴露在头文件中,让外部调用者根本不知道哪些才是public可以操作的方法。另外实际上,经过我自己这段时间的重构经验来看,大多数是可以通过局部变量或者__block变量来代替的。1.头文件中尽可能少暴露变量或方法,而要使用extension或者category放在.m文件,或者专门的private头文件中头文件中暴露的信息越少越好,一切不必要的信息都不要暴露出来m文件的extension中,定义conformsprotocol和对象属性,对于对象属性的定义,使用getter/setter来定义。2.使用局部变量或者__block变量代替局部变量不需要多说,需要写码的时候思路清晰一些,写完之后在commit之前即使review一定要check一遍,对自己的代码质量负责,codereview往往检查不出来冗余或者废弃的代码。不添加一个多余的对象属性,不留注释掉的代码,不留没有用途的代码,这些都是基本功,但是很多开发者就是做不到,或者说对写码没有爱,所以很多废弃的代码,我重构代码的时候,虽然对业务不熟悉,但是大多数模块都能删除掉十分之一的代码和大量的对象属性,这个是单纯的不够用心。关于使用__block变量,这个是Android开发中我感觉到最不满意的地方,这个特性简直太他妈爽了。比如这里,使用block的时候回传一些变量再比如这里,我需要记录一个pan手势开始时,headerView的顶部坐标,结合RAC之后,本来需要全局变量来记录的值,使用__block变量即可搞定3.可以尽可能避免循环引用有个地方很多开发者会疏漏,在block中使用_XXX对象变量的时候,block会retainself指针,一不小心就会造成循环引用的出现。所以使用局部变量的话,就能扼杀这种问题在摇篮之中。减少和模块化对象消息1.减少对象消息减少UI的action类消息,感谢block和RAC,或者blockskit,让我们得以通过hook来把之前target-action模型换为block来实现,UI和action的代码终于可以一起了,使整个逻辑变得紧凑,在查看代码的时候终于不用跳来跳去了。还有就是日常开发中,把自己写的各种protocol或者传递target/selector的地方,尽量使用block来代替,相信我,这个会使代码好读很多。2.模块化使用”#pragmamark-XXX”进行分割不同逻辑之间的界限,让整个文件阅读起来更加结构化。还有一个我现在最常用的就是是设置Xcode的快捷键,把Ctrl+6显示文档结构的快捷键改为:Command+J,搜索来快速跳转到对应的消息和模块,要尽量避免文档结构显示超过两屏幕,超过两屏幕说明有点多了,你肯定考虑一下重构了。我个人习惯一般划分的模块有:lifecycle,uihelper,datasource/delegate,依据功能进行划分的模块等等,如下是我最近重构的一个ViewController的文档结构MVVM&&RAC我自己使用MVVM思路的感觉是太爽了,说一下,MVVM不一定需要使用RAC,但是databinding少不了,在iOS中也就是KVO了,建议大家都去尝试一下,我自己感觉这个基本上MVVM的最核心的东西了,连AndroidSDK也不得不引入这个特性。把数据部分的逻辑抽取放在ViewModel中,然后让UI和ViewModel中的数据binding,这个不会减少代码量,但是绝对可以大大简化开发时逻辑的复度,再也不用重写-setXXX:方法来update一大堆不相关的UI了,关于UI开发,后面会专门再讲讲新的。这里说一下我自己的理解,有人说RAC影响性能,回调栈太深,这个的确是会有的,但是个人感觉RACObserver是基于KVO实现的,调用的时候是同步调用的,所以对性能的影响有限,也不会出现调用顺序的问题,所以我敢在列表开发中使用databinding,实践之后还好,对用户体验没什么影响。关于RAC,即使你不使用RAC,有一些东西也是绝对值得你在项目中引入的,比如@weakify(self)/@strongify(self),通过预编译查看的话,这个的做法是设置一个局部变量self来覆盖全局的self,进而避免循环引用的,需要注意的是block层次较深的时候使用的问题,。RAC/MVVM,我刚开始学习的时候,写了两篇文章,算是我自己的总结,理解上面还有不足,跟大家参考一下:,。大家可以通过我博客中文章的参考链接学习。UI开发1.重写setter方法和CodeBlockEvaluationCExtension语法重写UI的getter方法,把UI的初始化放在getter中,减轻-viewDidLoad的负荷,同时可以使整个页面变得清晰;同时,可以通过使用使用GCCCodeBlockEvaluationCExtension({…})语法,结构化局部变量初始化和处理的逻辑。关于这个语法,参考我之前的博客:。关于setter代码风格,可以参考别人写的一篇文章,,这个问题之前在我们Q群里探讨之后我也非常认同这种方式写UI。举一个例子,-viewDidLoad中,做为逻辑的入口,代码会变少但是变清晰,代码如下:然后重写bgView的getter方法,包括View和frame这些都可以使用({...})语法使代码结构化层次化:2.复杂UI的开发有时候我们开发业务的时候,产品需求往往非常复杂,酷炫的UI加上各种考虑全面的逻辑,这个的结果就是,码农的超长代码,而我们平时工作面对的也大多数都是这类问题。关于这个问题,我的解决方式,组合式UI/customview/childviewcontroller来解决。(1)组合式view这个概念是从Android中借鉴而来。重构时查看项目中的代码,发现大家用的做UI的时候,对这个概念不是很强烈,感觉是对UIView的viewhierarchy理解不够。比如一个复杂的UI,直接把所有的subviews直接堆积到superview上面,这样的结果就是,调整subview的frame非常困难。我个人的做法是,首先对复杂UI进行分块,从左到右或者从上倒下,把各个UI元素放到不同的containerview上面,然后组合这些containerview放到superview上面,这样的好处非常明显,首先UI干净清晰,阅读起来不那么费劲。其次就是你计算坐标或者设置约束会变得很简单,因为你调整一个UI元素的时候,只需要考虑它与包含它的containerview的坐标关系即可,而不是通过一大堆无趣计算跟最外层superview关联起来。还有就是可以充分利用AutoLayout和autoresiziingmask这些UI利器,使用的时候会非常方便。再有就是结合RACObserver这个利器之后,你能很容易做到根据data来updateui。举个例子,是我们项目中前一段时间我重构的一个页面,这个首页列表,性能要求比较高。并没有使用AutoLayout来实现,但是不使用AutoLayout并不是不把它写的很干净的理由。这是我对一个UITableViewCell的分层,最外层由iconview/rightview/bottomview这些containerview组成,而rightview这个containerview则又是由righttopview/rightmiddleview/rightbottomview这些subcontainerview组合而成,而具体的UI元素则是放在这些subcontainerview之中。这样UI代码就会以一种层次化样式展示出来,init/layoutsubviews只需要维护self与containerview的关系即可,而具体展示数据的UI元素也只跟subcontainerview存在坐标关系。我们看一下rightview这个containerview的代码实现:关于性能的话,感谢iOS,我们不存在Android中页面层次较深性能卡顿的问题,放心把UI层次化就行(2)customview对于非常复杂并且相对独立或者可以重用的UI,及时使用customview子类化。对于单纯的展示UI,我们只需要简单通过组合式view就可以实现了。但是有时候,我们会遇到一些包含无论是动画,逻辑都比较复杂的情况,这个时候使用组合式View去实现,一方面容易把逻辑弄混乱,会把文件的文档结构变得很复杂,简单来说就是对象的消息数量很多。这个时候,我们可以通过customview来实现,实际上这个也是组合式view,但是我们是把这些组合式view变成了一个类而已,只暴露少量的接口给外部调用。如果这个customview会出现在多个业务模块中,那么有必要使用一个单独的文件来容纳这个类,如果仅仅是这个模块一个使用的话,可以直接写在这个业务模块的文件中即可,没有必要对所有的类都单独一个文件,我们就当作这个“内部类”来弄了。什么时候使用customview而不是组合view,我想了很久,你觉得组合式view的代码很乱的时候,别客气,包装为一个customview就行了。我这边最近遇到的几个问题是使用UICollectionView来做部分UI的时候,同时还有其他很多UI元素,我会写一个customview。比如下面这个文件,把一个左右滑动查看图片的UI使用PhotoView这个customview进行包装,内部使用UICollectionView实现一部分相对独立的模块,这个时候这个控件实际上是可以包装为一个相对独立的模块的,用子类我感觉比较合适一些。(3)containerviewcontroller这个用法很多开发者不熟悉或者说是用的不多,但实际业务中,这个技术非常有用途,可以大大提高开发效率。对这部分知识不熟悉的,可以参考我之前的博客:。对于有相对独立业务逻辑以及生命周期要求的业务,使用childvi
本文标题:JAVA设计报告
链接地址:https://www.777doc.com/doc-2878990 .html