{"id":167,"date":"2017-06-28T12:05:20","date_gmt":"2017-06-28T12:05:20","guid":{"rendered":"http:\/\/cppdepend.com\/wordpress\/?p=167"},"modified":"2018-02-02T18:28:33","modified_gmt":"2018-02-02T18:28:33","slug":"doom3-is-the-proof-that-keep-it-simple-works-2","status":"publish","type":"post","link":"https:\/\/cppdepend.com\/blog\/doom3-is-the-proof-that-keep-it-simple-works-2\/","title":{"rendered":"Doom3 is the proof that \u201ckeep it simple\u201d works."},"content":{"rendered":"<p>If you search on\u00a0the web for the best\u00a0C++ source code. The Doom3 source code is mentioned\u00a0many times, with testimonials \u00a0like this one.<\/p>\n<blockquote><p>I spent a bit of time going through the Doom3 source code. It\u2019s probably the cleanest and nicest looking code I\u2019ve ever seen.<\/p><\/blockquote>\n<p>Doom 3\u00a0is a\u00a0video game\u00a0developed by\u00a0<a title=\"Id Software\" href=\"http:\/\/en.wikipedia.org\/wiki\/Id_Software\">id Software<\/a>\u00a0and published by\u00a0<a title=\"Activision\" href=\"http:\/\/en.wikipedia.org\/wiki\/Activision\">Activision<\/a>.The game was a \u00a0commercial success for id Software; with more than 3.5 million copies of the game were sold.<!--more--><span id=\"more-1103\"><\/span><\/p>\n<p>On November 23, 2011 id Software maintained the tradition and it released the <a href=\"https:\/\/github.com\/dhewm\/dhewm3\">source code<\/a> of their previous engine. This source code was reviewed by many developers, here\u2019s as example the feedback from fabien (<a href=\"http:\/\/fabiensanglard.net\/doom3_bfg\/\">orginal source<\/a>):<\/p>\n<blockquote><p>Doom 3 BFG is written in C++, a language so vast that it can be used to generate great code but also abominations that will\u00a0make your eyes bleed. Fortunately id Software settled for a C++ subset close to \u201cC with Classes\u201d which flows down the brain with little resistance:<\/p>\n<ul>\n<li>No exceptions.<\/li>\n<li>No References (use pointers).<\/li>\n<li>Minimal usage of templates.<\/li>\n<li>Const everywhere.<\/li>\n<li>Classes.<\/li>\n<li>Polymorphism.<\/li>\n<li>Inheritance.<\/li>\n<\/ul>\n<\/blockquote>\n<p>Many C++ experts don\u2019t\u00a0recommend any more the \u201cC with classes\u201d approach. However, Doom3 was developed between 2000 and 2004, what could explain \u00a0the no use of modern C++ mechanisms.<\/p>\n<p>Let\u2019s go inside its source code using <a href=\"http:\/\/www.cppdepend.com\/\">CppDepend<\/a> and discover what makes it so special.<\/p>\n<p>Doom3 is modularized using few\u00a0projects, here\u2019s the list of its projects, and some statistics about their types:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom5.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1272\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom5.png\" alt=\"doom5\" width=\"517\" height=\"204\" \/><\/a><\/p>\n<p>And here\u2019s the dependency graph to show the relation between them:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1110\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom2.png\" alt=\"doom2\" width=\"780\" height=\"328\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Doom3 defines many global functions.\u00a0However, most of the treatments are implemented in classes.<\/p>\n<p>The data model is defined using structs. To have a concrete idea of using structs\u00a0in the source code, the metric view above shows them as blue rectangles.<\/p>\n<p>In the Metric View, the code base is represented through a Treemap. Treemapping is a method for displaying tree-structured data by using nested rectangles. The tree structure used \u00a0is the usual code hierarchy:<\/p>\n<ul>\n<li>Project contains namespaces.<\/li>\n<li>Namespace contains types.<\/li>\n<li>Type contains methods and fields.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1281\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom13.png\" alt=\"doom13\" width=\"770\" height=\"383\" \/><\/p>\n<p>As we can observe many structs are defined, for example \u00a0more than 40% of DoomDLL types are structs. They are systematically used to define the data model. This practice is adopted by many projects, \u00a0this approach has a big drawback in case of multithreaded applications. Indeed, structs with public fields are not immutable.<\/p>\n<p>There is one important argument in favor of using immutable objects: It dramatically simplifies concurrent programming. Think about it, why does writing proper multithreaded programming is a hard task? Because it is hard to synchronize threads access to resources (objects or others OS resources). Why it is hard to synchronize these accesses? Because it is hard to guarantee that there won\u2019t be race conditions between the multiple write accesses and read accesses done by multiple threads on multiple objects. What if there are no more write accesses? In other words, what if the state of the objects accessed by threads, doesn\u2019t change? There is no more need for synchronization!<\/p>\n<p>Let\u2019s search for classes having at least one base class:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom6.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1274\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom6.png\" alt=\"doom6\" width=\"425\" height=\"307\" \/><\/a><\/p>\n<p>Almost 40% of stucts and classes have a base class. And generally in OOP one of the benefits of inheritance is the polymorphism, here are in blue the virtual methods defined\u00a0in the source code:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom7.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1275\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom7.png\" alt=\"doom7\" width=\"828\" height=\"386\" \/><\/a><\/p>\n<p>More than 30% of methods are virtual. Few of them are virtual pure and here\u2019s the list of all abstract classes defined:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom9.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1278\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom9.png\" alt=\"doom9\" width=\"391\" height=\"495\" \/><\/a><\/p>\n<p>Only 52 are defined abstract classes, 35 of them are defined as pure interfaces,i.e. all their virtual methods are pure.<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom8.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1277\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom8.png\" alt=\"doom8\" width=\"392\" height=\"493\" \/><\/a><\/p>\n<p>Let\u2019s search for methods using RTTI<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom17.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1290\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom17.png\" alt=\"doom17\" width=\"434\" height=\"496\" \/><\/a><\/p>\n<p>Only very few methods use RTTI.<\/p>\n<p>To resume \u00a0only basic concepts of OOP are used, no advanced design patterns used, no overuse of interfaces and abstract classes, limited use of RTTI and data are defined as structs.<\/p>\n<p>Until now nothing special differentiate this code from\u00a0many others using \u201cC with Classes\u201d and criticized by many C++ developers.<\/p>\n<p>Here are some interesting choices of their developers to help us understand its secret:<\/p>\n<p><strong>1 \u2013 Provides a common base class with useful services.<\/strong><\/p>\n<p>Many classes inherits from the idClass:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom10.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1279\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom10.png\" alt=\"doom10\" width=\"393\" height=\"496\" \/><\/a><\/p>\n<p>The idClass\u00a0\u00a0provides the following services:<\/p>\n<ol>\n<li>Instance creation.<\/li>\n<li>Type info management.<\/li>\n<li>Event management.<\/li>\n<\/ol>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom11.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1280\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom11.png\" alt=\"doom11\" width=\"392\" height=\"448\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><strong>2- Make easy the string manipulation<\/strong><\/p>\n<p>Generally the string is the most used type in a project, many treatments are done using them, and we need functions to manipulate them.<\/p>\n<p>Doom3 defines the idstr class which contains almost all useful methods to manipulate strings, no need to define your own method as the case of many string classes provided by other frameworks.<\/p>\n<p><strong>3- The source code is highly decoupled with the GUI framework (MFC)<\/strong><\/p>\n<p>In many projects using MFC, the code is highly coupled with their types, and you can find types\u00a0from MFC everywhere in the code.<\/p>\n<p>In Doom3, The code\u00a0is highly decoupled with MFC, only GUI classes has direct dependency with it. As shown by this following CQLinq query:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1117\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom3.png\" alt=\"doom3\" width=\"416\" height=\"496\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>This choice has a big impact on the productivity. Indeed, only the Gui developers must care about\u00a0the MFC framework, and for the other developers it\u2019s not mandatory to waste time with MFC.<\/p>\n<p><strong>4- It provides a very good utility library (idlib)<\/strong><\/p>\n<p>In almost all projects the most used types are utility classes, as shown by the result of this following query:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1119\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom4.png\" alt=\"doom4\" width=\"414\" height=\"496\" \/><\/a><\/p>\n<p>As we can observe the most used are utilities ones. If \u00a0C++ developers don\u2019t\u00a0use a good framework for utilities, they spend most of their developement time to fight with the technical layer.<\/p>\n<p>idlib provides useful classes with all needed methods to treat string, containers, and memory. Which facilitate the work of developers and let them focus more on the game\u00a0logic.<\/p>\n<p><strong>5- The implementation is very easy to understand<\/strong><\/p>\n<p>Doom3 implements a hard coded compiler, and as known by C++ developers, it\u2019s not an easy task to develop parsers and compilers. However, the implementation of the Doom3 is very easy to understand\u00a0and its\u00a0code is very clean.<\/p>\n<p>Here\u2019s the dependency graph of the classes used by the compiler:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom16.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1284\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom16.png\" alt=\"doom16\" width=\"726\" height=\"354\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>And here\u2019s a code snippet from the compiler source code:<\/p>\n<p><a href=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom15.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1283\" src=\"http:\/\/www.codergears.com\/Blog\/wp-content\/uploads\/doom15.png\" alt=\"doom15\" width=\"676\" height=\"513\" \/><\/a><\/p>\n<p>We already study the code source of many parsers and compiler. But it\u2019s the first time we discover a compiler with a source\u00a0code\u00a0very easy to be understood, it\u2019s the same for the whole Doom3 source code. It\u2019s magic. When we explore the Doom3 source code, we can\u2019t say: WOW it\u2019s beautiful!<\/p>\n<p><strong>Summary<\/strong><\/p>\n<p>Even if the Doom3 \u00a0design choices are very basic, but its designers make many decisions to let developers focus more on the game logic, and facilitate\u00a0all the technical layer stuff. Which\u00a0increase a lot the productivity.<\/p>\n<p>However when using \u201cC with Classes\u201d, you have\u00a0to know exactly what you are doing. You have to be expert like Doom3 developers. It\u2019s not recommended for a beginner to take risk and ignore the Modern C++ recommendations.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you search on\u00a0the web for the best\u00a0C++ source code. The Doom3 source code is mentioned\u00a0many times, with testimonials \u00a0like this one. I spent a bit of time going through the Doom3 source code. It\u2019s probably the cleanest and nicest looking code I\u2019ve ever seen. Doom 3\u00a0is a\u00a0video game\u00a0developed by\u00a0id Software\u00a0and published by\u00a0Activision.The game was &hellip; <a href=\"https:\/\/cppdepend.com\/blog\/doom3-is-the-proof-that-keep-it-simple-works-2\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Doom3 is the proof that \u201ckeep it simple\u201d works.&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[7,32,6],"class_list":["post-167","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-c","tag-code-quality","tag-doom"],"_links":{"self":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/167","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/comments?post=167"}],"version-history":[{"count":2,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/167\/revisions"}],"predecessor-version":[{"id":169,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/167\/revisions\/169"}],"wp:attachment":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/media?parent=167"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/categories?post=167"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/tags?post=167"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}