17611538698
webmaster@21cto.com

代码高质量等级的阶梯

资讯 0 2551 2018-03-07 11:56:34
社区诸君也许都听说过,“要写高质量的代码”,那么到底什么是高质量的代码?
 

a1.jpg

 
 
我在专业环境下开发软件有着比较长的时间。我先后在微软,Google,Sumo Logic,以及现在的Leap.ai工作过。
 
我现在来总结一下代码质量的阶梯增长。可以把代码质量阶梯视作是一个简单的框架,用它来确定一段代码是不是高质量代码。
 
希望“代码质量阶梯”能够帮助刚刚工作的软件工程师尽快到达职业游戏的顶峰。
 

a2.png

 
代码质量等级I:正确性
 
编写正确的代码是软件工程师最基本的要求。 听起来很似乎挺浅白,但说时容易做起来难,在现实生活中很难达成。
 
我用一个我最喜欢的面试题作为例子:许多常用的电子表格产品的列是从A到Z,然后是AA,AB等。 编写一个函数将列名转换为相应的列号。 即,A变成1,B变成2,C变成3,等等。
 
几乎每位看到这个问题的人很快就会想到,这是一个26位的转换。接下来他们就开始编码。 但是,能够正确编码的人的比例却惊人地低。
 
我们来看下面用C ++语言编写的实现。
 

a3.jpg

 
 
你能找出这个代码中的任何错误吗? 如果不能,那就更加努力吧。 :)
 
这段代码存在以下几个问题:
 
·      const char*是一个C风格的字符串。 在C ++代码中使用C风格的字符串可能是危险的,因为C风格的字符串被假定为NULL终止,但C ++字符串不一定如此。 需要用std::string来代替。
 
·      指针/引用可能是NULL,并且当传入一个NULL指针时,这段代码将会崩溃。如果调试服务器崩溃在凌晨3点出现NULL指针,那么用户将无法访问你的网站。
 
你可能会说,“但我会验证输入,以确保我不用NULL指针调用它”。对不起,你不能在现实生活中。 一旦你的代码被写入,你将不知道是谁在调用它,在什么条件下调用。
 
·      如果输入是小写字符串,这个代码是否正常工作?
·      那么输入中包含非英文字符呢?
·      如果输入是一个Unicode字符串会发生什么?
·      如果输入字符串有七个As就会发生什么? 是的,整数溢出。我们的代码也需要处理...
 
说到代码,记住墨菲定律是很重要的:任何可能出错的东西都会出错 。 这意味着编写可以处理任何输入的代码是非常必要的,不管它是什么。 如果你能做到这一点,你将避免给你的代码的调用者任何意外的惊喜。
 
为了达到这种编码“正确性”的水平,你需要对代码可测试性有一个很好的理解。 还必须为您的代码做大量的单元测试。
 
代码质量等级II:效率
 
恭喜你,现在你已经完成了Level I,假设你的代码大部分是正确的。 顺便说一句,没有无错代码这样的东西,所以“大多数正确”已经是一个非常高的比率。
想象一下,你把你的代码投入到生产环境中。这个时候ta-da一声, 你的网站出现故障。我们在惊慌和冒汗的状态下,对大量服务器日志追踪。最终把问题缩小到一个被请求所淹没的函数调用,是它无法完成处理,导致了超时。
 
欢迎来到效率的土地!
 
你问什么是“效率”? “效率和Big-O符号一样吗?” 
答案是:效率和Big-O很接近,但不一样。

 
下面是一个例子来说明我在说什么:什么是最快的排序算法? 您可能会说快速排序是最快的排序算法,平均为O(n*log n) 。
 
在我们深入研究之前,让我们快速回顾一下。 “大O符号”描述了算法完成某个功能所需的最长时间。 所以如果一个算法是O(n*log n) ,就意味着对于某个常数k ,运行时间是<k*n*(log n) 。 当n足够大时,我们知道O(n*log n)比O(n^2)更有效率。
 
但实际上,算法速度有两个条件需要考虑:
·      大小n是重要的。 例如,如果我们排序一个6维数组, O(n^2)气泡排序可能比O(n*log n)快排序快得多。
·      常数k也非常重要。 在计算机科学课程中,我们总是忽略k在算法复杂性分析,但在现实生活中, k是超级关键。 k=1的O(n^2)解将比任何n<1000 k=1000的O(n)解更快。 换一种说法,内存中的冒泡排序可能比磁盘上的mergesort更快。
 
到目前为止,我们只涉及与时间有关的效率。 但是还有其他类型的效率需要考虑。 如空间效率,功效,算法收敛速度,用户交互效率等。 我不能在所有这些方面详细讨论,但代码效率是非常依赖于上下文的。 编写任何代码时的目标是在给定的约束条件下尽可能高效。
 
关于效率的最后一个注意事项:做得太过也不好。
 
这些被称为“不成熟的优化”,应该避免,而应只优化需要优化的东西。 如果不确定,请首先使用最简单的解决方案,然后进行性能测试,再确定是否需要进一步改进代码。
 
代码质量等级III:可读性
 
现在你知道如何编写既正确又高效的代码。 下一个挑战是要确保代码也要让其他人容易阅读和理解。
 
现代软件工程总是关于团队合作的。 你写的代码并不是你的,它属于你的团队(甚至其它团队) 。 让我们沉浸其中......那么,为了成功,让你的队友们也有兴趣来维护你的代码。 你不想在度假时打个电话,告诉你上网并修改代码。因为团队中没有其他人能够理解它,对吗? 这发生在很多工程师身上。 有一家公司曾经要求我帮忙,想了解一年前我写的一段代码 - 在我离开公司之后! 相信我,这绝不是一个好的体验。
 
用于将团队放在同一页面上的常见行业惯例称为编码风格指南。 在编码风格指南中,一组商定的编码风格由整个团队或组织共享。 我推荐Google代码风格指南 , Google代码风格指南 (整个Google公司是紧随其后的)。 现在也被许多组织公开接受。 它是彻底的,涵盖了许多常见的编码语言。
 
谷歌编码风格指南编写得很好,所以我不再重复这里的内容。 有一件事我想强调。 始终遵循你的团队现有的约定。 即使与其他普遍接受的惯例略有不同,也要这样做。 最重要的是你的团队的代码是一致的。
 
 
a4.jpg

 
坚持编码风格是一个好的开始,但是也需要其他实践来使代码可读。 例如,注释不应该简单地复制写入的代码。 他们应该解释代码背后的想法,并给出代码的上下文。 通过描述性的,具体的来使它们更有用 。
 
在这里,我选择了一个非常简单的例子来说明这个哲学。 比较以下两种备注方式:
int index= -1; // init to -1; useless comment 
与 
int index = -1;// init to invalid value; useful comment

 
(更新:这只是一个例子来说明备注,但不是一个写代码的最好例子。正如在一个响应中指出的,写这段代码的更好方法是int index = INVALID_VALUE; // no comment needed )
 
如果你还是觉得这个例子太微不足道了,想要一个更有趣的例子,请您看Google开源的LevelDB头文件。 这是一个很好的关于备注的例子,最初由Jeff Dean和Sanjay Ghemawat(Google的两位高级研究员)编写。
 
因此,关于可读性的关键是: 你的队友将是你的代码可读性的重要判断 。您的目标是让您的同事轻松理解您的代码。 在假期里你有其它更好的事情要做!
 
代码质量等级IV:可扩展性
 
如果您编写的代码是正确,高效和可读的,那么你就可以在任何组织的编程人员中排名前10%。 
 
下一个挑战 - 可扩展性,我来说说我们如何登顶。
 
问题改变与代码演变。 一个好的程序员可以预见将要发生的变化,并将其考虑在内,编写与未来兼容的代码—— 这是“可扩展性”的魔力。
 
我们以MapReduce为例。 MapReduce来自Google搜索小组,大量工程师正在通过类似的任务来分析数据。 Jeff Dean和Sanjay Ghemawat认为需要对框架进行标准化,以使工程师的生活更轻松。
 
说实话,标准化框架有很多种方法。 还有批评说Map and Reduce的概念并不新鲜。 然而,MapReduce的强大之处在于它将标准化到了正确的层面 ,使得使用它变得容易。 这意味着Google Search工程师可以使用它,也适用于Google搜索之外的其他用例。 众所周知,MapReduce在Google内外都得到了广泛的应用,其创造成为Web大数据时代的基石。
 
这是可扩展性的关键:知道什么级别是正确的级别。 回答这个问题奇怪的是比科学更多的艺术。 如果您的代码太具体,那么用例将会受到限制,每当需求发生变化时,代码都需要修改。 如果你的代码太泛化了,那么你的客户需要做很多工作来为你的特定需求构建代码,然后使用起来就太困难了。
 
掌握可扩展性需要大量的经验和智能。 对于大多数人来说,提高可扩展性的方法就是从我们的错误中学习 - 尝试,失败,冲洗和重复。 即使在Google,在MapReduce之上至少也有四五个框架构建,以使得MapReduce更容易。即使在Jeff和Sanjay身边,Google也不止一次尝试做到这一点。 :)
 
小结
 
代码的正确性,效率,可读性和可扩展性不是彼此独立的。 可读的代码更可能是正确的,但低效率的代码很难延伸。 对于每个软件工程师来说,最终的目标是在这些方面都要做好。 
 
但是在一些时候,大部分人都处于一般的水平。 我的建议是评估你自己的专业水平,比如考虑一下你花费大部分时间和精力在哪里,然后把注意力集中在那个领域,然后再进入下一个阶段。 
 
在你准备好之前,避免攻击一个非常难的关卡。 记住这一点,在你未能建立出色的技能,或者在基础薄弱的情况下,解决更具挑战性的问题将会出现停顿。
 
祝大家都能成功攀登代码质量高峰。
 
谢谢阅读。 如果你有任何想法,请留下你的宝贵评论 。
 


作者:Yuankai Zhou。Leap.ai Co-founder&CTO。原Google公司技术工程师。
编译:21CTO社区
原文:https://medium.freecodecamp.or ... 8e6e2


评论