{"id":324,"date":"2018-02-17T22:05:37","date_gmt":"2018-02-17T22:05:37","guid":{"rendered":"http:\/\/cppdepend.com\/blog\/?p=324"},"modified":"2019-03-14T09:11:50","modified_gmt":"2019-03-14T09:11:50","slug":"some-c-good-practices-from-the-opencv-source-code","status":"publish","type":"post","link":"https:\/\/cppdepend.com\/blog\/some-c-good-practices-from-the-opencv-source-code\/","title":{"rendered":"Some C++ good practices from the OpenCV source code"},"content":{"rendered":"<p><a href=\"http:\/\/opencv.org\/\">OpenCV<\/a>\u00a0(Open Source Computer Vision) is a library of programming functions mainly aimed at real-time computer vision, developed by Intel Russia research center in Nizhny Novgorod. The library is cross-platform. It focuses mainly on real-time image processing.<\/p>\n<p>OpenCV is widely used,\u00a0Adopted all around the world, for end users, it\u2019s very mature and powerful, for developers it&#8217;s well implemented and designed. The OpenCV\u00a0developers used very basic principles which makes it very simple to understand and maintain.<\/p>\n<p>Let\u2019s discover some OpenCV design choices:<!--more--><span id=\"more-535\"><\/span><\/p>\n<p><strong>Modularity<\/strong><\/p>\n<p><em>1- Library based architecture<\/em><\/p>\n<p>A library-based architecture makes the reuse and integration of functionality provided more flexible\u00a0and easier to integrate into other projects.In addition, the library based architecture encourages clean APIs and separation.\u00a0Therefore making it easier for developers to understand, since they only have to understand small pieces of the big picture.<\/p>\n<p>OpenCV adopt this approach and defines many libraries, each one has a specific responsibility and all of them uses the opencv_core library.<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-559\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv1.png\" alt=\"opencv1\" width=\"834\" height=\"361\" \/><\/a><\/p>\n<p><em>2- Modularize by namespaces<\/em><\/p>\n<p>OpenCV uses widely namespaces to modularize its code base, here are for example the namespaces of the opencv_core project:<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-564\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv2.png\" alt=\"opencv2\" width=\"362\" height=\"400\" \/><\/a>OpenCV uses the \u201cNamespace-by-feature\u201d approach.\u00a0Namespace-by-feature uses namespaces\u00a0to reflect the feature set. It places all items related to a single feature (and only that feature) into a single namespace. This results in namespaces\u00a0with high cohesion and high modularity, and with minimal coupling between namespaces. Items that work closely together are placed next to each other.<\/p>\n<p>In case of OpenCV the namespaces are used for three\u00a0main reasons:<\/p>\n<ul>\n<li>Modularize the libraries.<\/li>\n<li>Hide details like for \u201ccv::detail\u201d namespace, this approach could be very interesting if we want to inform the library user that he doesn\u2019t need to use directly types inside this namespace and it\u2019s only for internal use. For C# the \u201cinternal\u201d keyword did the job, but in C++ there\u2019s no way to hide public types to the library user.<\/li>\n<li>Anonymous namespace: namespace with no name. It avoids making global static variable. The \u201canonymous\u201d namespace you have created will only be accessible within the file you created it in.<\/li>\n<\/ul>\n<p>[adrotate banner=&#8221;3&#8243;]<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Defines data model as POD types<\/strong><\/p>\n<p>Each project has its data model, it\u2019s recommended to defines\u00a0these data as\u00a0<a href=\"http:\/\/en.wikipedia.org\/wiki\/Plain_old_data_structure\">POD<\/a>\u00a0types.<\/p>\n<p>Let\u2019s search in the OpenCV code base for structs with no methods and having only fields. For that\u00a0<a href=\"http:\/\/www.cppdepend.com\/Doc_CQLinq_Features.aspx\">CQLinq<\/a>\u00a0will be used to query the code base.<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-565\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv3.png\" alt=\"opencv3\" width=\"362\" height=\"506\" \/><\/a><\/p>\n<p>The result of this query concern 25% of the number of types defined in OpenCV projects. OpenCV defines almost all its data model in structs with only fields.<\/p>\n<p><strong>Avoid multiple inheritance<\/strong><\/p>\n<p>Using multiple inheritance could complicate the design, debuggers can have a hard time with it, therefore it\u2019s not recommended by many C++ experts.<\/p>\n<p>Let\u2019s search which classes inherit from more than one concrete base class in the OpenCV code base.<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-566\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv4.png\" alt=\"opencv4\" width=\"386\" height=\"517\" \/><\/a><\/p>\n<p>Only a few classes from test projects use the multiple inheritance, this concept is avoided in the whole OpenCV code base.<\/p>\n<p><strong>Avoid defining complex functions<\/strong><\/p>\n<p>Many metrics exist to detect complex functions, NBLinesOfCode, Number of parameters and number of local variables are the basic ones.<\/p>\n<p>There are other interesting metrics to detect complex functions:<\/p>\n<ul>\n<li>Cyclomatic complexity is a popular procedural software metric equal to the number of decisions that can be taken in a procedure.<\/li>\n<li>Nesting Depth\u00a0is a metric defined on methods that is relative to the maximum depth\u00a0of the more nested scope in a method body.<\/li>\n<li>Max Nested loop equals the maximum level of loop nesting in a function.<\/li>\n<\/ul>\n<p>The max value tolerated for these metrics depends more on the team choices, there are no standard values.<\/p>\n<p>Let\u2019s search for methods that could be considered as complex in the OpenCV code base.<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv5.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-567\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv5.png\" alt=\"opencv5\" width=\"384\" height=\"511\" \/><\/a><\/p>\n<p>Only 1% is a candidate to be refactored to minimize their complexity.<\/p>\n<p><strong>Coupling<\/strong><\/p>\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>Low coupling could be achieved by using abstract classes.\u00a0Here are three key benefits derived from using them:<\/p>\n<ul>\n<li>An abstract class provides a way to define a contract that promotes reuse. If an object implements an abstract class\u00a0then that object is to conform to a standard. An object that uses another object is called a consumer. An abstract class\u00a0is a contract between an object and its consumer.<\/li>\n<li>An abstract class\u00a0also provides a level of abstraction that makes programs easier to understand. abstract class allows developers to start talking about the general way that code behaves without having to get into a lot of detailed specifics.<\/li>\n<li>An abstract class\u00a0enforces low coupling between components, what\u2019s make easy to protect the abstract class\u00a0consumer from any implementation changes in the classes implementing the abstract classes.<\/li>\n<\/ul>\n<p>Let\u2019s search for all abstract classes defined by OpenCV\u00a0:<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv6.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-568\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv6.png\" alt=\"opencv6\" width=\"387\" height=\"512\" \/><\/a><\/p>\n<p>If our primary goal is to enforce low coupling, there\u2019s a common mistake when using abstract classes,\u00a0that could kill the utility of using them. It\u2019s the using of the concrete classes instead of abstract ones, to explain better this problem let\u2019s take the following example:<\/p>\n<p>The class A implements the abstract class\u00a0IA which\u00a0contains the calculate() method, the consumer class C is implemented like this<\/p>\n<pre>public class C\r\n{\r\n   \u2026.\r\n   public:\r\n      void calculate()\r\n      {\r\n        \u2026..\r\n        m_a-&gt;calculate();\r\n        \u2026.\r\n       }\r\n       A* m_a;\r\n\u00a0};<\/pre>\n<p>The class\u00a0C instead of referencing the abstract class\u00a0IA, it references the class A, in this case, we lose the low coupling benefit, this implementation has two major drawbacks:<\/p>\n<ul>\n<li>If we decide to use another implementation of IA, we must change the code of C class.<\/li>\n<li>If some methods are added to A not existing in IA, and C use them, we also lose the contract benefit of using interfaces.<\/li>\n<\/ul>\n<p>C# introduced the\u00a0<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa288461(v=vs.71).aspx\">explicit interface implementation<\/a>\u00a0capability to the language to ensure that a method from the IA will be never called from a reference to concrete classes, but only from a reference to the interface. This technique is very useful to protect developers from losing the benefit of using interfaces.<\/p>\n<p><strong>Cohesion<\/strong><\/p>\n<p>The single responsibility principle states that a class should not 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 LCOM HS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. A LCOM HS value highest than 1 should be considered alarming. Here are \u00a0to compute LCOM metrics:<\/p>\n<blockquote><p>LCOM = 1 \u2013 (sum(MF)\/M*F)<br \/>\nLCOM HS = (M \u2013 sum(MF)\/F)(M-1)<\/p><\/blockquote>\n<p>Where:<\/p>\n<ul>\n<li>M is the number of methods in class (both static and instance methods are counted, it includes also constructors, properties getters\/setters, events add\/remove methods).<\/li>\n<li>F is the number of instance fields in the class.<\/li>\n<li>MF is the number of methods of the class accessing a particular instance field.<\/li>\n<li>Sum(MF) is the sum of MF overall instance fields of the class.<\/li>\n<\/ul>\n<p>The underlying idea behind these formulas can be stated as follow: a class is utterly cohesive if all its methods use all its\u00a0methods use all its instance fields, which means that sum(MF)=M*F and then LCOM = 0 and LCOMHS = 0.<\/p>\n<p>LCOMHS value higher than 1 should be considered alarming.<\/p>\n<p><a href=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv8.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-570\" src=\"http:\/\/www.javadepend.com\/Blog\/wp-content\/uploads\/opencv8.png\" alt=\"opencv8\" width=\"503\" height=\"508\" \/><\/a><\/p>\n<p>Only a few types are not cohesive.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>If you take a look at the OpenCV source code, you will be surprised by the simplicity of its implementation, no advanced design concepts are used, no\u00a0over-engineering, just some basic principles applied.<\/p>\n<p>[adrotate banner=&#8221;3&#8243;]<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>OpenCV\u00a0(Open Source Computer Vision) is a library of programming functions mainly aimed at real-time computer vision, developed by Intel Russia research center in Nizhny Novgorod. The library is cross-platform. It focuses mainly on real-time image processing. OpenCV is widely used,\u00a0Adopted all around the world, for end users, it\u2019s very mature and powerful, for developers it&#8217;s &hellip; <a href=\"https:\/\/cppdepend.com\/blog\/some-c-good-practices-from-the-opencv-source-code\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Some C++ good practices from the OpenCV source code&#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":[32,13,42],"class_list":["post-324","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-code-quality","tag-cpp","tag-opencv"],"_links":{"self":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/324","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=324"}],"version-history":[{"count":6,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/324\/revisions"}],"predecessor-version":[{"id":1252,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/posts\/324\/revisions\/1252"}],"wp:attachment":[{"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/media?parent=324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/categories?post=324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cppdepend.com\/blog\/wp-json\/wp\/v2\/tags?post=324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}