{"id":257,"date":"2024-07-23T18:36:00","date_gmt":"2024-07-23T18:36:00","guid":{"rendered":"https:\/\/permutationcity.co.uk\/bp\/?p=257"},"modified":"2024-07-27T15:39:13","modified_gmt":"2024-07-27T15:39:13","slug":"iterative-development","status":"publish","type":"post","link":"https:\/\/permutationcity.co.uk\/bp\/2024\/07\/23\/iterative-development\/","title":{"rendered":"Iterative development"},"content":{"rendered":"\n<p>It can be useful to develop in a series of small steps. At each point trying to write the code that you need but not too much more. Building a huge library that you think you&#8217;ll need <a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/05\/14\/forever-change\/\">might be a waste of time<\/a> but building something small that lets you simplify you current code is worthwhile.<\/p>\n\n\n\n<p>I&#8217;ve often do this at work but that code isn&#8217;t available to me here.\nSo a direct demonstration isn&#8217;t possible.\nInstead I&#8217;ve have done\n<a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/02\/22\/building-to-throw-away\/\">some prototyping<\/a>\nand I&#8217;ll use that to tell the story.\nI&#8217;m going to use the example of a bit manipulation library because I&#8217;ve done one before.\nLets imagine we&#8217;re working on some sort of packet inspector on a network.\nIn particular I&#8217;m going to reference the\n<a href=\"https:\/\/en.wikipedia.org\/wiki\/Transmission_Control_Protocol\">TCP segment structure<\/a>\nin the code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"direct-manipulation\">Direct manipulation<\/h2>\n\n\n\n<p>The first way to access bit flags is directly with basic bit manipulation and some masks.<\/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;}\">bool IsECE(const std::array&lt;std::byte, 56&gt;&amp; segmentHeader) {\n    const auto flags = segmentHeader[13];\n    return ((flags &gt;&gt; 1) &amp; 1u) &amp;&amp; ((flags &gt;&gt; 6) &amp; 1u);\n}<\/pre><\/div>\n\n\n\n<p>This works but for me this is just not enough.\nIf someone comes across this later it will mean nothing.\nMy minimum would be to have a comment or some helpfully named types and constants, perhaps both. <\/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;}\">\/\/ https:\/\/en.wikipedia.org\/wiki\/Transmission_Control_Protocol\n\nstruct TcpSegmentHeader {\n...\n    uint8_t DataOffsetAndReserved;\n    uint8_t Flags;\n...\n};\n\nconst uint8_t gc_DataOffsetBitIndex(4);\nconst uint8_t gc_DataOffsetBitSize(4);\n...\nconst uint8_t gc_ExplicitCongestionNotificationBitIndex(6);\n...\nconst uint8_t gc_SynchronizeSequenceNumbersBitIndex(1);\n...<\/pre><\/div>\n\n\n\n<p>I could have used the abbreviated form of the flag names but\n<code>gc_CongenstionWindowReducedBitIndex<\/code> appeals to me more than <code>gc_SwrBitIndex<\/code>.\nThat lets me re-write the function.<\/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;}\">bool IsExplicitCongestionNotification(const TcpSegmentHeader&amp; segmentHeader) {\n    const auto flags = segmentHeader.Flags;\n    return ((flags &gt;&gt; gc_SynchronizeSequenceNumbersBitIndex) &amp; 1u) &amp;&amp;\n           ((flags &gt;&gt; gc_ExplicitCongestionNotificationBitIndex) &amp; 1u);\n}<\/pre><\/div>\n\n\n\n<p>Now someone looking at the code has a hope of understanding it. Next you might be asked to start updating the flags.<\/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 ClearExplicitCongestionNotificationFlag(TcpSegmentHeader&amp; segmentHeader) {\n    const auto&amp; flags = segmentHeader.Flags;\n    flags = flags &amp; ~(1u &lt;&lt; gc_ExplicitCongestionNotificationBitIndex);\n}<\/pre><\/div>\n\n\n\n<p>This isn&#8217;t hard but making a mistake becomes more likely. Did you mask the right thing? Was that the right operator to use? If you do it enough times one of them will be wrong. To me it is also less obvious what the code is doing. If I was skimming the code I could tell it&#8217;s doing bit manipulation but what sort? I mean, it <em>says<\/em> it&#8217;s &#8220;clearing the explicit congestion notification flag&#8221; but is that what it&#8217;s actually doing?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"bit-manipulation-library\">Bit manipulation library<\/h2>\n\n\n\n<p>So when you have a few of these it&#8217;s useful to make a functions to help. For the real thing I&#8217;d use template functions based on a <code>Value<\/code> type but I&#8217;ll skip that here for simplicity.<\/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;}\">namespace Bits\n{\n    Value MaskUpTo(uint8_t index);\n    Value Mask(uint8_t index, uint8_t size = 1);\n    \n    bool IsSet(Value value, uint8_t index);\n    bool IsClear(Value value, uint8_t index);\n    \n    bool IsAllSet(Value value, uint8_t index, uint8_t size = 1);\n    bool IsAnySet(Value value, uint8_t index, uint8_t size = 1);\n    bool IsNoneSet(Value value, uint8_t index, uint8_t size = 1);\n    \n    Value Clear(Value value, uint8_t index, uint8_t size = 1);\n    Value Set(Value value, uint8_t index, uint8_t size = 1);\n    Value Flip(Value value, uint8_t index, uint8_t size = 1);\n    \n    Value GetAt(Value value, uint8_t index, uint8_t size);\n    Value SetAt(Value value, uint8_t index, uint8_t size, Value subValue);\n} \/\/ namespace Bits<\/pre><\/div>\n\n\n\n<p>And I&#8217;ll take advantage of my new library and add some more functions.<\/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;}\">uint8_t GetDataOffset(const TcpSegmentHeader&amp; segmentHeader) {\n    return Bits::GetAt(segmentHeader.DataOffsetAndReserved,\n        gc_DataOffsetBitIndex, gc_DataOffsetBitSize);\n}\n\nvoid SetDataOffset(TcpSegmentHeader&amp; segmentHeader, uint8_t size) {\n    return Bits::SetAt(segmentHeader.DataOffsetAndReserved,\n        gc_DataOffsetBitIndex, gc_DataOffsetBitSize, size);\n}\n\nbool IsExplicitCongestionNotification(const TcpSegmentHeader&amp; segmentHeader) {\n    const auto flags = segmentHeader.Flags;\n    return Bits::IsSet(flags, gc_SynchronizeSequenceNumbersBitIndex) &amp;&amp;\n           Bits::IsSet(flags, gc_ExplicitCongestionNotificationBitIndex);\n}\n\nvoid ClearExplicitCongestionNotificationFlag(TcpSegmentHeader&amp; segmentHeader) {\n    const auto&amp; flags = segmentHeader.Flags;\n    flags = Bits::Clear(flags, gc_ExplicitCongestionNotificationBitIndex);\n}<\/pre><\/div>\n\n\n\n<p>This is much better. The function names tell you what&#8217;s happening. It&#8217;s easier to write and easier to read. The type constraints from the functions make it a safer as well. Unit tests can make sure at least this part of your logic is right.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"bit-manipulation-classes\">Bit manipulation classes<\/h2>\n\n\n\n<p>If you continue to expand your codebase you can make it even easier. The API is functional but the code it produces could be more concise.<\/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;}\">namespace Bits\n{\n    template &lt;typename Value&gt;\n    class Index\n    {\n    public:\n        Index(uint8_t index);\n\n        bool IsSet(Value value) const;\n        bool IsClear(Value value) const;\n\n        Value Set(Value value) const;\n        Value Clear(Value value) const;\n        Value Flip(Value value) const;\n    ...\n    };\n\n    template &lt;typename Value&gt;\n    class Range\n    {\n    public:\n        Range(uint8_t index, uint8_t size);\n\n        bool IsAllSet(Value value) const;\n        bool IsAnySet(Value value) const;\n        bool IsNoneSet(Value value) const;\n\n        Value Set(Value value) const;\n        Value Clear(Value value) const;\n        Value Flip(Value value) const;\n\n        Value GetAt(Value value) const;\n        Value SetAt(Value value, Value subValue) const;\n    ...\n} \/\/ namespace Bits<\/pre><\/div>\n\n\n\n<p>Which requires some new constants.<\/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 Bits::Range&lt;uint32_t&gt; gc_DataOffsetBitRange(4, 4);\n...\nconst Bits::Index&lt;uint32_t&gt; gc_ExplicitCongestionNotificationBitIndex(6);\n...\nconst Bits::Index&lt;uint32_t&gt; gc_SynchronizeSequenceNumbersBitIndex(1);\n...<\/pre><\/div>\n\n\n\n<p>And I can simplify the functions some more.<\/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;}\">uint8_t GetDataOffset(const TcpSegmentHeader&amp; segmentHeader) {\n    return gc_DataOffsetBitRange.GetAt(segmentHeader.DataOffsetAndReserved);\n}\n\nvoid SetDataOffset(TcpSegmentHeader&amp; segmentHeader, uint8_t size) {\n    return gc_DataOffsetBitRange.SetAt(segmentHeader.DataOffsetAndReserved, size);\n}\n\nbool IsExplicitCongestionNotification(const TcpSegmentHeader&amp; segmentHeader) {\n    const auto flags = segmentHeader.Flags;\n    return gc_SynchronizeSequenceNumbersBitIndex.IsSet(flags) &amp;&amp;\n           gc_ExplicitCongestionNotificationBitIndex.IsSet(flags);\n}\n\nvoid ClearExplicitCongestionNotificationFlag(TcpSegmentHeader&amp; segmentHeader) {\n    const auto&amp; flags = segmentHeader.Flags;\n    flags = gc_ExplicitCongestionNotificationBitIndex.Clear(flags);\n}<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"library-performance\">Library performance<\/h2>\n\n\n\n<p>While there are benefits to this code: easy to write, easy to read, easy to test.\nYou might have concerns about performance.\nDirect bit manipulation is about fast as you can get.\nThere are assemble equivalents for most of this.\nIs this library going to use them?<\/p>\n\n\n\n<p>Performance is often less of an issue than people think but, if it is, you can check. Modern optimisers are pretty good but if the compiler isn&#8217;t using the best assembly then you can do something about it. Everything that uses these functions will gain the benefit. I&#8217;ve done some <a href=\"https:\/\/quick-bench.com\/q\/WojwVDpZPor_Qpdo1nyqy7DtrJw\">quick benchmarking<\/a> for this and my library looks neck and neck with direct manipulation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"skipping-to-the-end\">Skipping to the end<\/h2>\n\n\n\n<p>I&#8217;ve suggested building up this library in a series of small steps.\nHowever if you <em>know<\/em> you&#8217;ll be using something a lot\nit might be better to go for a good interface with a bad implementation.\nI could have gone straight for the <code>Bits::Index<\/code> and <code>Bits::Range<\/code> classes but\nimplementing it with <code>std::bitset<\/code>.\nIt would probably have involved a lot of conversion between types and\nlooping through arrays of bits.\nThat means it would have been slow but\nit would have still worked.\nI could have let me get on to the urgent packet inspection work.\nIf you can get a good interface the implementation can always be fixed later on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"in-the-end\">In the end<\/h2>\n\n\n\n<p>It matters less whether you take it in small steps or skip to the end.\nThat comes down to how much you can predict about where the code is going.\nIt&#8217;s about noticing patterns that occur in your codebase and then simplifying those patterns.\nI&#8217;ve posted about this before when thinking about\n<a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/03\/12\/how-often\/\">DRY<\/a>.\nThere is a bit of extra work to notice and formalise the pattern but\nfuture work is then easier in many ways.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It can be useful to develop in a series of small steps. At each point trying to write the code that you need but not too much more. Building a huge library that you think you&#8217;ll need might be a waste of time but building something small that lets you simplify you current code is [&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":[7,11],"class_list":["post-257","post","type-post","status-publish","format-standard","hentry","category-general","tag-performance","tag-planning"],"_links":{"self":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/257","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=257"}],"version-history":[{"count":2,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/257\/revisions"}],"predecessor-version":[{"id":262,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/257\/revisions\/262"}],"wp:attachment":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/media?parent=257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/categories?post=257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/tags?post=257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}