当前位置: 首页 > news >正文

郑州网站公司排名新建网站

郑州网站公司排名,新建网站,网站设计服务费一般多少钱,门户网站开发难点摘要#xff1a;Dyad作者、资深C工程师Shawn McGrathz在空闲时翻看了Doom3的源代码#xff0c;发出了这样的惊叹#xff1a;“这是我见过的最整洁、最优美的代码#xff01;”“Doom 3的源代码让我对那些优秀的程序员刮目相看。”因此有了本文。 背景介绍#xff1a; Doom…摘要Dyad作者、资深C工程师Shawn McGrathz在空闲时翻看了Doom3的源代码发出了这样的惊叹“这是我见过的最整洁、最优美的代码”“Doom 3的源代码让我对那些优秀的程序员刮目相看。”因此有了本文。 背景介绍 Doom3是id Software于2004年开发的第一人称射击游戏目前以GPL v3协议开源。其采用游戏引擎的是id Tech 4由id Software创始人、首席程序员John Carmack领导开发。 再做个简单的对比作者刚刚完成的Dyad有193k行纯C代码Doom3是601k2004Quake3是229k1999Quake2是136k1997。 以下是CSDN译文做了部分删减 关于代码什么才能被称为“好看”——或者说“优美”在和几个程序员朋友讨论后我得出了结论 代码应该局部连贯而且功能单一一个函数解决一个问题。而且应该很清晰。局部代码应该能够解释至少暗示整体的系统设计。代码应该“自文档”尽可能地避免注释。因为无论是在读还是写代码时注释都是一项冗余工作。如果你需要添加注释才能帮别人理解那么那段代码可能需要重写。 这里是idTech4引擎的编码标准绝对值得一读。 统一的语法与词法分析 我在Doom源代码中所见最聪明之处在于其词法分析器和解释器。所有的资源文件都是语法统一的ASCII文件脚本、动画文件、配置文件等等所有东西都遵循相同的规则。因此一大块代码就可以阅读并处理所有的文件。这个解析器非常健壮支持一个C的主要子集。通过一个统一的词法分析、解释器引擎所有组件都不必担心序列化数据的问题因为已经准备好了相应的代码这保证其它地方的代码更加整洁。 参数严格和const化 Doom的代码非常严格尽管在我看来const方面还不够严格。可能很多程序员都没注意到const的多种种作用。我的看法是“任何东西只要可以都应该设定为const”我希望C中所有的变量都默认是const。Doom参数几乎完全遵守“no in-out”规则这意味着所有函数都参数都不能既是输入参数也是输出参数。这样在当你向函数传入参数时更容易理解他身上发生了什么。比如 从这几个const中我就看出来 这个函数不会修改作为参数传入的idPlane。我无需坚持idPlane是否被修改就可以安全地使用它。函数中的epsilon也不会被修改。front, back, frontOnPlaneEdges and backOnPlaceEdges是输出变量是值的写入目标。参数列表后面的const是我最赞赏的地方。它表明idSurface::Split()不会去修改surface。这是我最喜欢的C独有功能因为我可以这样使用 void f(const idSurface s) { s.Split(....); }  如果Split没有被定义为 Split(...) const这段代码将无法编译。无论被谁所调用f()都不会去修改外表即使f()将surface传递给另一个函数或者调用一些Surface::method()。const能够透露出很多关于函数甚至整个系统设计的信息仅仅通过阅读这里的函数声明我就明白了surface可以被plane动态地split()。这个函数不会修改surface而是返回新的surface、front、back数据可选地返回frontOnPlaneEdges和backOnPlaneEdges。 const规则以及无input/output参数对我来说也许是最重要的原则也是区分好的代码跟优美代码的关键它能简化整个系统的理解、编辑和重构。 最少注释原则 这是一个“格式问题”但Doom基本不会过度注释这很漂亮我经常会看到这样的代码 这太让人恼火了我通过名字就可以知道它的作用如果这个函数名不能体现出其功能毫无疑问应该重新命名如果名字描述得过多那么去简化它。除非实在不能通过重构、重命名内描述它唯一的功能那么注释才是合理的。我本以为程序员在学校已经学会注释的重要性但实际上没有。注释很有必要但它经常没必要。Doom在这方面做得非常合格以idSurface::Split()为例我们看看它是如何注释的 // splits the surface into a front and back surface, the surface itself stays unchanged // frontOnPlaneEdges and backOnPlaneEdges optionally store the indexes to the edges that lay on the split plane // returns a SIDE_?  第一行有点多余从函数定义中我们已经能明白所有的信息了但第二、第三行很有价值虽然我们已经可以推断出第二行的属性但注释消除了歧义。 Doom的代码加上合理的注释阅读非常方便。也许很多人把它归为格式问题但我认为格式也有正确与否。如果有人修改了函数并且删除了最后的const这样surface可以直接被函数修改于是注释与代码不再同步这样注释反过来会导致误解导致代码更加难以阅读。 纵向空间 Doom从不浪费纵向空间。我们以t_stencilShadow::R_ChopWinding()为例 整个算法只占了我1/4个屏幕剩下的3/4可以用来观看其周围的相关代码块。实际上我经常看到这样的代码 这可以归为格式问题我有10年编程经历都是像后者那样大概在6年前才强行转换为紧凑风格的。 两者的代码行数比是1118同样的代码后者行数几乎是前者的两倍所以可能导致看不到后面的代码块就像这样 如果没有前面的for循环仅仅上面这段代码毫无意义如果id没有纵向紧凑的风格代码可能更难阅读、更难写、更难维护、也就远离了优美代码的定义。 另外一个我认同的格式是id永远尽可能地使用{}没有括号会很糟糕比如我看过这段代码 这非常丑陋甚至比把{}放在同一行还要糟糕我在id的代码中从未发现省略{}的情况。省略{}会导致while代码块解析的时间大幅增加而且编辑起来也非常痛苦如果我希望往else if(c d)分支中再插入一个if分支怎么办 最少模板 id“犯了不少C的禁忌”他们重写了所有需要的STD函数。我个人对STD爱恨交织。在Dyad我调试构建时常使用它来管理动态资源在发布时又会处理所有的资源避免使用任何STL函数以求尽快地加载。STL很不错因为它提供了快速的通用数据结构它又很糟糕因为使用它经常导致代码丑陋不堪甚至容易出错。例如std::vectorT类如果我想迭代每一个元素 在C11中要简单些 但我个人并不喜欢自动化虽然它简化了代码编写却导致代码更难阅读最起码我现在是这么认为的。 STD有的函数、算法甚至非常荒谬比如要从std::vector中删除一个值 你必须每次都能拼写正确id除去了其中所以含糊不清的部分他们使用自己的通用容器、字符串类等等。他们编写的类比起STL要更加专一易于理解。id还尽可能地避免使用模板而且使用自己定制的内存分配器。STD代码里则充斥着无意义的垃圾模板而且不易于阅读。 C代码很难写好所以你需要不断地努力不相信的话可以去看看Microsoft和GCC的STD代码这是我见过的最难看的代码 id通过不滥用泛型就简单地解决了这个问题。他们编写了HashTableV和HashIndex类HashTable强制key类型是const char *而HashIndex是int-int对。这看起来像是很糟糕的C实例。他们“本应该”只有一个HashTable类然后为编写局部特殊化KeyType const char *然后专门 int, int。 当然id的做法完全正确也保证了代码的优美。 对比更鲜明的是Hash生成“C优秀实践”和id做法的比较 为特定类型专门化 这样你可以把ComputeHashForType当作HashComputer传给HashTable 这和我的做法很相近看起来很聪明但实际上很难看因为如果可选的模板参数很多怎么办 这种情况下函数定义要更糟 如果没有代码高亮我甚至不能区分出方法名 我也曾看到其它引擎试图通过卸载模板参数规范到无数的typedef这更糟糕也许这利于理解但却导致了本地代码和整个系统逻辑的断层所以缺乏美感。例如 以及 你这样使用两者 你会产生疑惑StringHashTable内存分配器——StringAllocator会涉及全局内存吗这里导致了混淆于是你又需要返回之前的代码检查循环…… Doom的做法和常规C逻辑完全相反它尽可能地避免泛型除非有特别的意义。Doom的HashTable需要生成hash值时怎么办它只需要调用idStr::GetHash()。 C语言的余韵 虽然我不清楚id团队其他人的出身如何但John Carmack基本上可以说是开发C应用起家的id在Quake III之前开发游戏用的都是C语言。我见过很多没有C开发功底的C程序员编写代码都有非常重的C特色上面过度使用模板的情况只是其中一例其它还有 过度使用set/get方法使用字符串流过度使用操作符重载 id在以上方面都做得非常完美。 通常很多人会这样创建一个类 这样不仅浪费行数还需要花费更多的时间编来写和阅读代码。相比之下 如果你经常为var自增某个数字n呢 相比于 上面的例子明显容易阅读和编写。 id从不使用字符流字符流通常包含糟糕的操作符重载 例如 虽然它有很多好处但是很难看而且语法也让人讨厌。 id选择printf()来代替这样也易于阅读理解。我同意这样的决定。 另一方面Doom还尽量避免操作符重载。虽然操作符重载是非常优秀C特性但没有操作符重载也就没有歧义更便于编写和阅读。 横向空间 这是我从Doom的代码中最大的收获原来我是这样编写代码的 根据Doom3的编码标准始终使用相对于4个空格的tab水平对齐其中所有类的定义 他们很少在类的定义中嵌入内联函数我看到的唯一一次是代码和函数声明写在了同一行这种做法有点不符合规范。这种类定义的组织方式非常容易解析不过需要更多的时间来编写。 我讨厌多余的代码编写但这种情况下我只需要这次稍微多做一点工作其他程序员在之后接手时就可以省下很多功夫。相信这里的Doom3编程规范能够帮助你理解其代码之美。有网友称Google的C编程规范与其也有很多相似之处。 方法名 我认为Doom在方法名方面缺乏规范我个人会尽可能地以动词开头命名方法 比这样要好得多 以下是John Carmack本人的回复 从某些角度来看我认为Quake3的代码更加整洁算是我C语言代码的风格的一次进化而非C风格的第一次迭代。当然也可能因为总代码行数更少或者是因为我已经10年没看过它的代码引起的错觉。我认为“好的C”在可读性方面比“好的C语言”更好其它方面大体相同。 我开始掌握C是在Doom3开发的时候——在这之前我有丰富的C语言编程经验因为NeXT Objective-C编程的原因也有OOP面向对象编程背景因此在使用C的时候并没有对其使用和习惯进行适当针对性的研究。现在回想起来真希望提前看过Effective C这样的教程。团队里其他程序员虽然之前有C编程经验但基本上也是按照我选择和设置的风格在编程。 很多年来我一直怀疑模板一直在克制地使用它不过最终确定自己更喜欢强类型而非充满奇怪的代码的头文件。关于STL的争论在id内部一直没有停息显得很有生气。回想Doom3开始开发的时候使用STL基本上算不得好主意直到现在即使是在游戏中我们也仍然在争论这件事。 关于const我直到现在基本上还是一个nazi我会斥责任每一个不尽可能常量化变量和参数的程序员。 我现在的风格主要是在向函数式编程靠近这样可以舍去很多旧习逐渐远离一些OOP的方向。 关于C函数式编程John Carmack写过一篇《Functional Programming in C》值得一读《程序员》对这篇文章做过编译。 原文链接KOTAKU
http://www.pierceye.com/news/625026/

相关文章:

  • 强化 门户网站建设今天的新闻大事
  • 专业做刀具网站的公司单页面网站模板
  • 企业网站制作及cms技术wordpress站点 HTML
  • 网络宣传网站建设制作加盟网络推广方案怎么写
  • 花店网站建设毕设介绍wordpress批量导入txt
  • 上海市网站建设定制百度推广怎么优化关键词的质量
  • 建设工程质量检测公司网站html5 响应式音乐网站
  • 网站建设托管推广海报中文域名做的网站
  • 临沂专业网站建设公司哪家好网站建设的网页
  • 当牛做吗网站源代码分享百度云帝国怎么做网站
  • 简约网站欣赏做美食网站赚钱吗
  • 一叶子网站建设目标教育平台oss做视频网站
  • 购物网站开发流程图wordpress 批量注册
  • 如何做网站优化的内容google网站推广
  • 网站模版亮点北京电商网站开发费用
  • 南昌专业的企业网站建设公司wordpress源码在哪
  • 农家院做宣传应该在哪个网站营销代码查询
  • 大型企业网站设计案例晋江做网站的公司哪家好
  • 海外模板网站有哪些全国网页设计大赛
  • 网站设计常州注册公司没有地址怎么弄
  • 注销建设工程规划许可证在哪个网站wordpress+Apache升级
  • 视频网站如何做盗链青岛商城网站开发
  • 网站主色调googleapis wordpress
  • 作网站番禺区网络推广渠道
  • app开发网站排行app制作平台排行
  • 盐城网站建设找哪家好个人如何做短视频网站
  • 域名进行网站备案吗2023年重启核酸
  • 为什么几年前做的网站视频看不了wordpress图片标签
  • 做照片用的视频模板下载网站好网站源代码购买
  • 网站rss生成上海网页网络技术有限公司