{"id":41,"date":"2023-01-27T02:41:00","date_gmt":"2023-01-27T02:41:00","guid":{"rendered":"https:\/\/blogs.oregonstate.edu\/clangdo\/?p=41"},"modified":"2023-03-10T03:57:57","modified_gmt":"2023-03-10T03:57:57","slug":"clean-code","status":"publish","type":"post","link":"https:\/\/blogs.oregonstate.edu\/clangdo\/2023\/01\/27\/clean-code\/","title":{"rendered":"Clean Code"},"content":{"rendered":"\n<p>From my university experience, my personal projects, and my volunteer work on web apps and tutoring, I have learned that developing software is like a battle. I know conflict is a tired metaphor but stick with me for a bit. In this metaphorical battle the programmer struggles against numerous and varied adversaries. Among these foes are functional constraints like &#8220;I must get the computer to render a convincing ocean at 60+ frames per second,&#8221; logistical constraints like &#8220;I need to communicate this really complex idea quickly to my teammates,&#8221; and operational constraints like &#8220;I need other developers to be able to work with this code base in the future.&#8221; It is this last ostensible category, and indeed this last example, that begets the need for clean code.<\/p>\n\n\n\n<p>&#8220;Clean code&#8221; is simply quickly comprehensible code. It tends to be free of &#8220;smells&#8221; which are indicators that your code could be simpler, more descriptive, or simply more intuitive. Is my code pristine, does it smell perfectly fresh? No, of course not, and I found a <a href=\"https:\/\/pragmaticways.com\/31-code-smells-you-must-know\/\">reasonably comprehensive article<\/a> to benchmark against so I can show you why not. Let&#8217;s look at a simple piece of code I wrote to fill a two channel (two numbers stored per pixel) texture with random data and let&#8217;s compare this code against the article.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fn create_seed() -&gt; Image {\n    let texture_extent = Extent3d {\n        width: TEXTURE_SIZE.x,\n        height: TEXTURE_SIZE.y,\n        depth_or_array_layers: 1\n    };\n\n    let mut data = Vec::new();\n    let channels = 2;\n    let size = channels * TEXTURE_SIZE.x * TEXTURE_SIZE.y;\n    \n    for _ in 0..size {\n        data.push(fastrand::u8(0..=0xff));\n    }\n\n    \/\/ We only need two channels for the seed.\n    Image::new(\n        texture_extent,\n        TextureDimension::D2,\n        data,\n        TextureFormat::Rg8Unorm,\n    )\n}<\/code><\/pre>\n\n\n\n<p>This is littered with under-descriptive names (#28) &#8220;size,&#8221; &#8220;data&#8221;. The single comment isn&#8217;t actually in the right place (which would probably be above channels), and doesn&#8217;t explain why (#1 in the code smells list) I&#8217;m pushing a bunch of random data into the image. I&#8217;m sure there are more things beside that that I&#8217;m blind to as well (I am looking at my own code after all). And this is <em>after<\/em> one refactor. Originally, this code was part of another function which created three different images of varying formats (doing multiple things is discussed in #9). Even now that other function contains duplicated code in the form of an identical texture_extent definition (#2 in the list). So I have terrible code in some respects. When under time pressure, it can be difficult to write clean code, and I still struggle to do so when I&#8217;m quickly prototyping.<\/p>\n\n\n\n<p>That said, I manage some things better than I used to. <a href=\"https:\/\/web.archive.org\/web\/20220126183049\/https:\/\/blog.mgattozzi.dev\/russian-dolls\/\">One particularly clear article<\/a> clearly explains a simple technique for clean code in Rust. It tells us how to use built-in functions to avoid the &#8220;nestiness&#8221; of rust. What do I mean by &#8220;nestiness&#8221;? Well everything is a block in Rust, functions, match clauses, if-let statements, loops, closures (lambdas), structure definitions (which can be nested), structure declarations, trait implementations, you get the picture. With all those opportunities, it&#8217;s easy to nest more than 3 blocks deep if you aren&#8217;t careful. The article clearly discusses one way to deal with this is by using functions which call other functions under certain conditions. The standard library is full of these &#8220;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Adapter_pattern\">adapters<\/a>&#8221; and utility functions. I used adapter utility methods often in my citygen project for a previous course. I wouldn&#8217;t say that the code in citygen is clean overall, but I did work hard to avoid significant nesting. See <a href=\"https:\/\/github.com\/clangdo\/citygen\/blob\/main\/cityservice\/src\/city\/mod.rs#L203-L212\">the example<\/a> below. (Still has poor names, oh well.)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ These are the x start and end pairs for the grid rectangles\nlet x_bounds = square_x_starts\n    .into_iter()\n    .zip(square_x_ends.into_iter());\n\n\/\/ These are the y start and end pairs for the grid rectangles\nlet y_bounds: Vec&amp;lt;(f64, f64)&amp;gt; = square_y_starts\n    .into_iter()\n    .zip(square_y_ends.into_iter())\n    .collect();\n<\/pre><\/div>\n\n\n<p>This post is long enough now, but to close I&#8217;ll say from looking at code around the internet, and at my own, it&#8217;s is easy to criticize, but hard to actually fix. The difficulty is exacerbated when you&#8217;re under the pressures of time constraints or you&#8217;re struggling to meet functional constraints. Hopefully in the future I can build in the time necessary to step back from the code and really check it for numerous code smells. By spending more time I might be able to fend off the adversary of deadlines long enough to finally emerge victorious over the notorious squad of code smells.<\/p>\n\n\n\n<p>Thanks for reading!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>From my university experience, my personal projects, and my volunteer work on web apps and tutoring, I have learned that developing software is like a battle. I know conflict is a tired metaphor but stick with me for a bit. In this metaphorical battle the programmer struggles against numerous and varied adversaries. Among these foes [&hellip;]<\/p>\n","protected":false},"author":12972,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[20,19,22,21,14,23],"class_list":["post-41","post","type-post","status-publish","format-standard","hentry","category-capstone-project","tag-clean-code","tag-code-smells","tag-efficiency","tag-refactoring","tag-rust","tag-syntax"],"_links":{"self":[{"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/posts\/41","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/users\/12972"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/comments?post=41"}],"version-history":[{"count":3,"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/posts\/41\/revisions"}],"predecessor-version":[{"id":51,"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/posts\/41\/revisions\/51"}],"wp:attachment":[{"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/media?parent=41"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/categories?post=41"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/clangdo\/wp-json\/wp\/v2\/tags?post=41"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}