{"id":89,"date":"2024-03-12T18:47:00","date_gmt":"2024-03-12T18:47:00","guid":{"rendered":"https:\/\/permutationcity.co.uk\/bp\/?p=89"},"modified":"2024-10-21T15:08:25","modified_gmt":"2024-10-21T15:08:25","slug":"how-often","status":"publish","type":"post","link":"https:\/\/permutationcity.co.uk\/bp\/2024\/03\/12\/how-often\/","title":{"rendered":"How often?"},"content":{"rendered":"\n<p>Don&#8217;t Repeat Yourself (DRY) is, ironically, said quite a lot.\nI think in <em>general<\/em> this is uncontroversial.\nIf you have a choice between writing a lot of very similar code:<\/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;}\">    std::vector&lt;int&gt; numbers;\n    numbers.append(0);\n    numbers.append(1);\n    numbers.append(2);\n    numbers.append(3);\n    numbers.append(4);\n    numbers.append(5);\n    numbers.append(6);\n    numbers.append(7);<\/pre><\/div>\n\n\n\n<p>Or something smaller that does the same job:<\/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;}\">    std::vector&lt;int&gt; numbers;\n    for (size_t i = 0; i &lt; 8; i++) {\n        numbers.append(i);\n    }<\/pre><\/div>\n\n\n\n<p>You are probably going to choose the later.\nMaybe you think this is an overly simple example but I&#8217;ll come back to it later.<\/p>\n\n\n\n<p>There are a number of reasons that DRY makes sense:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Reducing code size: Less to read and less to understand.<\/li>\n\n\n\n<li>Identical behaviour: One piece of code has one behaviour.<\/li>\n\n\n\n<li>Easy updates: One place to change and everything is updated.<\/li>\n\n\n\n<li>Fewer bugs: One place for bugs, one place to fix bugs.<\/li>\n\n\n\n<li>Easier testing: Less code to test.<\/li>\n\n\n\n<li>Better code: Less code can be better checked and optimised.<\/li>\n<\/ul>\n\n\n\n<p>However this isn&#8217;t without costs both initial and ongoing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Sharing code: Everything must be able to access the master version.<\/li>\n\n\n\n<li>Recognising duplication: Sometimes it&#8217;s not obvious what counts.<\/li>\n\n\n\n<li>Removing duplication: Refactoring always takes time and effort.<\/li>\n\n\n\n<li>Added complexity: A few similar functions can be easier to write than a single clever one.<\/li>\n<\/ul>\n\n\n\n<p>So, while repetition can be bad, I don&#8217;t think it can be as simple as <em>never<\/em> repeat yourself.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-often-is-too-often\">How often is too often?<\/h2>\n\n\n\n<p>Over the years I&#8217;ve talked to a few people about this and a common threshold to think about this is 3.\nSo that could be 3 lines, 3 functions, 3 files.<\/p>\n\n\n\n<p>I&#8217;m going to go further and say that you should start thinking about it at 2.\nAs soon as you notice your repeating something at all, start thinking about whether it would be better to refactor.\nAll the standard reason for DRY apply, admittedly with lower benefits for such a small number.\nHowever <em>you<\/em> repeating yourself the first time doesn&#8217;t mean the code is only being repeated for the first time.\nIt&#8217;s very easy for many people to write similar code many times without anyone catching on.\nIf you can start looking for that repetition the project may get more benefit than just a couple of functions.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"copy-paste-is-problematic\">Copy-paste is problematic<\/h2>\n\n\n\n<p>When you are just getting started with a problem it&#8217;s hard to know what the code should look like at the end.\nIt&#8217;s very common to write a function then know you need something like it but different.\nA quick copy-paste and a few tweaks gets you a new but different function that does what you want.\nI do this as well.<\/p>\n\n\n\n<p>Where it falls down is when you have two, three or more functions that are 90% the same.\nMaybe the codebase is stable and these don&#8217;t change.\nHowever my experience is that requirements change over time and so the code has to change.\nWhat are the chances that all these functions are going to be changed in the same way at the same time?\nEven if all the functions still work they have begun to diverge.<\/p>\n\n\n\n<p>I have spent literally years, on and off, with a project trying to pull two sets of classes back together.\nOne set of classes was obviously copied from another and then both were changed as required.\nThey did <em>very<\/em> similar things. So much of the code was <em>almost<\/em> the same.\nHowever there can be a big difference between the same and almost the same.\nEvery time I needed to make a change both sets of classes had to be updated separately!\nEventually I was able to account for or remove all the differences.\nAlmost everything could be done by a single code path with a few specific differences.\nFuture changes were smaller and quicker.<\/p>\n\n\n\n<p>As I said before, I often start with some copy-pasting.\nOnce I have working code and before I start checking in there&#8217;s a chance for review.\nIt&#8217;s often easy to replace a few custom functions with a generic one which has a few extra parameters.\nMaybe you keep the custom functions around but the call the generic function to do the heavy work.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"thinking-small\">Thinking small<\/h2>\n\n\n\n<p>Although removing large duplications can lead to big benefits you can also remove lots of little duplications.\nIn my initial example many people would be happy to leave it here:<\/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;}\">    std::vector&lt;int&gt; numbers;\n    for (size_t i = 0; i &lt; 8; i++) {\n        numbers.append(i);\n    }<\/pre><\/div>\n\n\n\n<p>However filling a vector with &#8220;stuff&#8221; is probably happening in lots of places as well:<\/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;}\">    std::vector&lt;int&gt; numbers;\n    std::generate_n(numbers.begin(), 8, [](const int i){ return i; });<\/pre><\/div>\n\n\n\n<p>This has fewer significant lines but you could argue against it as the techniques it uses are more complicated.\nWe can go further:<\/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;&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    const auto numbers = ext::generate_n&lt;std::vector&lt;int&gt;&gt;(8, ext::identity);<\/pre><\/div>\n\n\n\n<p>To <em>me<\/em> this is a better as it uses one line to give us exactly what we want. We&#8217;ve moved beyond what the standard template library provides. I&#8217;m assuming our own <code>ext<\/code> library provides a templated <code>generate_n<\/code> function to create a collection and a templated <code>identity<\/code> function which returns the value it&#8217;s given. Those are both very general functions which can be used in lots of other situations.<\/p>\n\n\n\n<p>A library might not provide exactly you need but that doesn&#8217;t have to mean hand-crafting things all the time.\nRemoving very small duplications can be worth it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>All sorts of operations on all sorts of collections, e.g. custom comparison operations for your data.<\/li>\n\n\n\n<li>A function wrapper that uses fewer parameters, e.g. replace <code>log(INFO, ...)<\/code> with <code>info(...)<\/code>.<\/li>\n\n\n\n<li>Your favourite string operations, e.g. <code>contains<\/code> was only implemented in C++23!<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"when-its-hard\">When it&#8217;s hard<\/h2>\n\n\n\n<p>Sometimes it&#8217;s not easy to avoid duplication.\nDuplication can exist in very separate areas.\nWhether that&#8217;s different libraries, languages, platforms or departments.\nThese things should be identical but the only connection may be the specification.<\/p>\n\n\n\n<p>In my last project we had to run code on two different platforms and ensure they were in sync.\nInitially both sets of were separately written in different languages.\nEssentially no functional changes were made to the code because of the overhead this created.\nEventually I was to use something like cross-compilation to simplify this.\nSuddenly changes to the code could be made easily&#8230; but there was a bigger build system to maintain.<\/p>\n\n\n\n<p>I don&#8217;t know a general solution here because the reasons can be very different.\nIf you <em>can<\/em> manage it then the normal benefits apply.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"when-to-repeat-yourself\">Repeating yourself<\/h2>\n\n\n\n<p>Every so often you&#8217;re going to come across where it does make most sense to repeat yourself.\nTo me this probably comes down to overall complexity both now and in the future.\nMost often this is going to be at the lower end of repetitions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If it&#8217;s just a specific 2 or 3 times then it may not be worth factoring out a function or a lambda.<\/li>\n\n\n\n<li>If things <em>happen<\/em> to be the same but are not required to be the same then it may not make sense,\nindeed calling common code could lead to confusion.<\/li>\n\n\n\n<li>If making common code adds a lot of complexity then a bit of repetition may be more understandable.<\/li>\n\n\n\n<li>If the code is likely to change often it then repeated refactoring may be too costly.<\/li>\n\n\n\n<li>If the code is unlikely to ever change then maybe it can just wait.<\/li>\n<\/ul>\n\n\n\n<p>Do remember the benefits, especially if it could be used elsewhere. The most basic guideline might be to use whichever version of the code is shorter&#8230; as long as it&#8217;s still understandable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">P.S.<\/h2>\n\n\n\n<p>I&#8217;ve noticed a few issues with my example:<\/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;}\">    const auto numbers = ext::generate_n&lt;std::vector&lt;int&gt;&gt;(8, ext::identity);<\/pre><\/div>\n\n\n\n<p><a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/01\/31\/we-all-make-mistakes\/\">Mistakes do happen<\/a> but we can still try to improve. So what are the problems:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>I intended to mimic<code>std::generate_n<\/code> here but it wouldn&#8217;t accept this sort of function. Instead it expects a function that takes no parameters. It might be better to choose a different name to avoid misleading people.<\/li>\n\n\n\n<li>There isn&#8217;t enough type information for the compiler to work it all out. It is best to test these things.<\/li>\n\n\n\n<li>My <a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/02\/27\/good-names\/\">naming guidelines<\/a> say to avoid non-standard contracts and here is <code>ext<\/code>. Depending on your code some namespaces can be referenced a lot. A long namespace identifier can end up weighing the code down. I might have to come up with a new exception for namespaces in my guidelines.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Don&#8217;t Repeat Yourself (DRY) is, ironically, said quite a lot. I think in general this is uncontroversial. If you have a choice between writing a lot of very similar code: Or something smaller that does the same job: You are probably going to choose the later. Maybe you think this is an overly simple example [&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":[25],"class_list":["post-89","post","type-post","status-publish","format-standard","hentry","category-general","tag-acronyms"],"_links":{"self":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/89","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=89"}],"version-history":[{"count":7,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/89\/revisions"}],"predecessor-version":[{"id":401,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/89\/revisions\/401"}],"wp:attachment":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/media?parent=89"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/categories?post=89"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/tags?post=89"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}