{"id":111,"date":"2024-03-26T18:48:00","date_gmt":"2024-03-26T18:48:00","guid":{"rendered":"https:\/\/permutationcity.co.uk\/bp\/?p=111"},"modified":"2024-04-28T12:05:46","modified_gmt":"2024-04-28T12:05:46","slug":"when-to-warn","status":"publish","type":"post","link":"https:\/\/permutationcity.co.uk\/bp\/2024\/03\/26\/when-to-warn\/","title":{"rendered":"When to warn"},"content":{"rendered":"\n<p>If the software you&#8217;re developing has a problem then you want to know about it.\nWe use log messages at runtime,\nbuild messages at compile time and we can run extra tools to tell us even more about our code.\nHowever there can be so many messages they you don&#8217;t end up reading them, at least not the ones that count.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fatal-errors\">Fatal errors<\/h2>\n\n\n\n<p>I like fatal errors.\nThat is, I don&#8217;t like getting fatal errors but it&#8217;s much better than spending days tracking down a bug.\nAs this is a <em>fatal<\/em> error is it still a warning?\nI&#8217;m going to say yes.\nThe message attached is the warning and <em>there should be an attached warning<\/em>.<\/p>\n\n\n\n<p>I&#8217;m use to having a set of logging functions like this:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">void log::Debug(const std::string&amp; format, ...);\nvoid log::Info(const std::string&amp; format, ...);\nvoid log::Warning(const std::string&amp; format, ...);\nvoid log::Error(const std::string&amp; format, ...);\nvoid log::Fatal(const std::string&amp; format, ...);<\/pre><\/div>\n\n\n\n<p>And that last one logs a message and exits the program.\nYou might come at it from the other direction and have exit functions like this:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">void ExpectedExit();\nvoid UnexpectedExit(int code, const std::string&amp; format, ...);\n<\/pre><\/div>\n\n\n\n<p>I wouldn&#8217;t just use <code>exit<\/code> because then someone can forget to use a message.\nGenerally speaking if someone can do something they are going to do it at some point.<\/p>\n\n\n\n<p>This is when something catastrophic has gone wrong and continuing makes no sense.\nWhat this means depends on the product.<\/p>\n\n\n\n<p>Recently I&#8217;ve been working on batch processes which powered a web service.\nThat meant exiting made sense even with fairly simple things such as the configuration file being missing.\nThe end user wasn&#8217;t able to touch the configuration directly so the file really should have been there.\nThe web front end was still there to interact with the user.<\/p>\n\n\n\n<p>If your process is interacting directly with the user then a fatal error is less useful.\nIdeally if something goes wrong you tell the user with a status message or dialogue box and continue,\na warning can go to the log file as well.\nHowever depending on what the &#8220;something&#8221; is continuing may or may not be possible.\nAgain, to avoid wasting time tracking down bugs it&#8217;s better to detect an error and exit than just crash.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"warnings-everywhere\">Warnings everywhere<\/h2>\n\n\n\n<p>It helps if the team has a clear idea of what each logging level is used for.\nWhat is the difference between <code>log::Debug<\/code> and <code>log::Info<\/code>?\nMaybe the first has low level details including variables and the second shows more general program flow.\nWhat is the difference between <code>log::Warning<\/code> and <code>log::Error<\/code>?\nMaybe the later is the underlying problem and the former is the chaos that is caused.<\/p>\n\n\n\n<p>It&#8217;s fairly common to end up drowning in messages.\nBe especially careful with <code>log::Warning<\/code> and <code>log::Error<\/code>.\nIf you it&#8217;s possible do some extra processing to weed out red herrings.\nIdeally these messages should really mean something.\nSeeing one should make you stop and investigate&#8230; otherwise you run the risk of habituating to them.\nOnce you&#8217;re use to warnings it&#8217;s very easy to miss new ones when they really matter.\nThis is where <code>log::Fatal<\/code> has an advantage because it&#8217;s impossible to ignore.<\/p>\n\n\n\n<p>I think the most common occurrence of this is with build systems.\nA lot of systems, especially legacy systems, have so many build warnings they cease to have meaning.\nIf possible start your project by switching on &#8220;warnings as errors&#8221;.\nThis will force you to go the extra step and keep a clean build.\nThat means potential problems that do appear will be caught immediately.\nOf course, it normally means jumping through some extra hoops in your code to satisfy the compiler.\nIt&#8217;s a bit of extra work but rarely hard.<\/p>\n\n\n\n<p>A particularly annoying situation here is changing or updating your compiler.\nAll of a sudden code that was &#8220;clean&#8221; is now flagged as problematic.\nI didn&#8217;t like some of my recent experience with automatic compiler updates.\nIt meant that whomever was updated first suddenly had a broken build.\nMixing their original branch with this fix can be confusing and\nmay end up duplicating work if someone else hits the same update.\nReally fixing the build in this situation is a separate task.\nIdeally it could be noticed and scheduled rather than dropping in unexpectedly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"and-now-sonarqube\">And now SonarQube<\/h2>\n\n\n\n<p><a href=\"https:\/\/www.sonarsource.com\/products\/sonarqube\/\">SonarQube<\/a> is my original inspiration for this post.\nIt&#8217;s a code analysis tool that can integrate with your build system and give you feedback on\na variety of problems, both actual and potential.\nIn many ways it&#8217;s good although\n<a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/02\/04\/a-step-too-far\/\">I don&#8217;t always agree with every rule<\/a>.\nImagine a code review but a knowledgable but pedantic colleague.\nMaybe a bit irritating on minor issues but helpful in the long run?<\/p>\n\n\n\n<p>My experience was that it&#8217;s a bit like the situation with automatic updates.\nIn an instant the codebase went from being warning free to having hundreds of issues.\nNo bugs or security issues but many code smells.\nIt&#8217;s good that we could know about them but very distracting that we suddenly did know about them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Some are easy to fix, some are hard.<\/li>\n\n\n\n<li>Some are important, some really aren&#8217;t.<\/li>\n\n\n\n<li>Some warnings need fixing, some need suppressing.<\/li>\n\n\n\n<li>Should they be fixed now or when nearby code is changed?<\/li>\n\n\n\n<li>Who is responsible for each one?<\/li>\n<\/ul>\n\n\n\n<p>With hundreds of warnings to fix it&#8217;s very easy to focus on getting rid of them now\nrather than getting rid of them right.\nIn the end we ended up with more complicated branches,\nmultiple fixes for individual smells and the wrong fixes for some of them.\nMonths later there were still a couple of hundred of the harder ones left.<\/p>\n\n\n\n<p>In retrospect starting with all the warnings is probably a mistake for an existing project. Using a configuration that restricted what was reported would have made it easier to focus. Choosing a set of smells to worry about and only checking for them. Indeed the branch that enabled a set of checks could also be where those smells are fixed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">On balance<\/h2>\n\n\n\n<p>I think warning can be very useful. We do want to know when something is wrong. However too many warnings can be just as problematic as too few. If you dealing with lots of warnings but they don&#8217;t mean much or with no warnings but lots of problems then maybe stop and think about what is actually going on.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If the software you&#8217;re developing has a problem then you want to know about it. We use log messages at runtime, build messages at compile time and we can run extra tools to tell us even more about our code. However there can be so many messages they you don&#8217;t end up reading them, at [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[1],"tags":[12,18],"class_list":["post-111","post","type-post","status-publish","format-standard","hentry","category-general","tag-debugging","tag-tools"],"_links":{"self":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/111","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/comments?post=111"}],"version-history":[{"count":3,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/111\/revisions"}],"predecessor-version":[{"id":207,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/111\/revisions\/207"}],"wp:attachment":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/media?parent=111"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/categories?post=111"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/tags?post=111"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}