需求着急上线,是写烂代码的理由吗?

2022 年 3 月 16 日 CSDN

【CSDN 编者按】软件开发大师Martin Fowler说过,“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”翻译过来就是:“任何傻瓜都能写计算机能理解的代码,优秀的程序员编写人类能够理解的代码。”

整理 | 于轩       
出品 | 程序人生 (ID:coder _life)

除了编程语言之争,代码质量好坏也是程序员们津津热议的话题之一。近日微博原创视频博主@蛋疼的axb发表了一个关于烂代码的话题,一时间引起了不少开发者的关注与讨论。

截图自蛋疼的axb微博

他在微博中写到,大多数人一提到代码质量就摆“需求着急上线”之类的理由。经过他多年的实践,想要写出高质量的代码,远比“明天晚上下班之前上线老板今天提的需求”难得的多。

令他不解的是,需求真的紧急时,程序员往往会通过加班来赶进度;而代码质量下降时,却鲜少有人做出努力。

在他看来,真正影响产出代码质量的,往往涉及两方面原因。一方面是需要在合格理论指导下的进行长期实践,另一方面则是要有足够的心理抗压能力。能写出高质量代码的人,日常只会比赶需求时更加忙碌。


烂代码是如何产生的?

程序员写出烂代码的原因有很多,最常见莫过于以下几种:1.为了按时完成紧急的项目;2.没意识到代码质量和最佳编码实践的重要性;3.粗心大意,想走捷径,不考虑未来的变化……

关于烂代码是如何产生的,网友说:

  • 刚毕业入行,苦于无人指点,不知道什么是高质量代码。

  • 不是因为时间赶,而是人太菜了,平时琢磨的少,经验少。

  • 思维的差距大,水平区分度也不同,不是所有人都能写出所谓的高质量代码。

  • 需求不确定的情况下,来回改动调整结构设计,代码就会越改越臃肿,最后变成烂代码。

  • 没有准备应对紧急情况的预案,实践经验不丰富才会导致为赶进度忽略代码质量。

  • 本质上是需求管理问题,缺乏专业能力的管理会盲目扩大需求范围,也就是力求「多快好省」的多和快,不管好和省了。


烂代码“长”什么样?

为了快速交差而产生的烂代码,不会过多考虑未来的变化,更别提代码的后期维护了。它们通常会具备以下这些问题:

  • 难以阅读和理解:烂代码最显著的特征就是没有人能够快速理解它。这意味着如果有开发者想更新这些代码,就必须要投入额外的时间先理解这些代码,然而理解烂代码后,他们就很难添加新代码了。这就导致很多新开发人员因为不理解旧代码而失业,老开发人员面对现有混乱和糟糕的烂代码选择离职。

示例:

system.whenTerminated.onComplete(result => session.close())implicit val materializer: Materializer = Materializer.matFromSystem(system) val dataPath = args(0)var batchSize = 512if (args.length > 1) {  batchSize = Integer.valueOf(args(1))}var skip = 0if (args.length > 2) {  skip = Integer.valueOf(args(2))} val lines = scala.io.Source.fromFile(dataPath)try {  import session.profile.api._  val parallels = Runtime.getRuntime.availableProcessors   val source = Source.fromIterator(() => lines.getLines())  val action = source    .map({ line: String =>      val number = counter.incrementAndGet()      (number, line)    })    .drop(skip)    .mapAsync(parallels)(tuple => Future(decode(tuple._1, tuple._2)))    .filter(_.isDefined).map(_.get)    .grouped(batchSize)    .mapAsync(1)({ articles =>      val max = articles.map(_.line).max      val min = articles.map(_.line).min      println(f"group of articles ${articles.size} [$min, $max]")      Future.sequence(articles.map(a => nonExists(db, a)))        .map(articles => articles.flatten)        .recover({          case err: Exception =>            println(f"unexpect error $err when check in [$min, $max]")


  • 包含许多级别的嵌套块,如if-else语句、循环:开发人员经常使用像if-else语句、循环这样的嵌套块来快速获得想要的结果。而当程序编译成功后,开发人员却忘了优化程序。

示例:

anchors foreach { anchor =>  if (anchor.hasAttr("href")) {    val href = anchor.attr("href")    val next = completeUrl(href)    println(next)    if (next.contains(domain) && !roadMap.contains(url) && !next.contains("/email-protection#")) {      roadMap.add(next)      if (process(next)) {        println(f"processed $next")        Thread.sleep(sleep)      } else {        println(f"skip $next")      }    }    else {      println(f"skip $next")    }  }}
  • 命名不当的方法和变量:为了节省时间,开发人员经常会使用变量/方法名,如X、Y、Z或ABC。这种做法很不好,因为开发者当下可能记得它们的作用,说不定过几天更新相同一段代码时就忘了。如果换做其他人,那就更不懂它们的含义了。

示例:

x = "abdon"y = 314z = 151r = f(x).f2(y).f3(z)


  • 不必要的代码注释:写注释是一个很好的习惯,但写的时候要分得清主次。如果添加太多,很容易会让读者跳过每一条注释,这就会造成重要注释被忽略的情况。

示例:

// 注释class Foo {  // yun xing cheng xu  public void run() {    // 调用 foo    foo(args);    // 调用    abc(args);    // 判断返回值    if(exists(efg(c))){       foo(x);    } else {      // 打折      dazhe(efg(d));    }  }}
以上示例代码由刘鑫提供

烂代码的危害

“代码写的太烂怎么办?”,“没关系,程序和人有一个能跑就行。”有人说,写代码是为了交差,在需求着急上线的时候,代码的质量就无法保证了。那事实真的是如此吗?答案肯定是:“No”

要知道,程序员写代码是为了解决问题,而不是单纯为了完成任务。低质量的代码就像是有问题的车,虽然还可以跑,但是需要不断维护,不然随时有可能无法启动。想必很多程序员面对自己的代码时都觉得,世界上最简洁易懂的,是自己刚写出来的代码;而世界上最烂的代码,则是自己一年前写出来的。

烂代码表面上看可以满足实际操作,但从长远的角度来看,它们很有可能成为一颗“定时炸弹”。因为烂代码一旦出现问题,面临的就是:

1.需要大量的时间和金钱来修改,成本会随着时间的推移而增加;

2.很难或无法增加新功能;

3.无法预测哪里以及何时会停止工作;

4.对开发人员的积极性有负面影响……

最坏的结果就是,烂代码可能导致项目报废。


专家分享解决之道

针对这个问题,微博认证为前微软Asp.Net最有价值专家、互联网科技博主的网友@宝玉xp,发布了一条长微博,分享了他在解决团队烂代码问题上的干货内容。

截图自@宝玉xp微博

他认为,当系统到处都是烂代码时,那就要思考更深层次的原因了。是不是需求太奇葩?进度太赶?没有设计?或者多个因素在一起?

关于这些问题,他和团队做了以下的努力:

  • 代码审查。所有更新的代码都先在分支开发,合并到主干前要代码审查。审查的部分工作要靠工具配合,运用自动化测试。

  • 写代码前要先做系统设计。磨刀不误砍柴工,写设计文档可以让开发人员在实现前就有清楚的思路,遵循最佳实践,把控代码质量。

  • 定期偿还技术债务。对于不值得维护的老项目,只打补丁,不增加新功能也不更新,只要能运行就行。对于需要长期维护、经常新增功能的老项目,就要通过重构来改进完善。需要注意的是,重构要先补自动化测试代码,逐个模块替代,不要一下子推翻重写然后迁移。

  • 开发模式分两步走。在两周的Sprint中,第一周只做产品的需求,开发完成后部署到测试环境测试;第二周修复各种新功能的Bug,同时做纯技术相关的任务,比如偿还技术债务、测试新的技术栈、开发公共组件。这种做法不仅能保证代码质量,还能保证持续有新的产品功能交付。

  • 新项目或已有项目要有最佳实践。在架构设计完成后,团队成员基于架构设计先实现一些基本的功能模块,把基本的场景都覆盖。在这些模块实现的时候,形成一个好的开发实践。实践时同时进行代码审查,每个人都可以提出意见反馈,根据反馈对最佳实践做出调整。有了最佳实践,其他人不仅可以照葫芦画瓢,写出质量不错的代码;对于不符合最佳实践的代码,在审查阶段也可以排除出来。

由此可见,烂代码可以轻易写出,想要写出高质量则需要程序员十分努力,保持思考、学习和批判的精神。对于烂代码,你是怎么看的?你有为提升代码质量做过什么努力吗?欢迎留言交流~

参考链接:

  • @蛋疼的axb微博:https://weibo.com/1809500942/LivUMjzNL

  • @宝玉xp微博:https://weibo.com/1727858283/LiykCzE5n

  • https://sunnysultan1640.medium.com/what-is-bad-code-how-to-write-clean-code-a9b7b539ad8 

END 

《新程序员001-004》全面上市,对话世界级大师,报道中国IT行业创新创造


  
  
    
— 推荐阅读 —
   
   
     
腾讯各事业群裁员比例没有网传30%那么高;郭明錤称苹果汽车团队已解散;Go 1.18 发布,正式支持泛型|极客头条
☞CTO 梁军离职,市值蒸发 59 亿,核心技术人才仅剩 3 人!寒武纪“动荡”的 6 周年
IntelliJ IDEA、Kotlin 背后公司 JetBrains 在俄罗斯停服
登录查看更多
0

相关内容

算法通关手册(LeetCode)
专知会员服务
157+阅读 · 2022年1月13日
专知会员服务
40+阅读 · 2021年9月6日
【经典书】数据科学艺术:数据工作者指南,162页pdf
专知会员服务
54+阅读 · 2021年3月9日
专知会员服务
91+阅读 · 2020年12月26日
《代码整洁之道》:5大基本要点
专知会员服务
49+阅读 · 2020年3月3日
程序员大部分时间都在“熟悉系统”
CSDN
0+阅读 · 2022年4月6日
复制粘贴代码,很可能会带来灾难性的后果
AI前线
0+阅读 · 2022年3月26日
当云原生遇上低代码,云端开发so easy!
SQL 被当成代码?谷歌的理由绝了!
CSDN
0+阅读 · 2022年2月23日
6000字,快速理解低代码
人人都是产品经理
2+阅读 · 2022年1月3日
国家自然科学基金
4+阅读 · 2014年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
3+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2009年12月31日
Arxiv
0+阅读 · 2022年4月18日
Arxiv
16+阅读 · 2021年7月18日
Arxiv
25+阅读 · 2018年1月24日
VIP会员
相关资讯
相关基金
国家自然科学基金
4+阅读 · 2014年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
3+阅读 · 2012年12月31日
国家自然科学基金
1+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2009年12月31日
Top
微信扫码咨询专知VIP会员