`
cats_tiger
  • 浏览: 277663 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

借花献佛——也写给我的团队(一)代码篇

阅读更多

看了neora的大作写给我的团队 ,颇受启发,在这里我借花献佛,也写一些短文给团队的新老成员做些总结。照搬的地方neora老大表骂我

 

各位尊敬的同事

你们好!我知道大家都很忙,忙的连写注释和文档的时间都没有,更不要说做总结了。所以我就写一些短文,帮助大家总结一下。正如大家所知道的,我们的团队每天所面对的问题有很多——需求、测试、编码、变更、架构 …… ,好吧,就让我们从编码开始吧。

为什么要编码?

软件就是把人们的需要转化为计算机可以执行的程序。

这一点毫无疑问,但是这就是我们编码的目的吗?我们都知道,计算机其实很笨,它只能认识 0 1 这两个数字,无论多么复杂的程序都是由这两个最简单的数字构成。这正如哥德巴赫猜想,作为最复杂的数学证明题,要求解决的却是最简单的 1+1 问题。也就是说,最直接的编程就是向计算机输入 0 或者 1 ,为什么我们不这样呢?

原因当然很简单,因为 0 1 组成的机器语言实在是太难以理解和记忆了。于是前辈们就发明了汇编语言,汇编语言用单词代替了机器语言,它能够让人们更加容易理解代码和程序。可是前辈们又发现汇编语言还是太晦涩难懂,几百行代码已经让人云山雾罩,遇到几万行的大型程序,那简直就是天书了。所以先行者们又发明了高级语言,高级语言用接近自然语言的方式来编写程序,就象自然语言一样,它(们)成为了程序员阐明观点交流思想的通用工具。

所以,我们编写代码的目的就是为了交流和沟通,而这,也正是计算机语言存在的意义。

考虑别人

既然编写代码的目的是为了沟通,那么作为一个程序员有什么理由去写那些只有自己才能够看懂的代码呢。如果吧这个作为一个问题问大家,恐怕没有一个人会这样回答:“编写只有自己能看懂的代码,让别人去猜吧!”。因为大家都希望合作,都愿意与其他人沟通,这不仅仅是工作的需要也是人类的基本需要之一。

可是,并不是每一个程序员都懂得沟通的艺术。几年前,我认识了一个很有天分的程序员,他的编程能力让人吃惊。但是,当他把一个命名为“ tj ”的函数交给我的时候,我只有无语了——“统计?”“添加?”,反复猜测不得要领之后,我只好让他重写这个函数。这样的例子还有很多,几乎每一个新手都出现过这样问题,即使他们对所使用的编程语言掌握的无比纯熟。

那么怎样才能编写一份能够阅读并易于理解的代码呢?下面我给出一些建议,其中的一些已经作为我们团队《编程规范》的一部分而被大家了解了,而另一些则不然。

     时刻考虑你所编写的每一行代码、代码中的每一个单词都会在将来某个时候被你的伙伴们阅读、测试和维护。这是一个原则,也是一个前提,是每一个程序员所必须具备的基本素质。在一个团队中,编写可以阅读和维护的代码是团队合作的前提条件。

●    必须认真的慎重的为你的变量、函数(方法)、类命名。要起一个科学合理的名字,因为名字是理解代码的重要依据。同时,一旦代码发布,其依赖者、继承者都要永远维持这种命名。想像一下,如果你和你的同事不得不使用类似“ tj ”这样的名字,而又不能改变现状(会影响其他使用者),那该是一件多么痛苦的事情。

为你的代码编写注释。注释是代码的重要组成部分,同时也是别人理解你代码的重要依据,无论任务多么繁重,时间多么紧张,都应该象对待代码一样对待你的注释。哦,还有,最重要的是维护你的代码的同时要维护注释,就像下面一条所说的:

●  请确保注释是有效的。无效的,甚至是错误的注释还不如不写注释,这是显而易见的。注释应该言简意赅,不要用注释重复你的代码,也不要用注释阐述代码中显而易见的逻辑。请原谅我的啰嗦——在维护代码的同时不要忘记维护注释。

  空行、空格也是代码。空行是一个逻辑段起止的标志,它和编程者的思路是一致的。另外,适当的使用空行和空格可以使你的代码更加清晰。

  不要耍小聪明。只要有可能,请尽量使用平实的思路来规划你的代码。我们都知道,阅读别人的代码往往比自己编写同样功能的代码要困难,因为阅读代码的过程就是读懂对方思想的过程。困难的原因之一是作者的水平比读者要高——这当然是读者所欢迎的;但是,也可能是因为作者使用了晦涩难懂的思路和技巧,这些技巧五花八门无法列举,下面是常见的几种情况:

1)        过度的使用了设计模式。
这是设计模式初学者经常犯的错误,设计模式是面向对象思想的精华,但是对于经验较少的程序员来说,设计模式是抽象的和复杂的,过多的使用设计模式,会使得代码结构复杂难以理解。

2)        拼凑结果。
例如,某个复杂的函数返回的值总是比预期结果少 1 ,有些程序员会采用 +1 的方式使结果正确。这类做法往往使得代码逻辑混乱莫名其妙,更为严重的是,类似的方法很冗余导致程序中隐藏着错误。

3)        过度封装。
经常遇到的一种情况就是对第三方类库的进一步封装,这必须在有经验的设计者的指导下进行,因为类似的需求往往出现在各种架构级别的模块中。对第三方类库的不合理封装会导致使用着对类库的使用产生异议,出现错误的用法等。

4)        拒绝使用成熟的第三方类库。
许多初级设计人员,往往喜欢自己编写框架级别的代码,例如,在 JavaEE 开发中自行设计 MVC 框架。这类做法在多数情况下都是错误的,因为成熟的产品比比皆是,这些产品都有广泛的用户群、详尽的文档、活跃的社区和大量的成熟案例。普通开发人员极少能够自行编写同样水准的代码,而且,即便写出来了谁又能够保证其他开发人员会使用并且喜欢使用呢。

5)        冒然采用新的技术。
程序员是思维活跃敢于尝试创新的人群,他们往往乐于使用新的技术和新的产品。但是,在使用这些产品之前请仔细考虑:“你了解它吗 ? ”。冒然在团队中应用新技术是一种非常不负责任的行为,学习曲线、隐藏 BUG 、适用范围等等会成为应用新技术的障碍,严重的情况下一个类似的决策会导致整个项目的失败。

 

消除重复

如果说软件目的就是将需求转换为程序,那么软件的本质就是复用。复用是一个非常宽泛概念,微软将 Windows 操作系统刻录成光盘出售,用户买到的都是同样的程序,这就是复用;我们使用 163 或者 google Email 服务,访问同样的 Web 网站,这,也是复用。一个程序、一个 URL 、一个架构、一个类、一个方法都可以成为复用的对象。这里,我们只讨论代码的复用。

仅在需要的时候使用接口。
接口为我们的应用提供很好的“可替换性”,简单的说,使用者仅依赖接口,而不必考虑接口是如何实现的,这样,一旦发生变化只需要重新实现接口,而依赖于接口的代码不必改动。显然,接口是非常强大的,它使得我们的代码具有扩展性,但是,是否所有的模块都需要这种扩展性呢?实践证明, 80% 左右的模块不需要替换实现类,这些模块即使发生了变化也往往是局部的,不会影响其他模块。而对它们的修改和维护的工作量要远远小于重新实现它们的接口。这类模块,是不需要接口的。那么什么时候使用接口呢,下面列出几种常见的情况:

1)  两个并行开发的模块(或类、子系统),互相存在依赖关系。
例如, A 模块依赖 B 模块的某些功能,因为是并行开发的,所以 B 模块可能还没有完成,这个时候,需要 B 模块提供接口以供 A 模块使用。 A 模块开发的时候,可以先使用一个 B 模块接口的“模拟实现”,等到 B 模块完成,再替换为真实的实现。

2)  对于结构复杂的或提供公共服务的模块。
有时候,需要提供一些公共的服务为整个系统使用。例如,在 Java 中直接使用 JDBC 操作数据库往往比较繁琐,这个使用需要提供一个通用的 JDBC 封装,将重复繁琐的 JDBC 操作提取到抽象类或者工具类中。但是, JDBC 操作中并非所有的代码都是重复的和可预见的,此时应该将这些非重复的和不可预见的代码抽象为接口,工具类依赖接口编程,工具类的使用者来根据自身情况实现这些接口。这其实是一个策略模式的应用,在实际开发中是很常见的。

3)  当模块的可变性是可以预见的时候。
如果开发人员预见到:“这个模块将来一定会发生某种变化”,那么此时可以使用接口。这种情况下,接口的粒度一定要细,仅仅包含变化的功能即可。例如,一组结构相同的数据,需要我们对其中一些特殊的数据进行处理,而原始数据中并没有提供某种规律来辨别哪些数据是特殊的,此时,我们只好通过硬编码( Hard Code )来处理这些特殊数据(例如,通过名称来判断)。这显然是代码中的坏味道,解决的办法就是提供一个用于判别特殊性的接口,然后用 Hard Code 的部分来实现接口,当客户方提供了数据的规律的时候,重新实现一个就可以了。

4)  在某些大型项目中,不同的模块可能需要不同的团队甚至不同公司进行开发。这个时候需要使用接口来规范双方之间的通信。

 

用抽象类实现公用的代码。
面向对象的原则告诉我们,聚合复用应该优先于继承复用。但是,当你确定某些类从本质上讲是同一个类别 的时候,就应该考虑将这些类的公共部分提取到抽象类中,以实现代码的复用。经过这种处理的子类比原来要精简很多,甚至比使用了聚合复用还要精简。

在复杂的模块中使用设计模式。

适量的使用条件分支判断。
大量的条件分支判断会导致代码冗长、结构松散、逻辑混乱,这类代码往往没有可阅读性和可维护性。但是,并非 if-else 就不能使用的了,只要遵循下面的原则, if-else 仍然可以使用:

1)      一组条件分支只判断一类条件。多种条件混合在一组分支中只能说明编程者的思维混乱。

2)      分支要尽可能少,不要超过 8 个。

3)      每个分支的代码在 3 行以内。

4)      每个分支都有注释。

5)      最后一个分支用于判断缺省情况。

6)      如果上述 5 条不能同时满足,请休息片刻,然后重构你的代码。

不要 Copy-Paste 你的代码。
当你 Copy-Paste 代码的时候,说明代码中存在重复,重复的代码往往导致代码难以维护和阅读。一旦那些保存在剪切板中的代码中存在错误,编写者甚至不知道到哪里修改这些错误。每当你 Copy-Paste 代码的时候,请停下来,考虑将这些代码提取为方法、类或者组件。

源代码就是文档

我们为什么写设计文档呢?设计文档可以说明你的代码,阐明设计思路,文档是我们沟通的重要工具,它可以使软件具有可持续发展性。这里我只想说说详细设计文档。 几年 前,我一直有一些疑问,什么是概要设计和详细设计?怎样才算“概要”?怎样才算“详细”?详细到什么程度才算合格?

现在我已经明白了,所谓概要设计就是架构设计,架构就是将一个软件中功能性的东西剔除之后剩下的部分。这一部分是软件的结构,它说明了软件中最为重要的特性和这些特性的实现方式。

那么详细设计呢?我曾经看到过的详细设计可以细致到伪代码,程序员可以不必动脑筋,直接将伪代码翻译为 Java 或者 C# 代码即可。我对这样的设计人员致以无比的敬意,因为他(们)不但可以为数量远超他们的程序员写代码,更为神奇的是,这些代码可以在没有调试过的情况下正常运行。但是,我想今生我都无法达到这个水平了。而且即使我达到了这个水平,我还要为这些设计文档的维护尤其是文档与代码之间的同步 付出无比艰辛的劳动,与其这样,我不如:

 

        简单设计。
Kent Beck
在《解析极限编程——拥抱变化》中为简单设计制定了 4 个评价标准,依次为(最重要的排在最前面):通过所有测试;体现所有意图;避免重复;类或者方法数量最少。这其中包含的核心意义就是不要为了考虑程序的可扩展性,把目前不需要的功能加入到软件中来。不要为了遵循某种规范而编写大量无用的甚至是起到反作用的文档,将精力转移到代码上来。依附在良好架构上的优质代码,比任何文档的作用都明显。

        单元测试的文档作用。
测试方面我将另行撰文阐述,这里所说的是单元测试的文档作用。任何一个学习计算机编程的人都知道, 10 行文字说明不如一行代码演示,这体现了“例子”的重要性。单元测试对于维护者而言就是“例子”,当维护者难以理解你的代码,当使用者不知如何使用你写的 API ,当你自己不知道修改代码会造成哪些影响的时候,单元测试可以为你说明一切。所以,请每一个程序员都要认真的编写测试代码,力求测试代码能够反映全部的意图,此时,单元测试就是文档!它不但能够说明代码的使用、功能,而且天然的与代码同步,更重要的是,它可以使你放心的维护你的代码。

        现代编程语言对于文档的支持。
Java C# Ruby 等新兴的编程语言中,可以将代码注释当作文档使用。例如 Java 为文档提供了很多支持——使用 HTML 标签、使用 @ 标记等,结合 Javadoc 命令就可以生成 HTML 格式的文档。相比传统的 Word 文档,注释作为文档的优势是显而易见的:

1)  天然的与代码同步,省去了很多同步的成本。

2)  连接特性使得文档更容易阅读。

3)  更加规范的文档格式。

        源码之前了无秘密。
当测试、注释、文档都失去作用的时候,不要忘记,我们还有逻辑,还有代码!代码之前了无秘密。优质的代码是说明应用程序的最根本的方式,是程序员沟通的通用语言。
所以,请认真的编写每一行代码!

 

 

分享到:
评论
6 楼 tobato 2008-11-03  
<div class='quote_title'>cats_tiger 写道</div>
<div class='quote_div'>
<p><span style=''>为什么要编码?</span> </p>
<p class='MsoNormal' style='text-indent: 21pt;'><span style=''>软件就是把人们的需要转化为计算机可以执行的程序。</span> </p>
<p class='MsoNormal' style='text-indent: 21pt;'><span style=''>这一点毫无疑问,但是这就是我们编码的目的吗?我们都知道,计算机其实很笨,它只能认识</span> <span lang='EN-US'>0</span> <span style=''>和</span> <span lang='EN-US'>1</span> <span style=''>这两个数字,无论多么复杂的程序都是由这两个最简单的数字构成。这正如哥德巴赫猜想,作为最复杂的数学证明题,要求解决的却是最简单的</span> <span lang='EN-US'>1+1</span> <span style=''>问题。也就是说,最直接的编程就是向计算机输入</span> <span lang='EN-US'>0</span> <span style=''>或者</span> <span lang='EN-US'>1</span> <span style=''>,为什么我们不这样呢?</span> </p>
<p class='MsoNormal' style='text-indent: 21pt;'><span style=''>原因当然很简单,因为</span> <span lang='EN-US'>0</span> <span style=''>和</span> <span lang='EN-US'>1</span> <span style=''>组成的机器语言实在是太难以理解和记忆了。于是前辈们就发明了汇编语言,汇编语言用单词代替了机器语言,它能够让人们更加容易理解代码和程序。可是前辈们又发现汇编语言还是太晦涩难懂,几百行代码已经让人云山雾罩,遇到几万行的大型程序,那简直就是天书了。所以先行者们又发明了高级语言,高级语言用接近自然语言的方式来编写程序,就象自然语言一样,它(们)成为了程序员阐明观点交流思想的通用工具。</span> </p>
<p class='MsoNormal' style='text-indent: 21pt;'><span style=''>所以,我们编写代码的目的就是为了交流和沟通,而这,也正是计算机语言存在的意义。</span> </p>
</div>
<p> </p>
<p>这一段口水话意义在哪里?</p>
5 楼 cats_tiger 2008-10-24  
hyhongyong 写道
LZ的意思是不是: 不要做编程牛仔,要做有职业素养的程序员?

也不是呀,编程牛仔也不错,我是说,编程牛仔+职业素养更好。
4 楼 dearwolf 2008-10-24  
唔,推荐一下KENT Beck的新书“Implementation Patterns”吧,中文名“实现模式”。

该书的影印版已经上市,在China-pub可以看到。

翻译版年底也会上市。
3 楼 hyhongyong 2008-10-24  
LZ的意思是不是: 不要做编程牛仔,要做有职业素养的程序员?
2 楼 hanshifei 2008-10-24  
受益匪浅,期待下篇。
1 楼 zhijie435 2008-10-24  
山哥的这些实践和经验绝对是多年丰富积累的成果,给我们提供了样板和模板,同时对我的项目组也具有极高的借鉴!
强烈建议推出其他篇章,我们翘首企盼,拭目以待。  

相关推荐

    2015高考语文满分作文36计之借花献佛:巧用诗词增文采素材

    在中国高考语文的写作评分标准中,一篇作文的文采斐然往往能够给阅卷老师留下深刻的印象,而其中,巧妙地将古典诗词融入作文之中,不仅能够增色不少,更是展现考生文化素养和语言驾驭能力的重要手段。在2015年的高考...

    Flex教程系列之(四) AS3语法——面对对象编程

    我只是借花献佛。 Flex教程系列之(一) AS3语法——编程基础 http://download.csdn.net/source/1161756 Flex教程系列之(二) AS3语法——流程控制语句 http://download.csdn.net/source/1161804 Flex教程系列之...

    Flex教程系列之(五) AS3语法——静态常量继承和接口

    我只是借花献佛。 Flex教程系列之(一) AS3语法——编程基础 http://download.csdn.net/source/1161756 Flex教程系列之(二) AS3语法——流程控制语句 http://download.csdn.net/source/1161804 Flex教程系列之...

    sqlPpt借花献佛之作

    在“sqlPpt借花献佛之作”这个主题中,我们可以期待一个详细讲解SQL的PowerPoint演示文稿,它可能是某位作者整理的关于SQL的学习资料,旨在帮助初学者或有一定基础的学习者深入理解和掌握SQL。 在PowerPoint演示...

    自治成功的stk500-借花献佛

    标题“自治成功的stk500-借花献佛”表明我们即将探讨的是关于STK500开发板在实现自我控制方面取得成功的一个项目或教程。STK500是Atmel公司推出的一种通用的AVR微控制器开发平台,常用于进行AVR系列芯片的编程、调试...

    1一厘米——学生学习课件

    - **家庭教育**:通过陶影对儿子的教育方式,传达了一个明确的信息——家长的行为对孩子有着深远的影响,应当以身作则,培养孩子的正直品格。 ### 二、作者简介与作品风格 - **毕淑敏**:中国著名作家,曾长期从事...

    借花献佛的成语接龙.doc

    借花献佛的成语接龙.doc

    C# 界面设计代码 资源 合辑

    因为最近做一个项目,在网上收集了一些有用的东西,自己的测试了,借花献佛。东西都是别人做的,我只是收集整理测试。 迅雷5界面代码 360安全卫士界面代码 非规则窗体界面代码 IrisSkin2&Skins 破解版DLL + 60个皮肤...

    react后台管理项目的效果展示

    react的一个后台管理系统代码,包括...注:我也是借花献佛,分享给大家。来源处没有讲明执行细节,对于react初学者来说,执行比较费劲。我这里做了一些详解。 参考来源:https://segmentfault.com/a/1190000009379222

    论文模版-借花献佛大规模

    ### 论文模版-借花献佛大规模 #### 关键知识点提炼: 1. **信息技术与网络技术的发展:** - 20世纪90年代以来,信息技术与网络技术的快速发展成为了全球关注的焦点。 - Internet技术的进步改变了资源获取、拥有...

    很不错的信息系统工程师考试资料 借花献佛

    很不错的信息系统工程师考试资料 借花献佛了

    VB 代码环境鼠标滚补丁

    VB为何在编辑代码时,怎么不... VB根本就不支持,除非你自己写个程序来检视滚轮,然后将滚动信息发送给代码窗口让他滚动。为此,就借花献佛给懒得动手的兄弟姐妹们做了个一键完成的小包裹. &lt;br&gt;希望各位喜欢!

    Spring3 MVC Hibernate-JPA Eclipse Demo

    链接上的那个示例代码写的很好,但是有一些bug,在我的demo中都已经修正。 2、平台环境:JAVA1.6以上、Apache Tomcat6.0以上、MS SQL2005(可以自己更换数据库,在persistence.xml更改参数就行,具体配置参考第一天...

    Spring3 MVC +HibernateJPA Eclipse Demo

    链接上的那个示例代码写的很好,但是有一些bug,在我的demo中都已经修正。 2、平台环境:JAVA1.6以上、Apache Tomcat6.0以上、MS SQL2005(可以自己更换数据库,在persistence.xml更改参数就行,具体配置参考第一天...

    codematic2.0

    这个工具似乎是由用户分享出来的,用“借花献佛”来表达分享的精神,暗示它可能是一个开源或者免费的资源。 在标签"codematic2.0"中,我们看到这个名称再次出现,这通常是用于分类或者搜索关键词,方便用户识别与这...

    反激式开关电源研发范例

    本篇将详细阐述反激式开关电源的研发过程,包括设计步骤和关键参数的计算。 首先,设计流程通常包含绘制电路图和PCB布局、变压器计算、零件选择以及设计验证等步骤。电路图是电源设计的基础,它描绘了电源内部的...

    跟我学习javascript的闭包

    也犯过几次因为不理解闭包导致的错误,一年多了资料也看了一些,但还是不是非常明白,最近偶然看了一下 jQuery基础教程 的附录,发现附录A对JavaScript的闭包的介绍简单易懂,于是借花献佛总结一下。 1、定义 闭包:...

    神经网络入门-神经网络入门.pdf

    感谢strongbox的辛勤劳动,连续发了6期神经网络入门,使我受益匪浅,同时我也产生一个想法,如果把这6期做成一个pdf文档,就可以方便更多的人。正好论坛里也有很多这样的呼声,所以本人借花献佛,用了一个小时(跟...

    九年级语文上册 6 一厘米同步练习 语文版(通用).doc

    这篇文档是针对九年级语文上册第六单元的同步练习,主要涵盖了语文基础知识、重要词语解释以及作家介绍。其中,文章《一厘米》是当代女作家毕淑敏的作品,她是一位具有丰富经历的一级作家,拥有医学背景。练习内容...

    VB_DTFT_2.rar_DTFT

    描述中的“借花献佛”意味着作者可能是基于已有的代码或资源进行了修改或改进,并分享给需要的人。这暗示了VB实现可能包含了对已有DTFT算法的优化或调整。 标签"dtft"再次确认了这个压缩包与离散时间傅里叶变换相关...

Global site tag (gtag.js) - Google Analytics