{"id":492,"date":"2019-08-27T05:52:55","date_gmt":"2019-08-27T05:52:55","guid":{"rendered":"http:\/\/cppdepend.com\/blog\/?p=492"},"modified":"2023-05-31T15:19:34","modified_gmt":"2023-05-31T15:19:34","slug":"grasp-principles-exploring-irrlicht-3d-engine","status":"publish","type":"post","link":"https:\/\/cppdepend.com\/blog\/grasp-principles-exploring-irrlicht-3d-engine\/","title":{"rendered":"GRASP Principles: Exploring Irrlicht 3D Engine"},"content":{"rendered":"<p>A design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. Patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.<\/p>\n<p>\u201cGang of Four\u201d patterns are maybe the most popular ones. However, there are some basic design principles not well-known by developers, it\u2019s the General Responsibility Assignment Software Principles, abbreviated GRASP.<!--more--><\/p>\n<p>Here&#8217;s its definition from Wikipedia:<\/p>\n<blockquote><p><span style=\"font-size: 15px;\"><b>General responsibility assignment software patterns<\/b>\u00a0(or\u00a0<b>principles<\/b>), abbreviated\u00a0<b>GRASP<\/b>, consist of guidelines for assigning responsibility to classes and objects in\u00a0object-oriented design.<\/span><\/p>\n<p>The different patterns and principles used in GRASP are: controller, creator, indirection, information expert, high\u00a0cohesion, low\u00a0coupling,\u00a0polymorphism, protected variations, and pure fabrication. All these patterns answer some\u00a0software\u00a0problem, and these problems are common to almost every\u00a0software development\u00a0project. These techniques have not been invented to create new ways of working, but to better document and standardize old, tried-and-tested\u00a0programming\u00a0principles in object-oriented design.<\/p><\/blockquote>\n<p><a href=\"http:\/\/irrlicht.sourceforge.net\/\">Irrlicht<\/a>\u00a0is a 3D engine library using many GRASP principles, let\u2019s discover the benefits of using this kind of patterns.<\/p>\n<h2>Creator<\/h2>\n<p>Creation of objects is one of the most common activities in an object-oriented system. Which class is responsible for creating objects is a fundamental property of the relationship between objects of particular classes.<br \/>\nLet&#8217;s take as example the Gui skin class and discover where in the Irrlicht library it&#8217;s created. For that we can execute this cqlinq query:<\/p>\n<p>SELECT METHODS WHERE\u00a0DepthOfCreateA \u201cirr.gui.CGUISkin\u201d == 1<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img1.png\" alt=\"\" \/><\/p>\n<p>The CGUIEnvironement is the only class that creates the CGUISkin instances, and almost all the GUIElement are created by CGUIEnvironement class except the\u00a0CGUIButton class.<\/p>\n<p>SELECT METHODS WHERE\u00a0DepthOfCreateA \u201cirr.gui.CGUIButton\u201d == 1<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img2.png\" alt=\"\" \/><\/p>\n<p>As we observe the CGUIButton is created in three different places, maybe it&#8217;s better to refactor the code and delegate the creation responsibility to the CGUIEnvironement class like all the other GUI classes.<\/p>\n<h2>Controler<\/h2>\n<p>The\u00a0<b>controller<\/b>\u00a0pattern assigns the responsibility of dealing with system events to a non-UI\u00a0class that represents the overall system or a\u00a0use case\u00a0scenario. A controller object is a non-user interface object responsible for receiving or handling a system event.<\/p>\n<p>A use case controller should be used to deal with\u00a0<i>all<\/i>\u00a0system events of a use case and may be used for more than one use case (for instance, for use cases\u00a0<i>Create User<\/i>\u00a0and\u00a0<i>Delete User<\/i>, one can have a single\u00a0<i>UserController<\/i>, instead of two separate use case controllers).<\/p>\n<p>Let&#8217;s discover the Controler for the GUIElements which must at least manage the event processing, this treatment is processed by CGuiEnvironement::OnEvent.<\/p>\n<p>Let\u2019s see which methods are used by OnEvent<\/p>\n<p>SELECT METHODS WHERE\u00a0IsUsedBy \u201cirr.gui.CGUIEnvironment.OnEvent(constSEvent&amp;)\u201d<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img4.png\" alt=\"\" \/><\/p>\n<p>The events fired are processed by a class that implements the IEventReceiver abstract class. Let&#8217;s explorer which classes implements it.<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img5.png\" alt=\"\" \/><\/p>\n<p>Each gui element treats the events related to it.<\/p>\n<p><strong>What are the other responsibilities of CGUIEnvironement?<\/strong><\/p>\n<p>As we have seen before this class create the concrete classes and also manage the event processing, and to discover if it does another responsibility we can search for methods used by this class:<\/p>\n<p>SELECT METHODS WHERE\u00a0IsDirectlyUsedBy \u201cirr.gui.CGUIEnvironment\u201d<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img6.png\" alt=\"\" \/><\/p>\n<p>This class use also some classes from irr::io namespace to persist and load into xml files ,\u00a0 maybe this class has many responsibilities and it can impact its cohesion, but it still tolerable because this class has all the data needed to persist data,\u00a0 this class follows the \u201cInformation Expert\u201d principle of GRASP.<\/p>\n<h2>Low Coupling<\/h2>\n<p>Low coupling is desirable because a change in one area of an application will require fewer changes throughout the entire application. In the long run, this could alleviate a lot of time, effort, and cost associated with modifying and adding new features to an application.<\/p>\n<p>Using abstract classes can improve the low coupling and we can evaluate the abstractness of a defined module by the following metric:<\/p>\n<pre>A = Na \/ Nc<\/pre>\n<p>Where:<br \/>\n* A = abstractness of a module Zero is a completely concrete module. One is a completely abstract module.<br \/>\n* Na = number of abstract classes in the module.<br \/>\n* Nc = number of concrete classes in the module.<\/p>\n<p>The abstractness of Irrlich is equal to 0.1245972, and it contains 125 abstract classes.<br \/>\nAnd for irr::gui namespaces there are 28 abstract classes, for each GUI element there\u2019s the equivalent interface.<\/p>\n<p>SELECT TYPES FROM NAMESPACES\u00a0\u201cirr.gui\u201d\u00a0WHERE\u00a0IsAbstract<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img7.png\" alt=\"\" \/><\/p>\n<p>CppDepend provides the\u00a0 DSM graph, and we can triangularize this matrix to focus on red borders highly dependent classes, and to detect modules.<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img8.png\" alt=\"\" \/><\/p>\n<p>As we can observe all the abstract classes are grouped, and\u00a0they can be isolated in another namespace or maybe in another project.<br \/>\nAnd to see the benefit of using an abstract class to improve the low coupling, let\u2019s search for classes that use the concrete class CGUISkin.<\/p>\n<p>SELECT METHODS WHERE\u00a0IsDirectlyUsing \u201cirr.gui.CGUISkin\u201d<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img9.png\" alt=\"\" \/><\/p>\n<p>Only one class know directly this class, it\u2019s his creator. And the other concrete classes are used through the abstract classes which is enforce the loose coupling.<\/p>\n<p>What about the coupling between namespaces:<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img11.png\" alt=\"\" \/><\/p>\n<p>A dependency cycle exists between some namespaces, having this dependency could be not problematic.However, avoiding it enforce the loose coupling.<\/p>\n<p>We can also discover how the namespaces interact with each other. For that let\u2019s see what the namespace &#8220;irr&#8221; use as classes and methods.<\/p>\n<p>SELECT METHODS WHERE\u00a0IsDirectlyUsedBy \u201cirr\u201d<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img12.png\" alt=\"\" \/><\/p>\n<p>As we can see almost all interaction with the other namespaces pass by the abstract classes, except for irr::video::CVideoModelList and irr::scene::CMeshBuffer.<\/p>\n<p>Let\u2019s discover the origin of the dependency with irr::video::CVideoModelList. For that we can execute the following CQLinq query:<\/p>\n<p>SELECT METHODS OUT OF TYPES\u00a0\u201cirr.video.CVideoModeList\u201d\u00a0WHERE\u00a0IsUsing \u201cirr.video.CVideoModeList\u201d<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img13.png\" alt=\"\" \/><\/p>\n<p>The class\u00a0\u00a0irr::CIrrDeviceWin32 use it because this class declares a field as video::CVideoModeList instead of video::IVideoModeList. Maybe a refactoring could be done to improve the interaction between the namespaces.<\/p>\n<h2>High Cohesion<\/h2>\n<p>The single responsibility principle states that a class should have more than one reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class. There are several LCOM metrics. The LCOM takes its values in the range [0-1]. The LCOMHS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. Note that the LCOMHS metric is often considered as more efficient to detect non-cohesive types.<br \/>\nLCOMHS value higher than 1 should be considered alarming.<\/p>\n<p>SELECT TYPES WHERE\u00a0LCOMHS &gt; 0.95\u00a0AND\u00a0NbFields &gt; 10\u00a0AND\u00a0NbMethods &gt;10\u00a0AND!IsGlobal\u00a0ORDER BY\u00a0LCOMHS DESC<\/p>\n<p><img decoding=\"async\" class=\"bordered\" src=\"http:\/\/www.cppdepend.com\/img\/irrlicht\/img14.png\" alt=\"\" \/><\/p>\n<p>Only a few classes are considered as no cohesive.<\/p>\n<h2>Conclusion<\/h2>\n<p>Irrlicht uses namespaces to modularize the code base and abstract classes to improve low coupling which makes it very easy to understand and maintain.<br \/>\nIt\u2019s a good example to follow if you want to improve your design quality.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. Patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system. \u201cGang of Four\u201d patterns are maybe the most popular ones. However, there are some basic &hellip; <a href=\"https:\/\/cppdepend.com\/blog\/grasp-principles-exploring-irrlicht-3d-engine\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;GRASP Principles: Exploring Irrlicht 3D Engine&#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":[],"class_list":["post-492","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/492","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=492"}],"version-history":[{"count":18,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/492\/revisions"}],"predecessor-version":[{"id":1463,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/492\/revisions\/1463"}],"wp:attachment":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/media?parent=492"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/categories?post=492"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/tags?post=492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}