如何创建高质量代码

前言

程序本身就是逻辑的表示,程序第一服务对象是人,第二服务对象是机器。对于软件而言,可用性重要,可读性可扩展性也是一样。为了后续接手的人可以更容易通过代码理解所要实现的目的,就需要在编码时候更有规划地编码。
高质量的设计包括如下特征:

  • 最小复杂度。做出简单且易于理解的设计。
  • 易于维护。设计出逻辑自洽的代码。
  • 富有层次,在任意层面观察系统,都可以理解这一层所要实现的功能。

本文章大部分内容参考自《代码大全》。

指针的使用

指针表示的是内存地址,而要解析这个地址所表示的内容,还需要指针的“基类型”,取决于指针的类型,可以是int的,也可以是char的,类型不同,解析出的数据也不同。

使用标记字段来检查内存改写。在一个结构体中,加入一个仅仅用于检测错误的字段。一旦这个字段与预期不相符,那么这个数据就被破坏了。对于网络的缓存buf,使用这个就很有效。多个应用会使用到缓存的buf,可能会发生异常改写。通过这个标记,即可发现数据被改写了,再在此刻回溯是哪个应用改写了内存。

简化复杂的指针。如果发现调用了复杂的只恨表达式,思考是否能够增加变量,让代码变得更容易理解。

难以理解的代码
for (rate_index =0; rate_index < num_rates; rate_index++) {
    new_rate[rate_index] = base_rate[rate_index] * rates->discounts->factors->net;
}
易于理解的代码
quantity_discount = rates->discounts->factors->net;
for (rate_index =0; rate_index < num_rates; rate_index++) {
    new_rate[rate_index] = base_rate[rate_index] * quantity_discount;
}

指针出错是很难调试,能难确定什么时候指针会变为非法的了。一种方式是在释放指针的时候给这个区域添加一些垃圾数据,即如果意外调用到的话可以看出问题。另外常用的就是free指针后设置为null。free后,还是有可能读取这个指针的数据,写入null会保证读取的时候能发现这个错误。

全局变量的使用

全局变量会使代码重用变得复杂。同时全局变量会使得代码管理变得复杂,在阅读模块代码的时候,需要考虑这个全局变量是否会在其他位置发生变化。因此在编码设计时候,首先将每个变量设置为局部的,只有万不得已的时候才设置为全局变量。

尽量使用子程序来访问全局数据,而不是直接访问。这会给代码带来更好的可读性,同时防止在代码编写过程修改到实现细节。

不合适的代码
node = node.next;
node = node.next;
node =node.next;
合适的代码
account = next_account(account);
employee = next_employee(employee);
rate_level = next_rate_level(rate_level);

判断语句的使用

对于顺序无关的代码,显式地表现出来。对于有依赖关系的数据,利用输入参数来显式依赖关系。

没有显示表示依赖关系
initialize_expense_data(expense_data);
computer_market_expense(expense_data);
computer_sales_expense(expense_data);
显式表示依赖关系
expense_data = initialize_expense_data(expense_data);
expense_data = computer_market_expense(expense_data);
expense_data = computer_sales_expense(expense_data);

对于判断语句,尽量将正常情况和出错情况隔离。先关注正常处理的流程,然后再根据每个正常流程的异常情况,理解异常逻辑的处理。

然而当出错情况过多的时候,会造成if嵌套过多,正常逻辑的判断位置和出错逻辑的判断间隔过远,对于代码理解也不是好事。可以选择先初始化判断完所有异常后,才进入正常逻辑。

case语句尽量把default当做检测错误的语句,而不是把default当成其他未考虑的情况。因为case语句在修订的时候,会引入一个新的情况,如果default确实是真正的默认情况,无需修订。如果是假的话,则需要将原来的default修改为普通的情况。

循环语句的使用

for循环是为了简单的用途,更复杂的循环最好用while去实现。for循环在初始化完数据后,不要在内部通过下标变更的方式让for循环终止。而且for循环需要关注下标,对于结束条件不那么清晰。

将循环看成是一个黑盒子,外围程序只关心输入参数、结束条件,不需要了解内部实现过程。为了这一目标,将初始化代码放在循环前面。让循环的入口、出口变得一目了然。

减少goto的使用,goto的使用会增加代码理解复杂度,且很容易出错,经常会出现,跳转到goto的语句前,有些逻辑没有考虑全

循环的退出要明显,让循环的终止条件看起来很明显,避免在for循环中出现依赖下标值的代码。同时小心有很多break散布的循环。

循环的编写应该是由内向外,从最小的、最简单的逻辑创建循环,再往外扩展。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 第一部分 打好基础 Laying the Foundation 第一章 欢迎进入软件构建的世界 Welcome t...
    白桦叶阅读 4,600评论 0 17
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,087评论 1 32
  • 个人学习批处理的初衷来源于实际工作;在某个迭代版本有个BS(安卓手游模拟器)大需求,从而在测试过程中就重复涉及到...
    Luckykailiu阅读 4,685评论 0 11
  • 注:这是第三遍读《C语言深度解剖》,想想好像自从大学开始就没读完过几本书,其中谭浩强的那本《C语言程序设计(第四版...
    HavenXie阅读 1,716评论 1 6
  • 1 字节码实现 javap命令生成的字节码中包含 ** monitorenter ** 和 ** monitore...
    JavaEdge阅读 373评论 0 0