我是一名iOS开发的程序员, 我喜欢程序员的称谓, 当然了, 公司会给我面子, 赋予各种超越我工作范畴之外的职位称呼, 但不管什么称呼, 我最爱的, 就是开发工作本身, 这是我的狂热所在. 我做过十三年的开发工作, 按照普通人的想法, 这么大年纪了, 应该放弃开发, 转而做管理工作, 但我偏不, 这种固执, 别人很难理解, 而我很享受. 但我仍然觉得很遗憾, 那就是一直觉得自己往往在项目过程中, 没有摸到真正的门槛, 这个门槛, 就是对自己工作本质的总结, 在代码工作本身之上的原则总结.
第一原则: 相信标准
我们程序员往往特别自以为是, 所以, 很多时候, 我们都会无意的去创造标准, 并为自己的创造成果而得意, 但是, 这种做法, 并不是达到最大化效率的做法, 其实也很难提升自我. 举个例子, 现在的HTTP API, 一般都是Restful, 它有一种相对比较规范的准则, 但是, 我们的开发人员往往懒得去学习Restful的规则, 或者参考别人比较成熟的规则, 而是自己创造一套规则来做. 比如HTTP Body的设计, 有自己的标准; ErrorCode的设计, 放弃HTTP Status Code, 而是自己创造一套规则; 加密有现成的SSL可用, 但是非得略过HTTPS, 采用自己的一套加密方案… 这样的例子很多, 总结起来, 就是不相信标准.
当然, 相信标准, 是有成本的, 至少, 得去学习标准的组成内容, 这就是学习成本, 程序员的偷懒是众所周知的. 但是, 这其实并没有真正的偷懒多少, 因为, 放弃这种公共的经过深思熟虑的标准, 就意味着, 你得额外支出创造成本. 初期来算, 创造成本很低, 但是, 随着需求的细化, 会发现, 实际上自己做的一套东西, 远没有那些公共标准来得简单靠谱.
第二原则: 封装不是为了当下方便
这是很多开发人员的一大通病, 尤其是开发的初学者, 特别喜欢做封装, 而对封装的目的缺乏规划, 于是, 开发中遇到的问题, 觉得可以快速重用的, 赶紧封装一个, 看似这样的代码有一定重用性, 其实, 这种封装的代码, 换了一个项目, 就没有任何参考意义. 我相信, 代码本身有其灵魂所在, 那就是代码的价值, 它是通过开发者使用自己的智力成本为其价值加成的, 如果只是简单的为了接下去的工作简单一点, 就随意的封装一个类或者一个函数, 那这段代码的价值, 其实是很低的.
真正的封装, 是为了一个相对较长时间和较广范围的代码组合, 在我们封装的过程中, 其实是会增加当下开发的工作量的, 而不是减少工作量. 但是, 它会获取更长时间和更大范围项目内的更少的工作量. 所谓封装, 也就是放弃当下收获, 去换取未来的收获.
我在代码中, 经常见到初学者们会犯这个错误, 比如我遇到一个开发者, 在一个UIWebView中, 封装了一系列功能, 而这些功能其实是这个项目独有的功能, 他最终, 很得意的在UIViewController中很简单的调用各种功能, 确实, 看起来UIViewController中的代码变得非常简短. 但是, 问题最终来临, 在于我们需要修改一些功能的时候, 任何稍微动一下的功能, 都要到这个封装内部去研究它的逻辑, 大量的工作量平白无故的增加. 自那以后, 我对下属们强调一个原则, 那就是封装一定要控制, 而不是为了封装而封装.
第三原则: 单一行为
我们在类的设计中, 往往会提到面向对象的一个设计准则, 那就是单一原则, 就是一个类只做一个事情, 这个原则, 很多人都知道, 其实, 这个在我们开发的过程中, 我们的行为, 也应该有单一原则. 比如, Git的每次Commit一定是单一的行为; 每次写代码的过程, 只围绕着一个模块范围等等.
这样的做法, 会额外增加一些负担, 比如, Commit粒度太小, 就需要开发者准备很多内容, 无意间增加了工作量. 即使不增加负担, 随手的习惯也会破坏单一行为, 比如, 写代码的过程中, 突然发现另外一部分代码中的一句代码有问题, 随手也就改掉了. 可是, 我们世界往往没有那么简单, 尤其是程序规模化到一定程度后, 看似不经意的一句代码, 总会导向一个未知. 运气好的时候, 这句代码直接改掉, 并且解决了一个bug, 运气不好的时候, 这句代码, 还影响了别的代码, 于是, 我们可能需要再”顺手”去找另外的问题, 还有运气最坏的时候, 因为这句的改掉的代码, 我们会为自己埋下一个未知的bug.
在实际的开发工作, 我的建议是, 在手边随时准备纸笔, 遇到不是当前需要解决的问题的时候, 随手给自己在纸上做一个记录, 提醒自己待会回到这里来. 或者, 如果你提倡无纸化办公, 可以加上一句TODO注释, 做完当下的工作之后, 搜索一下代码中TODO, 来解决之前遇到的”顺便”问题.
第四原则: 管理关联
在我们的代码中, 经常会遇到代码模块和另外一个模块之间的关联, 这种关联, 就是程序的逻辑流向. 比如, 下载工作完成之后, 向另外一个模块发送提醒, 以便另外模块执行它应该去做的一些工作. 这种关联行为, 有很多, 比如回调函数(Block/闭包), Protocol, 信 量, 通知, 跨域变量(如全局变量), 数据存储, 文件变更, Sokect/HTTP… 理论上, 这些行为都是模块关联的形式, 对于关联的形式, 我们必须有一套相对比较规范的准则.
首先是, 关联形式要尽可能的单一, 一个模块跟另外一个模块的信息流向, 要尽可能的单一, 不能是各种关联形式都有, 那样的结果是一旦开发者离开, 其它开发者很难一下子摸清这段代码的结构.
其次是, 尽可能使用轻量的关联形式, 比如, 两个模块, 回调函数就比通知轻量, 通知要比跨域变量轻量, 轻量指的是代码理解上, 回调函数写在函数参数变量中, 实际写代码的时候, 代码提示就会提示我们去做, 不需要做额外的形式补充工作. 而通知是一种弱关联, 另外一个模块未对通知做回应, 代码是没有提示的. 跨域变量更是不可捉摸, 随时无法会出现一个无法控制的状态, 那么, 它的使用成本自然会更加高.
在实际的代码中, 尽可能将所有的关联形式以代码或者注释的形式, 标注出来, 以方便后续工作的进行. 比如, 通知, 尽量要有统一的管理地方, 比如类头部, 或者独立的文件; 回调函数尽量写在函数的参数中, 而不是成员变量(请思考为什么); 跨域变量, 要在注释中明确的说明它的功用….
第五原则: 微重构
作为程序员, 我反对任何一段守旧的代码, 总是希望在重构过程中体现出自己的开发能力, 但是, 我知道, QA人员不是这么看的, 对于已经测试好的代码, 总是希望开发人员不要动了, 而是以扩展功能为主. 这里没有任何一个意见是错误的, 有时候, 哪怕我们加入新功能, 并不是一段新功能, 而是在老代码身上做手脚, 这时候, 势必会影响老代码, 而如果老代码本身有问题(事实上, 所有的代码都一定是有问题的), 开发人员重构一次的成本反而比在老代码上动手脚更低, 所以开发人员自然倾向于重构过程.
对于这种情况, 我更提倡微重构的概念, 就是尽量缩小重构范围, 增加重构次数. 那种单次的超大规模的重构, 风险其实是很大的, 可能会导致以往的很多细节工作全部重做. 而多次小范围的重构, 则会将这种风险尽可能的缩小.
在重构过程中, 遵循两个原则:
1. 一定要明确原代码的意图, 很多看起来不可捉摸的代码, 可能会有一个意料不到的作用.
2. 每次微小的重构, 哪怕范围再小, 都要详细测试.
上述5个原则, 并不仅限于此, 在未来, 我应该会增加更多个人认为有作用的原则. 希望对你的项目开发工作有所提升.
文章知识点与官方知识档案匹配,可进一步学习相关知识Git技能树首页概览2960 人正在系统学习中 相关资源:1stopt数据拟合软件_曲线拟合软件-深度学习文档类资源-CSDN文库
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!