网站建设详方案,北京知名的品牌设计公司,wordpress 评论 设置,求西北地区网站建设专家 西安沉睡网络 官方网址?来源 | 码砖杂役责编 | Carol封图 | CSDN 付费下载自视觉中国我们经常谈论架构#xff0c;讨论设计#xff0c;却甚少关注实现和代码本身#xff0c;架构和设计固然重要#xff0c;但要说代码本身不重要#xff0c;我不同意#xff0c;Robert C.Martin大叔也不同意#… 来源 | 码砖杂役责编 | Carol封图 | CSDN 付费下载自视觉中国我们经常谈论架构讨论设计却甚少关注实现和代码本身架构和设计固然重要但要说代码本身不重要我不同意Robert C.Martin大叔也不同意Martin认为“源码即设计”。在讨论具体的实施细则之前我们不妨讨论一下什么是好代码Robert C.Martin认为衡量代码质量的唯一标准是WTF/min也就是review代码的时候每分钟说“握草”的次数。这个定义虽有辱斯文但粗野中不失奔放调皮中又蕴含哲理。好的代码如同文笔优美的散文行云流水赏心悦目阅读的时候如沐春风带给人愉悦与启迪。好的代码犹如构思精巧的小说它或许不够平铺直述却足够引人入胜读到最后你会豁然开朗原来是这样的啊那一刻你会觉得过程中的曲折和探索都是值得的。好的代码透过一个个函数你仿佛可以窥视到作者有趣的灵魂透过一行行代码你仿佛在与一个充满智慧的朋友聊天她总是条理清晰逻辑严谨有条不紊娓娓道来。而坏的代码犹如病毒它不仅瘫痪你的程序还有很强的传播效应等到它扩散开来神仙难治。坏的代码像一个泥团阅读的时候你仿佛被困于黑暗的迷宫又仿佛在跟一个絮絮叨叨的人交谈他的脑回路经常短路说话含混不清主次不分叨逼半天你依然get不到他的中心思想你常常感觉智商受到了莫大的侮辱你面露艰难神色心中万马奔腾。有很多区分好坏代码的规则我也看过一些对于文章中提到的一些标准做法就不重复嚼舌头根子了我想结合自己的工作经历谈一谈自己的切身体会。闲扯半日言归正传要编写弥漫好味道的代码要遵循哪些约束和指引呢一致性持之以恒的遵从一致性规则在代码风格上争论个三天三夜估计也定不出个好坏出来但好的风格一定是强一致性的这一点应该比较容易达成一致吧?风格的好坏其实更多受习惯的影响头发少一点的程序员应该都有自己风格变迁的经历多年前自己笃信不疑的Good Style或许正是当前深恶痛绝的Bad Style所以我主张在Style上搁置嘴炮一个项目应该有一个编码规则好的规则应该是以理服人的好的规则应该是拒绝任性夹带私货的规则定了之后就遵照执行吧可能某个风格跟你不相符但没关系你要知道这并不意味你在style之战败下阵来也并不表示它说服了你你遵守的是规则和纪律本身。我经历过一些c的项目函数命名有大驼峰有小驼峰有下划线连词还有驼峰加下划线有些是两个还有函数名下划线或者两个下划线开头总结一下它的规律就是没有规律非常随心所欲令我莫衷一是。变量包括文件、类/结构体、函数命名比如ohmygod你可能搞不清哪些字母是一伙的所以需要界定单词。驼峰通过单词首字母大写来界定单词另一个惯用做法是用下划线拼接单词。驼峰的弊端是丑下划线拼接的弊端是增加了标识符长度相比首字母大写好处是跟std c/c、linux kernel的做法一致喜欢kernel的码农容易找到如家般的归属感。c有namespace避免冲突c 经常用prefix防止命名污染全局空间但我认为命名简洁扼要很重要所以我支持简短的前缀而反对冗长的前缀。代码密度实现同样的功能你喜欢100行代码还是20行代码如果贵司不以代码行数考核绩效我建议你把代码写的精简而如果贵司以代码行数考核绩效我建议你离职开滴滴送外卖或者摆摊都行因为在这种公司耗费青春基本上也不会有什么发展前途。把简单的东西搞复杂化很容易你只需要找一个能力平庸的人就能实现化简为繁的愿望而化繁为简则堪称化腐朽为神奇。也许你要说我欠缺简化的能力这并不奇怪坦白讲这不是一件容易的事你做不到没关系但你拥有正确的理念更重要它将帮助你认清前进的方向而不是在错误的道路上越走越远。有些项目充斥各种无效代码其实你只需要稍加思考你就能识别出来。比如大块注释掉的代码像发臭的尸体一样遍布其中。比如大量功能重复的代码像垃圾一样堆砌在那里。比如本不需要返回值的函数执拗的固定返回true然后在调用的地方还要装模作样的check一下返回值如果返回false再记一条日志再assert一下再抛个异常这样显得很有职业操守美其名曰面向failed编程处理了各种异常情况。又或者函数一进来不管三七二十一对入参一顿无脑检查一顿操作猛如虎一看代码二百五宣称这是符合ISO XX标准的安全做法全然忘记你在编写的是一个私有实现函数你在调用它之前已经检查过一遍私有函数是一个受控的安全上下文这不仅不优雅而且不绿色低效耗电并且不安全在该崩的时候没崩把雷埋到了更隐蔽的地方话说你看标准库函数strcpy/strcatvector operator[]检查传参了吗提高代码密度或者说浓度有利于理清思路有利于突出重点有利于提高维护性而充斥各种无效语句的代码只会把关键语句淹没在汪洋大海使得review代码的人get不到重点看不清主次。像听一个絮絮叨叨的人做报告满篇废话像看一个剧情拖沓的连续剧昏昏欲睡像喝一瓶二锅头兑十斤白开水口能淡出个鸟来。重构是程序员的口头禅重构是在保持程序功能不变的情况下调整架构和实现我认为提高代码密度应作为重构的一项追求。linux kernel、lua、nginx、skynet 这些优秀的开源库代码浓度都很高建议读者朋友品尝一下。封装我们最常干的一件事就是把重复编写的代码封装到一个函数里去用多处调用替代重复编写这个很好理解但其实即使不被多处调用把相关的一段代码封装到一个实现函数也是有必要的因为把代码平铺开来把细节暴露出来容易掩盖重要的东西即框架和脉络会变得不够清晰。一个见名知义的函数调用比堆砌在那里的一段代码给我的感受好我如果关心它是怎么做的我可以跳转到定义看看实现。封装的一个核心原则是单一职责符合单一职责的函数更易于被复用。解耦构建松散耦合的系统一直是软件工程的一个目标模块化的一个方向便是解耦但我们口口声称心心念想的解耦在实施层面又有几分体现呢比如我们经常干的一件蠢事就是把类似配置文件或者宏定义的东西集中的一个头文件里去看起来很统一也很正规起码我之前也是这样认为的但忽然有一天发现自己这样做显得很不聪明的样子为什么呢因为你想把所有模块配置相关的东西都塞进配置公共文件真的合适吗是不是把公共接口抽离出来更好把配置相关的数据下沉到各模块更合适另外把宏都定义到一起这意味随便改点东西都会需要修改宏头文件而这个头文件就会成为程序世界的中心修改公共宏文件几乎会引起整个系统的所有源文件rebuild这简直就是AOE团灭啊。所以更好的方式是分而治之去集中式。我们知道c/c的编译单元是source file.c/.cpp编译的第一步是预处理所有include都会展开替换所以我们要避免引入任何不必要的头文件也应该把本编译单元用到的头文件都include进来这就是所谓的头文件自给自足。这点很重要但很多人会不以为然甚至有些人会搞一个allincluded.h把常用的一些头文件全部include进来然后自认为一劳永逸的完美的解决了问题包含不必要的头文件会增加编译时间会增加依赖我们不仅应该避免错误的包含还应该精心设计和划分文件使得每个文件的功能足够内聚单一。缩写慎用缩写相比缩写带来的含混不清我宁愿多敲几下键盘如果要缩写请符合惯例遵从常规比如AI比如App比如cfg但是你把threshold缩写成threshod把Item缩写成Iem我特木真的搞不懂你是拼错了还是缩错了遵从标准我遇到过一些项目每个模块单独定义自己的int32floatcharvoid比如定义MoKuaiA_int32MoKuaiB_int32MoKuaiC_CHAR不仅如此它还把inlinetruefalseVOIDconstcasestatic等一众关键字全部redefine了令人匪夷所思的是它竟然把标准C API全部重定义一遍令人发指的是它竟然不让你用语言的标准写法。我一直搞不懂为什么要这样做如果你只是需要解决不同体系结构下long等整型的长度差异我想偷偷告诉你c库头文件stdint.h已经从标准层面统一解决了这个问题里面int8_t/16_t/32_t/64_t还有uint8_t等等应有尽有。这样的做法是很不好的会让符合标准的写法寸草不生建议不要这么做。宏宏是c的一个有效武器在有些情况下确实行之有效我是宏的中间派我既反对禁用宏也反对滥用宏inline可以部分替代宏但不能完全替代宏。但我见过一些项目到处都是宏全大写至少1/3的代码都是各种花里胡哨的宏你review代码的时候不停的跳来跳去看了一眼哦就这样啊然后切回来频繁的上下文切换是低效的它打断了你的思路让你看代码有种撒尿撒到一半憋回去的感觉。其实很多时候完全没有必要不需要整这些虚头巴脑的。命名命名有一些指引比如类/结构体应该用名词函数应该用类似动词或者doSomething这样的动宾结构这些规矩都是耳熟能详的。我主张命名应该简明扼要不要罗里吧嗦要准确的表达出它要做的事情如果你碰到命名困难你可能需要考虑你的类定义或者接口划分是否合适。命名是接口的一部分很重要好的命名是自注释的。如果你没有思路那我建议你参考一下STD C/C API毕竟这些接口历经几十年没有大的变化算是经受住了历史的考验比如malloc/free/atoistl 容器的成员函数也有点意思size(), capacity()resize()reserve()push()pop()top()back()很干脆不废话我觉得很好。所以如果你编写的是某某管理器比如ItemManager我建议你直接取名add()remove()而不用AddItem()RemoveItem()因为你本身就是Item的Manager操作的必然是Item而且从参数上也能体现出来少即是多多不如少。扩展性开闭原则是应对扩展性的rule人无远虑必有近忧说的是我们不能局限于眼前但也请不要盲目迷信扩展性戏太多也是病。知乎有一篇神贴讲的是如何把helloworld搞成一个big project当你想给别人项目挑刺的时候你可以用扩展性说事但我建议你少说。避免特例linus大神分享过他心中的好代码说的是针对链表的操作他更喜欢统一性的处理方式而不是做特例化的处理我想这个例子很有代表性它其实代表一种理念那就是自始至终我们的头脑里必须优先考虑normal化的处理方式当然这其实是一个比较高层次的要求菜鸟互啄可以先跳过这一层要求。高效而鲁棒有很多避免运行低效的做法比如减少拷贝提高局部性buffer/cache空间时间置换内联分支预测判断前置计算延迟无锁技术。提高鲁棒性的关键是面向failed编程不信任/零信任设计假设依赖的上下文上下游都是不可靠的方法很多不一一列举了。最后喷了这么多也给大家一次喷作者的机会贴出来自己的代码https://github.com/ZhuanJia/mynet这是13年刚进福厂时候周末自己捣鼓的玩具它或许有这样那样的问题如果你觉得不错请给我点赞如果你觉得很水那我可以甩锅给时间毕竟7年前写的嘛。有句话说过如果你不觉得一年前的自己是傻逼那说明你这一年没什么进步何况7年前呢。推荐阅读
干货 | 大白话彻底搞懂 HBase RowKey 详细设计那天我去逛街发现连大编程语言都摆起地摊了……研发的未来在哪里Serverless 云开发来了Facebook 公司如何清除 960 万句“脏话”Linux 之父怒删工程师提交的补丁称“太蠢了”网友怼得好干货3 个重要因素带你看透 AI 技术架构方案的可行性热评 | 警惕新基建热潮中的区块链项目烂尾真香朕在看了