ET新版本,我从2014年10月进入开始着手做,一路做过来有很多收获,同时也发现很多问题,
其中问题主要集中在以下几个方面:
- 代码风格
- 界面端过多使用没有必要的C++类
- 代码模块划分
- 关于和界面和内核交互有没有必要全部走GCD并且异步
- 分工问题
下面就逐个描述遇到的问题:
1.代码风格
代码风格不只是简单的写代码的“书写”规范(代码美化),还有是否遵循苹果一些 代码结构模式
、变量命名
、接口设计
问题等等。
我记得赵永奎第一次讲座就讲到这个问题,我当时只是意识到了简单的代码“书写”规范
问题,而对他讲的关于是否遵循苹果的代码设计结构(MVC)问题没有很深的理解。经过这一年多的工作经验,我深刻的意识到这个问题对:代码维护
,代码复用
的巨大影响。
其中下面两个方面,我认为是最重要的:
a.代码结构
首先,在ET新的版本中,我能做到经过我写的功能块,做到遵守视图、数据、逻辑控制三部分分离,这样做的好处就是我拆除了某一部分对另外的两部分都没有影响,并且如果某一部分写的足够好,是可以拿来复用的,对于View
来说,不混杂业务逻辑和数据的View层,是最具有复用价值的,苹果最具代表性的就是UITableViewView
,业务逻辑和数据都交给代理和数据源去处理。
而在目前ET的工程中,很多代码很难遵循这个结构,太多的类明明是继承与一个视图类,但是发现业务逻辑也全部混杂在其中;一些类明明是处理业务逻辑的,但是发现这些类中又去处理了视图的逻辑,真实让人无法理解。某写类型或者函数完全没有做到遵守职责单一的原则,以至于后来用的时候,发现很难理解这个类设计的初衷是什么。
在我看来,一个功能块,如果要独立,分成视图、业务逻辑、数据三部分是必须的,即使一些界面不需要独立的控制块,控制逻辑也要放在别的控制类中,而不是视图中;如果想要做到三个组件共用的功能块,那么因业务的不同,数据、业务块可以看需求省去,但是视图必须完全独立,不依赖任何数据和外界逻辑,只用提供足够的业务功能接口和代理、数据源,供控制层根据数据变化操作视图变化即可。
b.书写风格
其次,第二个问题就是代码书写风格问题(代码美化)
我个人是要求自己遵循一种风格去写,也基本遵循近苹果的风格。其实最终遵循谁的风格去写都是无所谓的,只要这种风格是大家公认的,就没问题。
目前在ET,就存在多种编码风格,奇怪的a式命名法,方法函数肆意的打空格,最不能理解的是无意义的注释和日志打印。OC的命名规范已经代替大部分注释,虽然结果是使得代码变的很长,但是好处在于省去了不必要的注释,所以在加上无意义的注释,只能使人读起来非常累。所以,虽然我向往统一编码风格,但是绝对不是统一成不遵循苹果写法风格。
禅与 Objective-C 编程艺术这篇文所说的条例,ET的项目中很多都是违背的,究竟孰优孰劣,我想大家都有自己的评判。
2.界面端过多使用没有必要的C++类
ET新版本最开始的时候,峰哥坚持界面的每个功能层次外面都要套一层C++类。
当时针对这个问题和他进行了长久的争论,最终废弃了这一层完全没有必要的东西。
首先峰哥的观点在于:
1.OC的代码用C++包裹起来,就有了安全的保证。OC太灵活危险了,灵活到有时候无法控制,所以要用C++将他堵死(这一句是原话)。
2.C++有命名空间,能更好的隔离。OC没有。
我的观点在于:
1.我一只没有明白峰哥所说的OC灵活的危险弊端在哪里?这个问题那段时间和肖斌也讨论过,结果也是不明白。动态语言和静态语言相比,不灵活怎么叫动态语言。OC是有很多hack的方法,但是我想对于我们日常的大部分开发来说,很少有人谁去用那些hack的方法吧,所以包一层C++的作用何在?
并且最关键的问题在于:OC有很多语法特性,C++是不具有的,本身如果是写界面时纯OC去写,KOV
block
delegate
等等在oc代码之间衔结的非常好,但是中间夹杂了C++的一层,着实让人无语。
2.关于命名空间问题,OC类沉长的命名法为的效果就是达到防止命名冲突,只不过隔绝的方式不是命名空间那样隔绝,这一点OC确实做不到。
3.关于C++那一层的职责定位问题。
虽然我在外面写的界面部分没有再包一层C++的类,但是在etios模块仍然使用这种规范。我看了很多包的C++的那一层,我没有理解那一层的职责在哪里?有的那一层C++的类只是传接口,完全没有别的功能,只是在传递函数;有的又是混杂了业务逻辑,在起初,我以为那一层C++类是用来处理业务逻辑,即代替C层的,但是最终发现完全不是那个定位,所以关于那一层的职责,我不太理解。
3.代码模块划分
这个问题主要集中在et4ios那个模块中。
说et4ios是一个模块,其实根本不好定位这个模块到底是干嘛的。
新架构初期,et4ios的定位是真正内核外部的一层映射,算是靠近内核层的中间层,衔结界面和内核。
但后来发现并没有那么单一,目前et4ios中混有以下几个部分:
- 1.衔结内核的中间层。
- 2.编辑框的界面模块
- 3.表格区(手势,界面等)
这就违背了最开始设计的初衷,也导致一个问题:这个et4ios到底是干什么的,有内核?有界面?什么都有?
其中把原本同属于界面的东西放在了另外的一个模块,导致的结果就是界面的创建没有层级结构。本来编辑框 和 表格区 应该由界面端去创建,现在完全不是这样,而是由内核中间层去创建。导致真正调用的时候需要走从内核单例中去一步一步取到编辑框的对象,然后进行操作。这样合理吗?我实在想不出内核中间层去创建界面的依据是什么。
而且编辑框也是通过C++包裹起来,那么我真正想操作编辑框时,其实这层C++起到作用就是重新写一遍OC对象的接口,完全没有别的意义。这么冗余,为什么不直接调用呢?(参考2.界面端过多使用没有必要的C++类)
本文提到的前5点问题,编辑框中全部都存在
4.关于和界面和内核交互有没有必要全部走GCD并且异步
目前ET几乎所有的和内核数据的交互都走得GCD
简单点说,就是不管 读
或者 写
内核数据都是跑在 异步在串行的子线程上
目前有以下几个问题需要讨论:
a.被迫所有内核数据读写使用异步GCD
一旦有一个对内核的 读
或者 写
的操作走的 异步串行子线程
,那么之后所有的对内核的 读
或者 写
都要走 异步串行子线程
,原因在于只有这样才能让所有对内核的操作在一条队列上保证先进先执行的时序。所以时常读取一个非常简单的数据也要异步,等待回调,这样给功能实现上增加了不少的麻烦。
b.如何保证时序性?
因为对内核的读写是异步子线程操作,内核在子线程跑完之后同步回调主线程,所以如果存在异步套异步的现象发生,仍旧不能保证对内核操作的时序。(这种情况在在目前ET中是存在的)
c.一个操作,需要多次异步时怎么办?
回调问题。例如 操作A
在执行之前需要请求一个 数据X
,然后拿到 数据X
后再做相应的 操作A
。因为对 数据X
的请求也是异步的,所以要在请求 数据X
的回调代理中去执行 操作A
。这样一来就显得有些问题了,原因在于为什么要在请求到 数据X
的回调去执行 操作A
?这两个事件并没有什么必然联系。
所以后来我在解决这个问题时用的方法就是设置 completionBlock
闭包块。即在请求执行操作A
的函数中写请求 数据X
并且设置 completionBlock
为执行操作A
,在 数据X
回调时执行这个 completionBlock
,这样以来就显得不是突兀了,因为 数据X
回调不用关心具体要干什么,只用执行 completionBlock
即可, completionBlock
在之前就已经设置好了。
当然这并不是最好的解决方案,最好的方法是仿照网络请求回调,Block
+ delegate
共同支持,以场景需求选择 Block
或者 delegate
才能写出最优雅的代码,毕竟 Block
和 delegate
使用场景还是有很大区别的。
d.究竟有没有性能的提升?
1.从目前这个GCD设计模型上来看,只是把读写操作放在了另外一条 串行子线程
上去跑,既然读写操作依旧串行,那么必然效率是不可能提升的。唯一的不同是,子线程读写内核时主线程不再卡顿了,但是回过头来想:既然子线程读写内核都已经卡主,那么主线程不卡有什么实际意义吗?ET大部分操作都是建立在和内核的交互,还是要跑在 串行子线程
上的,所以子线程卡主时主线程不卡并没有什么实际意义。
2.既然没有效率提升,那么有没有效率降低呢?
因为目前几乎每个读写内核都要经过两次线程切换,即 主 ->(异步) 子 ->(同步) 主,大量线程切换是有损耗的,这个损耗我具体没有研究过,但是就目前ET这个GCD使用密集度,损耗应该还是有一定影响的。
5.工作效率问题
ET之所以拖这么长时间,问题就是重复性工作导致的效率低下。
最典型的就是编辑框,从去年的11月就开说这个东西属于比较中枢性的东西,很多东西的交互都跟它有关系,并且本身也是个有些复杂的东西。
当时如果按照原本的东西去做,不要去追求微软的样子,我相信早已完成了。这个东西最起初峰哥对很多细节和业务都不了解,我相信至少做过一边的肖斌是更有发言权的。只是他觉得能做出和微软一模一样的。结果呢?从峰哥转到肖斌,峰哥不满进度,又要自己重新搞,最后又抛给文强和荣华去做。从一开始的要重写编辑框那个基础控件,我们就告诉他没有那个必要,并且不好写,结果导致浪费了很多时间,最后编辑框依旧是老样子。
分工问题导致效率低下的一个表现是:某些功能是A写的,最后这些东西又交给B去处理,首先在我们组,我和文强对OC代码结构和写法的理解有偏差,说句实话,让我去看他写的代码,有些地方的写法我是无法接受的,所以看起来也比较没有耐心,这点是我的问题。我深知工作中这种交叉debug事情是不可避免的,但这个问题应当做到影响面最小,即尽量避免工作内容倒手。所有这也是后期可以改善的一个方面。当然这一点对于实际的项目工程来说是很难完美实现的,所以后期只能尽量避免过多的发生此类事情。
写在最后
以上的5点是我对这将近一年的新版本开发过程中遇到问题的总结,可能些许带有一些个人情感,如果有哪些写的欠妥,我们可以提出来一起进行讨论。
希望今后的工作中针对这些问题进行改善。
感谢阅读。
网友评论