{"id":11,"date":"2016-07-14T22:31:14","date_gmt":"2016-07-14T22:31:14","guid":{"rendered":"http:\/\/cppdepend.com\/wordpress\/?p=11"},"modified":"2016-07-22T15:05:45","modified_gmt":"2016-07-22T15:05:45","slug":"doom3-is-the-proof-that-keep-it-simple-works","status":"publish","type":"post","link":"https:\/\/cppdepend.com\/blog\/doom3-is-the-proof-that-keep-it-simple-works\/","title":{"rendered":"Doom3 is the proof that &#8220;keep it simple&#8221; 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&#8217;s probably the cleanest and nicest looking code I&#8217;ve ever seen.<\/p><\/blockquote>\n<p>Doom 3<span style=\"color: #252525;\">\u00a0<\/span><span style=\"color: #252525;\">is a\u00a0<\/span>video game<span style=\"color: #252525;\">\u00a0developed by\u00a0<\/span><a style=\"color: #0b0080;\" title=\"Id Software\" href=\"http:\/\/en.wikipedia.org\/wiki\/Id_Software\">id Software<\/a><span style=\"color: #252525;\">\u00a0and published by\u00a0<\/span><a style=\"color: #0b0080;\" title=\"Activision\" href=\"http:\/\/en.wikipedia.org\/wiki\/Activision\">Activision<\/a><span style=\"color: #252525;\">.<\/span>The game was a \u00a0commercial success for id Software; with more than 3.5 million copies of the game were sold.<!--more--><\/p>\n<p><span style=\"color: #3b3b3b;\">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&#8217;s as example the feedback from fabien (<a href=\"http:\/\/fabiensanglard.net\/doom3_bfg\/\">orginal source<\/a>):<\/span><\/p>\n<blockquote>\n<p style=\"color: #3b3b3b;\">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 &#8220;C with Classes&#8221; which flows down the brain with little resistance:<\/p>\n<ul style=\"color: #3b3b3b;\">\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&#8217;t\u00a0recommend any more the &#8220;C with classes&#8221; approach. However, Doom3 was developed between 2000 and 2004, what could explain \u00a0the no use of modern C++ mechanisms.<\/p>\n<p>Let&#8217;s 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 <span style=\"color: #333333;\">is modularized using few\u00a0projects, here\u2019s the list of its projects, and some statistics about their types:<\/span><\/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><span style=\"color: #333333;\">And here&#8217;s the dependency graph to show the relation between them:<\/span><\/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>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 style=\"color: #555555;\">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 style=\"color: #333333;\">\n<li>Project contains namespaces.<\/li>\n<li>Namespace contains types.<\/li>\n<li>Type contains methods and fields.<\/li>\n<\/ul>\n<p style=\"color: #555555;\"><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 style=\"color: #555555;\">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&#8217;s 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&#8217;s 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&#8217;s 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 &#8220;C with Classes&#8221; 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 &#8211; 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><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><span style=\"color: #000000;\">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&#8217;s not mandatory to waste time with MFC.<\/span><\/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&#8217;t\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&#8217;s 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&#8217;s 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>And here&#8217;s 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&#8217;s the first time we discover a compiler with a source\u00a0code\u00a0very easy to be understood, it&#8217;s the same for the whole Doom3 source code. It&#8217;s magic. When we explore the Doom3 source code, we can&#8217;t say: WOW it&#8217;s 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 &#8220;C with Classes&#8221;, you have\u00a0to know exactly what you are doing. You have to be expert like Doom3 developers. It&#8217;s 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&#8217;s probably the cleanest and nicest looking code I&#8217;ve 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\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Doom3 is the proof that &#8220;keep it simple&#8221; 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,6,8],"class_list":["post-11","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-c","tag-doom","tag-keep-it-simple"],"_links":{"self":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/11","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=11"}],"version-history":[{"count":1,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/11\/revisions"}],"predecessor-version":[{"id":12,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/11\/revisions\/12"}],"wp:attachment":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/media?parent=11"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/categories?post=11"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/tags?post=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}