Doom3证明了“保持简单”有效。
如果您在网上搜索最佳的C ++源代码,则会多次提及Doom3源代码,并附带诸如此类的推荐。
我花了一些时间浏览Doom3源代码。 它可能是我见过的最干净,最漂亮的代码。
《毁灭战士3》是由id Software开发并由Activision发行的视频游戏。该游戏是id Software的商业成功; 售出了超过350万本游戏。
2011年11月23日,id Software保持了这一传统,并发布了其先前引擎的源代码 。 许多开发人员都审查了此源代码,以下是fabien( 原始源代码 )的反馈示例:
Doom 3 BFG用C ++编写,这种语言是如此广泛,以至于它可以用来生成出色的代码,但也可以使人流血。 幸运的是,id软件选择了一个接近“带有类的C”的C ++子集,该子集几乎没有阻力地流向大脑:
- 没有例外。
- 没有引用(使用指针)。
- 模板使用最少。
- 到处都是const。
- 类。
- 多态性。
- 遗产。
许多C ++专家不再建议使用“带有类的C”方法。 但是,Doom3是在2000年至2004年之间开发的,这可以解释为什么没有使用现代C ++机制。
让我们使用CppDepend深入其源代码,并发现它的特殊之处。
Doom3使用很少的项目进行了模块化,这是其项目列表以及有关其类型的一些统计信息:
这是依赖关系图,显示了它们之间的关系:
Doom3定义了许多全局功能。 但是,大多数处理都是在课堂上实施的。
数据模型是使用结构定义的。 为了在源代码中使用结构有一个具体的想法,上面的度量视图将它们显示为蓝色矩形。
在“度量标准视图”中,代码库通过树形图表示。 Treemapping是一种使用嵌套矩形显示树状结构数据的方法。 使用的树结构是通常的代码层次结构:
- 项目包含名称空间。
- 命名空间包含类型。
- 类型包含方法和字段。
正如我们所看到的,定义了许多结构,例如40%以上的DoomDLL类型是结构。 它们被系统地用来定义数据模型。 许多项目都采用了这种做法,在多线程应用程序的情况下,这种方法有很大的缺点。 实际上,具有公共领域的结构并不是一成不变的。
有一个重要的观点支持使用不可变对象:它极大地简化了并发编程。 考虑一下,为什么编写适当的多线程编程是一项艰巨的任务? 因为很难同步线程对资源(对象或其他OS资源)的访问。 为什么很难同步这些访问? 因为很难保证在多个对象上的多个线程进行的多个写入访问和读取访问之间不会存在竞争条件。 如果没有更多的写访问权限怎么办? 换句话说,如果线程访问的对象的状态不变,该怎么办? 不再需要同步!
让我们搜索至少具有一个基类的类:
几乎40%的结构和类都有基类。 通常,在OOP中继承的好处之一就是多态性,下面是在源代码中定义的虚拟方法:
超过30%的方法是虚拟的。 它们很少是虚拟的,这是定义的所有抽象类的列表:
仅定义了52个抽象类,其中35个定义为纯接口,即它们的所有虚拟方法都是纯的。
让我们使用RTTI搜索方法
只有极少数的方法使用RTTI。
为了仅恢复使用OOP的基本概念,不使用高级设计模式,不过度使用接口和抽象类,将RTTI和数据的有限使用定义为结构。
到目前为止,没有什么特别的方法将此代码与其他使用“带有类的C”的代码区分开,并遭到许多C ++开发人员的批评。
以下是开发人员的一些有趣选择,以帮助我们了解其秘密:
1 —为公共基类提供有用的服务。
许多类都从idClass继承:
idClass提供以下服务:
- 实例创建。
- 键入信息管理。
- 事件管理。
2-简化字符串操作
通常,字符串是项目中最常用的类型,使用它们进行了许多处理,我们需要函数来对其进行操作。
Doom3定义了idstr类,该类包含几乎所有用于处理字符串的有用方法,而无需像其他框架提供的许多字符串类那样定义自己的方法。
3-源代码与GUI框架(MFC)高度分离
在许多使用MFC的项目中,代码与类型紧密相关,您可以在代码中的任何位置从MFC中找到类型。
在Doom3中,代码与MFC高度分离,只有GUI类才具有直接依赖性。 如以下CQLinq查询所示:
这种选择对生产率有很大影响。 确实,只有Gui开发人员才必须关心MFC框架,对于其他开发人员来说,并不是必须浪费时间使用MFC。
4-它提供了一个非常好的实用程序库(idlib)
在几乎所有项目中,最常用的类型是实用程序类,如以下查询结果所示:
正如我们可以看到的,最常用的是实用程序。 如果C ++开发人员没有为实用程序使用良好的框架,则他们会花费大部分开发时间来与技术层抗衡。
idlib提供有用的类以及所有需要的方法来处理字符串,容器和内存。 这促进了开发人员的工作,并使他们更加专注于游戏逻辑。
5-实施非常容易理解
Doom3实现了一个硬编码的编译器,正如C ++开发人员所知道的那样,开发解析器和编译器并非易事。 但是,Doom3的实现非常容易理解,其代码也很干净。
这是编译器使用的类的依赖关系图:
这是编译器源代码的代码片段:
我们已经研究了许多解析器和编译器的代码源。 但是,这是我们第一次发现具有易于理解的源代码的编译器,对于整个Doom3源代码都是相同的。 这是魔法。 当我们探索Doom3源代码时,我们不能说:哇,真漂亮!
摘要
即使Doom3的设计选择是非常基本的,但其设计人员还是做出了许多决定,让开发人员将更多精力放在游戏逻辑上,并促进所有技术层的工作。 从而大大提高了生产率。
但是,在使用“带类的C”时,您必须确切地知道自己在做什么。 您必须像Doom3开发人员一样是专家。 不建议初学者冒险并忽略Modern C ++建议。
From: https://hackernoon.com/doom3-is-the-proof-that-keep-it-simple-works-3884d2484084