首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

烂代码长什么样?

  • 24-03-05 00:01
  • 4109
  • 7629
blog.csdn.net

640?wx_fmt=gif

640?wx_fmt=jpeg

作者 | 小妞为何不笑

责编 | 胡巍巍

最近看别人写的代码看得头疼,写这篇不仅是总结同时也告诫自己不要写出烂代码祸害别人。看不懂别人的代码是什么感觉?就好像走进一片森林里迷了路,这时候你是不是想把写代码的人抓过来骂一顿?下面就总结几条最让人受不了的。


640?wx_fmt=png

标志位以及全局变量太多


标志位看似用起来很方便,是为了表达一种状态,然而一旦起了就要去维护,什么时候清零?什么时候置 1?什么时候初始化?当所表达的这件事情不简单,比如跟另一件事情有牵扯,标志位就不好用了,会有很多地方需要把他清零或置 1,一旦有个地方忘了程序就会出错。标志位一两个还好,多了别人看得头昏,能避免就避免,实在避免不了怎么办?等一下再写,过一会就发现其实不用也可以。

640?wx_fmt=gif

全局变量(这里指的是 int 型或 char 型等基本类型的变量)跟标志位同理,太多只会引起头昏,用之前应该明确这个变量的作用范围,如果作用范围只是在一个函数里面,那么就没必要起在外面,直接在本函数起一个“static”类型的就可以了,也许有时候起的时候并没有发现这个变量可以在函数里写成 static,代码写完后多看看就发现了。同理作用在本文件的那就在本文件里定义成 static。

比单个文件中全局变量更可怕的是一个变量跨越几个文件使用,一不注意看花眼,心累不心累?如果一个变量确实会在几个模块里被读和写怎么办?可以在一个模块定义成 static,然后通过读和写的接口函数来实现读写就好了。

640?wx_fmt=jpeg

在笔者看来,全局变量这种东西能不用就不用,一般涉及相同业务的变量一起组成一个结构体在结构体里面定义,单独起一个全局的结构体就够了,而不是这里一个那里一个单独的变量散落在文件的各个地方。

比如当某件事情发生时 A 模块会去写某个变量,让 B 模块来读,此时定一个标志位以及变量,当 B 模块发现标志位置 1 了就去读变量,这种做法就不太好。AB 模块完全可以通过消息队列来通信,A 模块只需要把变量值通过发特定消息带给 B 模块就好了,这样就实现了 B 模块在事件发生时得到了这个变量。


640?wx_fmt=png

逻辑不够简单


逻辑复杂一方面可能是产品的功能本来就设计的复杂;一方面可能是写程序的时候思路不清晰,实现方法不够简洁,代码一团糟自己把自己作死的。如果这两方面都占了,那差不多到了要吐血的边缘了。

640?wx_fmt=jpeg

如果功能逻辑复杂该怎么办?代码该怎么写就应该好好规划,先想清楚别急着写。

拿我们的产品举个例子,智能家庭网关子设备绑定入网流程就比较复杂,首先手机 App 在局域网内搜索子设备,网关收到搜索消息,去开启 ZigBee 子设备入网流程,入网成功后子设备开始登陆到服务器流程,这个过程中手机持续发搜索消息,网关持续回复搜索消息告知子设备基本信息以及连网处于哪一阶段(比如与网关连接中、登陆服务器中)直到子设备登陆服务器成功,获得了登陆 ID 号,手机向服务器申请绑定该子设备,整个流程结束。

体现到代码上,整个过程中涉及到三个线程,局域网线程、广域网线程、ZigBee 线程。其中,ZigBee 线程需要同时与局域网、广域网线程通信,广域网线程可能需要与局域网线程通信,这关系简直太复杂了。你无法想象原来代码靠一堆的 flag 和变量就把这功能做完了,你需要捋好多遍才搞清楚,那些名字相似的变量们都是些什么作用。

具体怎么做暂且不谈,反正让我做是不会做成这样的,可以利用操作系统的消息队列、回调函数、信号量等等让线程间通信变得简单些,操作系统就是为了让我们更简洁地编码啊!


640?wx_fmt=png

函数设计不合理


  • 一个函数功能不单一

这是很容易会犯的错误,有时候某个函数被设计成完成一种功能,但随着产品功能迭代升级,发现程序执行到这有了另外一种情况这个函数处理不了了,于是不得不在原来函数里面又补上一段。

这样就造成了这个函数有好几个功能:正常情况时就是原来功能,新的情况时,又是另外一种功能。从函数名看是只有前面这种功能,里面却藏着另一种功能,反正看着有些不爽,如果有时间来改一下,也许可以设计成两个函数,正常情况执行函数 A,新的情况执行函数 B。

  • 功能切分不合理

到底什么功能可以包装成一个函数?会被反复用到的功能,或实现起来代码比较多,放在程序里太长,细节又可以屏蔽的功能。不要几句代码就能实现的功能还要写一个函数,也不要很多不相干的东西全凑在一个函数里,函数又臭又长让人失去了耐心,然后又在某个旮旯里藏着关键性逻辑。 

  • 嵌套调用太多层

假如 A 函数调用 B 函数,B 函数里面又调用 C 函数,C 函数里面…….晕不晕?


640?wx_fmt=png

可读性差


  • 魔鬼数字

比如数组的第 5 个元素减 7,为什么是 5?为什么是 7?让人摸不着头脑,可以把 5 和 7 定义成宏,从宏的名字体现出其意义;

  • 没有注释

这不用多说了吧,关键函数、关键逻辑都应该加上适当注释让后来者好维护;

  • 命名风格不统一

无论是变量、函数还是文件名,都应该能望名知义并保持一样的规则,比如一个模块提供给其他模块的接口函数命名都保持”模块名 _ 功能”这样子,忽然来了个不按这种规则命名的函数,那就比较影响阅读,处女座会受不了的;另外英文的简写尽量用常见的(比如 count 一般缩写成 cnt),而不是冷门的让别人看不懂。

如果你觉得本篇不错,请帮忙转起来吧!

作者简介:绿罗裙,智能家居嵌入式软件工程师,一个程序媛妈妈。

640?wx_fmt=png

640?wx_fmt=jpeg

640?wx_fmt=gif

推荐阅读:

  • 一个程序员父亲的呼吁:不要教你的孩子从小学编程!

  • 我清华毕业,在龙泉寺写代码

  • Python 爬取爱奇艺腾讯视频 250,000 条数据分析为什么李诞不值得了?

  • 用 Python 分析了 1982 场英雄联盟数据,开局前预测游戏对局胜负!

  • Python | 7招教你识别一个网站是否是Django后台

  • 妈耶,摆脱机器音,二次宅的歌姬女友彻底活了

  • 比特币圈子段子多,苦中作乐就能过寒冬?

 
 

print_r('点个赞吧');
var_dump('点个赞吧');
NSLog(@"点个赞吧!");
System.out.println("点个赞吧!");
console.log("点个赞吧!");
print("点个赞吧!");
printf("点个赞吧!\n");
cout << "点个赞吧!" << endl;
Console.WriteLine("点个赞吧!");
fmt.Println("点个赞吧!");
Response.Write("点个赞吧");
alert(’点个赞吧’)
echo(’点个赞吧’)

640?wx_fmt=gif

点击“阅读原文”,打开 APP 阅读更顺畅 。 640?wx_fmt=png

程序人生
微信公众号
笑谈开发轶事,品味程序人生。
注:本文转载自blog.csdn.net的CSDN 程序人生的文章"https://blog.csdn.net/csdnsevenn/article/details/85086188"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top