<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>You Want Me To Recurse WHAT‽</title>
    <description>An ankle-deep dive into Chris's thoughts.
</description>
    <link>https://parich.us/</link>
    <atom:link href="https://parich.us/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 23 Jul 2021 12:12:46 -0500</pubDate>
    <lastBuildDate>Fri, 23 Jul 2021 12:12:46 -0500</lastBuildDate>
    <generator>Jekyll v3.8.6</generator>
    
      <item>
        <title>Some packaging tips for unmirrored dpkg repos</title>
        <description>&lt;p&gt;Debian package has one wart I’ve been trying to fight with:&lt;/p&gt;

&lt;p&gt;The entire package mechanism assumes your source code is a managed mirror of upstream.&lt;/p&gt;

&lt;p&gt;For those of us who don’t want to mirror upstream and apply debian packaging rebases and patches, there’s a way to pull from upstream (especially github branch/tag archives) and produce a self-contained and self-cleaning build.&lt;/p&gt;

&lt;p&gt;I’ll use &lt;a href=&quot;https://github.com/LAStools/LAStools&quot;&gt;LAStools&lt;/a&gt; as my example since this is what I just finished packaging:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/make -f&lt;/span&gt;

include /usr/share/dpkg/default.mk

SOURCE_NAME:&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;DEB_SOURCE&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;-&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;DEB_VERSION_EPOCH_UPSTREAM&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
SOURCE_TAR:&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;SOURCE_NAME&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;.tar.gz
REMOTE_TAR:&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;https://github.com/LAStools/LAStools/archive/master.tar.gz
SOURCE_DIR:&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;LAStools-master/

clean:
        &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;SOURCE_DIR&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;SOURCE_TAR&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; obj-&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;DEB_HOST_MULTIARCH&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
        dh clean

build:
        wget &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;SOURCE_TAR&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;REMOTE_TAR&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xaf&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;SOURCE_TAR&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;debian/patches/series&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;patch &lt;span class=&quot;nt&quot;&gt;-p1&lt;/span&gt; &amp;lt; debian/patches/&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;i&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done
        &lt;/span&gt;dh build &lt;span class=&quot;nt&quot;&gt;--buildsystem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;cmake &lt;span class=&quot;nt&quot;&gt;--sourcedir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;SOURCE_DIR&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

%:
        dh &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;--sourcedir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;SOURCE_DIR&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;


override_dh_auto_configure:
        dh_auto_configure &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;    &lt;span class=&quot;nt&quot;&gt;-DCMAKE_LIBRARY_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;DEB_HOST_MULTIARCH&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DBUILD_SHARED_LIBS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ON

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This rules file will download the master.tar.gz archive from github, extract it to produce a ./LAStools-master, patch with the necessary cmake and security patches in debian/patches (similar to using quilt), then build in the LAStools-master subdirectory using cmake.&lt;/p&gt;

&lt;p&gt;If you’re using multiarch (you should be), you can use dh-exec capabilities to generate multiarch-compatible package.install files. dh-exec is less necessary in compat 13, but that isn’t finished being rolled out yet to downstream releases like Ubuntu.&lt;/p&gt;

&lt;p&gt;Here’s what i produced to make the cmake files show up in the liblastools-dev package:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/dh-exec
/usr/lib/${DEB_HOST_MULTIARCH}/cmake
/usr/include
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just mark the debian/liblastools-dev.install file as exectuable and dh-exec will take care of the rest.&lt;/p&gt;

&lt;p&gt;A few callouts:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;I used &lt;code class=&quot;highlighter-rouge&quot;&gt;3.0 (custom)&lt;/code&gt; in debian/source/format, but I can’t say that was absolutely necessary for this build setup&lt;/li&gt;
  &lt;li&gt;make sure you use &lt;code class=&quot;highlighter-rouge&quot;&gt;include /usr/share/dpkg/default.mk&lt;/code&gt; in your makefile to get access to common packaging variables&lt;/li&gt;
  &lt;li&gt;Quilt (via dpkg-source) will automatically apply the patches listed by debian/patches/series, but that only works if you’re using importing from a .dsc file meaning somebody has already generated a debian package archive ahead of time.&lt;/li&gt;
  &lt;li&gt;Not all of us give a hoot about producing Debian hosting conformant packages with signing, etc, so you can pass &lt;code class=&quot;highlighter-rouge&quot;&gt;--no-sign&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;dpkg-buildpackage&lt;/code&gt; to skip that step.&lt;/li&gt;
  &lt;li&gt;CMake build system isn’t set to produce shared libs by default so make sure to set &lt;code class=&quot;highlighter-rouge&quot;&gt;-DBUILD_SHARED_LIBS=ON&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;override_dh_auto_configure&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Since I wanted an atomically rebuild-able library I overrode the default build steps for dpkg-buildpackage
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dpkg-buildpackage -Tclean,build,binary,clean --no-sign&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;I still had to go through the original rigamarole of producing a base package, getting quilt/dquilt configured and producing a patch series, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s what I did to create the initial project structure to prepare for quilt patching:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; lastools-0.1.0.tar.gz https://github.com/LAStools/LAStools/archive/master.tar.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;lastools-0.1.0&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;lastools-0.1.0
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dh_make &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ../lastools-0.1.0.tar.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xaf&lt;/span&gt; ../lastools-0.1.0.tar.gz
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dquilt new 1.patch
... apply changes
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dquilt refresh
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dquilt new 2.patch
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dquilt refresh
... etc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This gave me the initial debian/ files to work with. From there, updating debian/rules, debian/control, debian/changelog, debian/source/format to produce a downloaded build was all that was necessary. All the other generated files can be removed except for debian/patches as this is what Quilt produces and you’ll want to re-apply them for your repeatable build.&lt;/p&gt;

&lt;p&gt;You’ll want to make sure to manage your changelog, I don’t need to do that yet for this release so we’ll see how to get upstream comments in from the remote archive at a later date. In general, probably don’t care about this too much beyond just annotating releases&lt;/p&gt;
</description>
        <pubDate>Fri, 23 Jul 2021 00:00:00 -0500</pubDate>
        <link>https://parich.us/blog/2021/07/23/dpkg.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2021/07/23/dpkg.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>A neat trick for function pointer lambdas in C++</title>
        <description>&lt;p&gt;I just learned of a neat trick for getting a function pointer from a lambda in C++. This is not my code but I am passing it along for others should you happen upon my humble blog.&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;cstdio&amp;gt;
#include &amp;lt;typeinfo&amp;gt;
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s %p&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s %p&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%s %p&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeid&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;produces&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ./test | c++filt -t
main::{lambda()#1} 0x7ffde2731538
void (*)() 0x401131
void (*)() 0x40115d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also use this trick with say &lt;code class=&quot;highlighter-rouge&quot;&gt;decltype(+x)&lt;/code&gt; (using the above snippet for context) to generate a function pointer type.&lt;/p&gt;

&lt;p&gt;Importantly, if you add a capture to &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt;’s declaration a compile error will occur on &lt;code class=&quot;highlighter-rouge&quot;&gt;y&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 16 Dec 2020 00:00:00 -0600</pubDate>
        <link>https://parich.us/blog/2020/12/16/neat-trick.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2020/12/16/neat-trick.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>2020 US Election</title>
        <description>&lt;p&gt;Am I really expected to believe this travesty of an election?&lt;/p&gt;

&lt;p&gt;Am I really expected to believe a man who underperformed his predecessors in every race except the 12 counties he needed at 4 AM the day after the election is legitimate?&lt;/p&gt;

&lt;p&gt;Am I really expected to believe a man who can barely fill a parking lot with empty rental cars for his victory speech is the winner?&lt;/p&gt;

&lt;p&gt;After countless tales of shenanigans on election night?&lt;/p&gt;

&lt;p&gt;After months of dire warnings on mail-in fraud?&lt;/p&gt;

&lt;p&gt;After numerous courts have ruled against the election night procedure changes?&lt;/p&gt;

&lt;p&gt;After those court rulings were ignored and illegal procedure changes were performed anyway?&lt;/p&gt;

&lt;p&gt;After numerous violations of Benford’s Law?&lt;/p&gt;

&lt;p&gt;After voting machines were shown to violate state and federal law on error rates?&lt;/p&gt;

&lt;p&gt;After audits showed voting machines were tampered with?&lt;/p&gt;

&lt;p&gt;After countless documented counting errors that only ever went in one direction?&lt;/p&gt;

&lt;p&gt;There are two things that keep the American Republic functioning today: Money and Voting.&lt;/p&gt;

&lt;p&gt;As long as my money is stable I can secure wealth over time and improve my and my children’s lives.&lt;/p&gt;

&lt;p&gt;As long as my vote counts, I can gather a smidgen of collective representation.&lt;/p&gt;

&lt;p&gt;The government has decimated my money’s value over the last 100 years, and especially the last year with these insane stimulus bills. They have decimated my ability to earn an income with these insane lock-downs.&lt;/p&gt;

&lt;p&gt;And now my vote has been made irrelevant with severe, blatant, and extensive cheating.&lt;/p&gt;

&lt;p&gt;I have no hope of representation.&lt;/p&gt;

&lt;p&gt;I have no faith in my ability to secure wealth via currency.&lt;/p&gt;

&lt;p&gt;The legacy of this country’s founding has been destroyed. Prepare for war.&lt;/p&gt;
</description>
        <pubDate>Tue, 15 Dec 2020 00:00:00 -0600</pubDate>
        <link>https://parich.us/blog/2020/12/15/election.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2020/12/15/election.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Codec for modern C++</title>
        <description>&lt;p&gt;I had some fun recently when working on my game.&lt;/p&gt;

&lt;p&gt;I got to build a type-safe encoder decoder utility set that can encode and decode arbitrary types (with overload). It was an enjoyable experience to build, and I figure I’d just like to share it&lt;/p&gt;

&lt;script src=&quot;https://gitlab.com/-/snippets/2005011.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Feel free to take this and use at your leisure, no copyright attribution is required.&lt;/p&gt;

</description>
        <pubDate>Sun, 16 Aug 2020 00:00:00 -0500</pubDate>
        <link>https://parich.us/blog/2020/08/16/codec.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2020/08/16/codec.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Formalizing My Design Principles</title>
        <description>&lt;p&gt;I’ve been spending a bit of time thinking about what it is I do when designing interfaces.
I definitely follow a few rules that I think are common:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;immutable by default&lt;/li&gt;
  &lt;li&gt;composition over inheritance&lt;/li&gt;
  &lt;li&gt;dependency injection&lt;/li&gt;
  &lt;li&gt;single responsibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But these don’t seem to capture my decision-making entirely, as other people don’t replicate my instructions with just these rules.&lt;/p&gt;

&lt;p&gt;After spending some time thinking about it, I’ve decided to name some new rules that I follow.&lt;/p&gt;

&lt;h2 id=&quot;mental-offloading&quot;&gt;Mental Offloading&lt;/h2&gt;

&lt;p&gt;Mental Offloading is the process by which you remove the need to consider what code is doing as you write it.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Methods should have clear inputs and outputs, be self-contained, and make no &lt;em&gt;mutations&lt;/em&gt; to system state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This last part of this statement is obviously impossible in the strictest sense, but it’s a goal rather than an outcome. 
The system state must be modifiable to make any program progress, so instead, consider that the function must not alter the behavior of the system after it has been called.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A print function should always print the same way.&lt;/li&gt;
  &lt;li&gt;A state machine must always consume it’s full language.&lt;/li&gt;
  &lt;li&gt;A class instance must be initialized completely before using it.&lt;/li&gt;
  &lt;li&gt;A class must allow for any order of initialization, and any order of method calls after initilization.&lt;/li&gt;
  &lt;li&gt;Don’t handle every case, make the cases you don’t want impossible instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important takeaway is that the programmer should not have to have a mental model of program state on each line of code. 
Pass off work to subroutines liberally, but have strict minimal interfaces for those subroutines.
Rather than writing a function with lots of parameters and tests and variability on output, write a function that does things one way, always the same way, is easy to test and verify; then when you consume it, the callsite should contain your mutations into and out of form.&lt;/p&gt;

&lt;h2 id=&quot;stateless-classes-stateful-functions&quot;&gt;Stateless classes, Stateful functions&lt;/h2&gt;

&lt;p&gt;As an extension of the above rule, tracking system state is the hardest part of software development.
So make it easy on yourself and everyone else:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Constrain all state mutations to be within a single function scope.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You should consider your program as a series of idempotent “entry points” rather than a continuous state graph.
Each entry point should progress the program state &lt;em&gt;completely&lt;/em&gt;.
Consider the principles of REST, where each HTTP verb has an explicit meaning, and server methods are idempotent.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Get - retrieve a document that exists&lt;/li&gt;
  &lt;li&gt;Put - update an existing document and return the result&lt;/li&gt;
  &lt;li&gt;Post - create a new document and return the result&lt;/li&gt;
  &lt;li&gt;Delete - destroy a document&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these methods maintain a consistent behavior no matter how many times called, or what order they are called in. 
Each method progresses the system state in some way, but no method causes the system to modify it’s behavior for any other invocation.&lt;/p&gt;

&lt;p&gt;Your goal should be to write functions that either finish what they are doing or do nothing at all.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Detect error conditions in your function as early as possible and bail out without mutating the data.&lt;/li&gt;
  &lt;li&gt;Pre-calculate all parameters for state transforms ahead-of-time and only use at the last possible moment.&lt;/li&gt;
  &lt;li&gt;Mutate copies of data if there is any potential for error during execution, and apply the mutation later.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;an-example&quot;&gt;An example&lt;/h2&gt;

&lt;p&gt;Consider a class that does some stateful work:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;foo_t&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurement_t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurement_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updateModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timestamp_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addMeasurements&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurement_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurements_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recalculateScores&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculateAverage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;measurement_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;average&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The mental model of this class is complex, as you have to remember which order to call it’s methods in, what their side effects are, and whether or not you can use each method at a certain time.
And while it may still fit inside of “SOLID” principles, dependency injection, composition over inheritnace, and immutable by default, the class is difficult to use.&lt;/p&gt;

&lt;p&gt;Consider an updated class:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;foo_t&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurement_t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurement_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;observe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timestamp_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurement_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurements_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;updateModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;addMeasurements&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurements_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;recalculateScores&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;calculateAverage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;measurement_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;average&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;private:&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updateModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timestamp_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addMeasurements&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurement_t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;measurements_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recalculateScores&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculateAverage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we have 3 operations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;initialize&lt;/li&gt;
  &lt;li&gt;mutate&lt;/li&gt;
  &lt;li&gt;query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As long as your write these operations to execute in any order, the programmer that uses these methods doesn’t need to track how they work, only that they will have an outcome. You have effectively offloaded the mental effort necessary to use your code to the code itself.&lt;/p&gt;

</description>
        <pubDate>Mon, 20 Apr 2020 00:00:00 -0500</pubDate>
        <link>https://parich.us/blog/2020/04/20/formalizing-design.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2020/04/20/formalizing-design.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Steam and Vulkan - updated</title>
        <description>&lt;p&gt;Qt and Vulkan work fine.&lt;/p&gt;

&lt;p&gt;Vulkan and Steam work fine.&lt;/p&gt;

&lt;p&gt;Qt and Steam do not work fine.&lt;/p&gt;

&lt;p&gt;Qt does some kind of weird behavior when inspecting the display layout that creates an early xcb window sized to the whole display. Steam catches this behavior and generates a Vulkan frame and adds input hooks to the early surface. Qt destroys this surface and generates a new one for your application’s widgets…&lt;/p&gt;

&lt;p&gt;I can’t seem to get Steam to behave correctly with Vulkan, so I’ve ripped Qt Vulkan out and replaced it with a fully hand-rolled renderer on top of GLFW3. I’m still keeping my signals though, Qt can stay for that.&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Jan 2020 00:00:00 -0600</pubDate>
        <link>https://parich.us/blog/2020/01/20/steam-and-vulkan-2.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2020/01/20/steam-and-vulkan-2.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Steam and Vulkan</title>
        <description>&lt;p&gt;Just a note if anybody doesn’t know already:&lt;/p&gt;

&lt;p&gt;To enable your Vulkan application to receive steam overlay support, make sure you add the Vulkan instance layer to your device initialization.&lt;/p&gt;

&lt;p&gt;Here’s mine:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;std::vector&amp;lt;char const *&amp;gt; const validationLayers = {
#ifndef NDEBUG
#ifndef Q_OS_ANDROID
    &quot;VK_LAYER_LUNARG_standard_validation&quot;,
#else
    &quot;VK_LAYER_GOOGLE_threading&quot;,
    &quot;VK_LAYER_LUNARG_parameter_validation&quot;,
    &quot;VK_LAYER_LUNARG_device_limits&quot;,
    &quot;VK_LAYER_LUNARG_object_tracker&quot;,
    &quot;VK_LAYER_LUNARG_image&quot;,
    &quot;VK_LAYER_LUNARG_core_validation&quot;,
    &quot;VK_LAYER_LUNARG_swapchain&quot;,
    &quot;VK_LAYER_GOOGLE_unique_objects&quot;,
#endif
#endif
    &quot;VK_LAYER_VALVE_steam_overlay_64&quot;,
    &quot;VK_LAYER_VALVE_steam_overlay_32&quot;,
};
&lt;/code&gt;&lt;/pre&gt;

</description>
        <pubDate>Fri, 05 Jul 2019 00:00:00 -0500</pubDate>
        <link>https://parich.us/blog/2019/07/05/steam-and-vulkan.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2019/07/05/steam-and-vulkan.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Qt Widgets and Vulkan</title>
        <description>&lt;p&gt;I had the hardest time getting Qt Widgets to be usable in the context of a Qt Vulkan Window, but I believe I’ve found a general method for using Qt Widgets on top of native drawing APIs.&lt;/p&gt;

&lt;p&gt;The simplified version is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Wrap your native drawing in a widget container (&lt;code class=&quot;highlighter-rouge&quot;&gt;createWidgetContainer&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Create a central widget to attach child widgets to&lt;/li&gt;
  &lt;li&gt;Set the central widget as a child of your native drawing container&lt;/li&gt;
  &lt;li&gt;Add a QImage field to the central widget&lt;/li&gt;
  &lt;li&gt;Override &lt;code class=&quot;highlighter-rouge&quot;&gt;paintEngine ()&lt;/code&gt; to return the QImage field’s &lt;code class=&quot;highlighter-rouge&quot;&gt;paintEngine ()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Upload the QImage to native rendering each frame as necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This of course has some overhead of copying image buffers around, especially to the GPU, as well as putting the updated texture in the correct form if you’re using Vulkan. But given the flexibility and power built-in to Qt Widgets, I definitely see the overhead being worth it.&lt;/p&gt;

&lt;p&gt;I’ll give a little bit of sample code from my current project using Vulkan to demonstrate.&lt;/p&gt;

&lt;h2 id=&quot;central-widget&quot;&gt;Central Widget&lt;/h2&gt;

&lt;p&gt;Let’s start with the central widget. I’m assuming you already have a robust renderer setup doing all the magic drawing you want in whatever way you please and now you want to put (alpha-enabled) widgets on top. If you’re just doing a viewport with widget support on the side, then the rest of this post won’t help you.&lt;/p&gt;

&lt;p&gt;In your constructor make sure to include &lt;code class=&quot;highlighter-rouge&quot;&gt;WA_NoSystemBackground&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;WA_TranslucentBackground&lt;/code&gt;. This should tell Qt not to expect to fill the widget background when drawing, and ensure that it uses a alpha channel when drawing as well. You’ll also want to call &lt;code class=&quot;highlighter-rouge&quot;&gt;setAutoFillBackground (false)&lt;/code&gt; to keep Qt from filling the background with during draw with system colors.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;centralWidget_t::centralWidget_t (QVulkanWindow *vulkan_) : m_vulkan (vulkan_)
{
	setAttribute (Qt::WA_NoSystemBackground);
	setAttribute (Qt::WA_TranslucentBackground);
	setAutoFillBackground (false);

	m_d-&amp;gt;video-&amp;gt;installEventFilter (this);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I added an event filter to track my Vulkan window’s resize event. This allows me to keep the central widget positioned at the window extents:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;bool centralWidget_t::eventFilter (QObject *const watched_, QEvent *const event_)
{
	Q_UNUSED (watched_);

	if (!event_)
		return false;

	QSize newSize;

	switch (event_-&amp;gt;type ())
	{
	case QEvent::Type::Resize:
		newSize = dynamic_cast&amp;lt;QResizeEvent *&amp;gt; (event_)-&amp;gt;size ();
		break;
	default:
		return false;
	}

	resize (newSize);
	move (0, 0);

	return false;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You’ll also want to override the &lt;code class=&quot;highlighter-rouge&quot;&gt;paintEngine ()&lt;/code&gt; method of the central widget. This is necessary to keep Qt from trying to draw everything to framebuffer but still allow widget interactions. In this method, &lt;code class=&quot;highlighter-rouge&quot;&gt;m_image&lt;/code&gt; is a QImage.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;QPaintEngine *centralWidget_t::paintEngine () const
{
	return m_image.paintEngine ();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, we need to get the frame uploaded and drawn. I’ll leave the transition, copy, and pipeline handling mechanisms as an excercise to the reader; if you’ve gotten this far these should be relatively simple.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;void centralWidget_t::prepareDraw (VkCommandBuffer cmd_)
{
	auto const deviceFn = m_vulkan-&amp;gt;deviceFn ();
	auto const device   = m_vulkan-&amp;gt;device ();
	auto const frameId  = m_vulkan-&amp;gt;currentFrame ();

	if (!m_img[frameId])
		return;

	m_frameDirty = clamp (m_frameDirty - 1, 0, m_video-&amp;gt;concurrentFrameCount ());

	if (m_frameDirty &amp;lt;= 0)
		return;

	m_frame.fill (Qt::transparent);
	QPainter painter (&amp;amp;m_frame);
	render (&amp;amp;painter);

	unsigned width  = size ().width ();
	unsigned height = size ().height ();

	// data hasn't been mapped before
	if (!m_memMap[frameId])
		deviceFn-&amp;gt;vkMapMemory (
		    device, m_txMem[frameId], 0, imageSize (size ()), 0, &amp;amp;m_memMap[frameId]);

	memcpy (m_memMap[frameId], m_frame.bits (), m_frame.sizeInBytes ());

	VkBufferImageCopy region{};
	region.bufferOffset                    = 0;
	region.bufferRowLength                 = 0;
	region.bufferImageHeight               = 0;
	region.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
	region.imageSubresource.mipLevel       = 0;
	region.imageSubresource.baseArrayLayer = 0;
	region.imageSubresource.layerCount     = 1;
	region.imageOffset                     = {0, 0, 0};
	region.imageExtent                     = {width, height, 1};

	// see https://vulkan-tutorial.com for reference functions
	transitionImageLayout (
	    m_vulkan,
	    cmd_,
	    m_img[frameId],
	    VK_IMAGE_LAYOUT_UNDEFINED,
	    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);

	deviceFn-&amp;gt;vkCmdCopyBufferToImage (
	    cmd_,
	    m_txBuffer[frameId],
	    m_img[frameId],
	    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
	    1,
	    &amp;amp;region);

	transitionImageLayout (
	    m_vulkan,
	    cmd_,
	    m_img[frameId],
	    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
	    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}

void centralWidget_t::draw (VkCommandBuffer const cmd_)
{
	auto const frameId = m_vulkan-&amp;gt;currentFrame ();

	if (!m_img[frameId]) // this is a VkImage
		return;

	// if you're using QVulkanRenderer defaults, this method should record and execute a 
	// secondary command buffer using the default renderpass settings
	drawImage (cmd_, m_view[frameId], m_sampler[frameId]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I know I haven’t shown you the class members or all the initialization. I’m going to justify this by saying you shouldn’t need to see them if you’ve studied the Vulkan API and &lt;a href=&quot;https://vulkan-tutorial.com&quot;&gt;vulkan-tutorial&lt;/a&gt;, and I don’t want you just copy-pasting this. I’ll eventually release this code under GPL anyway.&lt;/p&gt;

&lt;h2 id=&quot;qvulkanrenderer&quot;&gt;QVulkanRenderer&lt;/h2&gt;

&lt;p&gt;Now we need to ship commands off to the gpu. If you’re using QVulkanRenderer and QVulkanWindow defaults you’re probably already using the default renderpass which contains one subpass. If you’re not, have fun, you’re probably already ahead of me in terms of capabilities. In general your process should be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Start your subpass draw commands&lt;/li&gt;
  &lt;li&gt;Prepare your widget texture transitions&lt;/li&gt;
  &lt;li&gt;Run your primary subpass secondary command buffers&lt;/li&gt;
  &lt;li&gt;Run your widget texture draw command buffer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That will look probably a little like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;void startNextFrame () override
{
	auto const device      = m_video-&amp;gt;device ();
	auto const deviceFn    = m_video-&amp;gt;deviceFn ();
	m_frameId              = m_video-&amp;gt;currentFrame ();
	auto const cmd         = m_video-&amp;gt;currentCommandBuffer ();

	// start threaded drawing
	m_waitFrame[m_frameId] = false;
	emit m_video-&amp;gt;draw ();

	// render widget while we wait (note this adds pipeline barriers on the raster step)
	m_video-&amp;gt;centralWidget ()-&amp;gt;prepareDraw (cmd);

	while (!m_waitFrame[m_frameId])
		std::this_thread::yield ();

	// begin drawing
	VkClearColorValue        clearColor = ;
	VkClearDepthStencilValue clearDS    = {2.0f, 0};
	VkClearValue             clearValues[3];
	memset (clearValues, 0, sizeof (clearValues));
	clearValues[0].color        = clearColor;
	clearValues[1].depthStencil = clearDS;
	clearValues[2].color        = clearColor;

	QSize const    sz     = m_video-&amp;gt;swapChainImageSize ();
	unsigned const width  = sz.width ();
	unsigned const height = sz.height ();

	VkRenderPassBeginInfo rpBeginInfo{};
	memset (&amp;amp;rpBeginInfo, 0, sizeof (rpBeginInfo));
	rpBeginInfo.sType             = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
	rpBeginInfo.renderPass        = m_video-&amp;gt;defaultRenderPass ();
	rpBeginInfo.framebuffer       = m_video-&amp;gt;currentFramebuffer ();
	rpBeginInfo.renderArea.offset = {0, 0};
	rpBeginInfo.renderArea.extent = {width, height};
	rpBeginInfo.clearValueCount = 3;
	rpBeginInfo.pClearValues    = clearValues;

	deviceFn-&amp;gt;vkCmdBeginRenderPass (
	    cmd, &amp;amp;rpBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
	
	// submit our command buffers
	if (m_commandBufferList.size () &amp;gt; 0)
		deviceFn-&amp;gt;vkCmdExecuteCommands (
		    cmd,
		    static_cast&amp;lt;uint32_t&amp;gt; (m_commandBufferList.size ()),
		    m_commandBufferList.data ());

	// draw the widget onto a view-aligned quad after everything else
	m_video-&amp;gt;centralWidget ()-&amp;gt;draw (cmd);

	deviceFn-&amp;gt;vkCmdEndRenderPass (cmd);

	m_video-&amp;gt;frameReady ();
	m_video-&amp;gt;requestUpdate ();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;main-window&quot;&gt;Main Window&lt;/h2&gt;

&lt;p&gt;Somehwere in your main, you’ll need to capture your QVulkanWindow into a widget container using &lt;code class=&quot;highlighter-rouge&quot;&gt;QWidget::createWindowContainer ()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the basic process I followed:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C++&quot;&gt;int main (int argc, char *argv[])
{
	QApplication app (argc, argv);

	auto const myVulkan = new myQVulkanWindow ();
	auto const videoWidget = QWidget::createWindowContainer (myVulkan);

	auto const centralWidget = new centralWidget_t ();
	centralWidget-&amp;gt;setParent (videoWidget);

	centralWidget-&amp;gt;setLayout (new QVBoxLayout ());
	centralWidget-&amp;gt;layout ()-&amp;gt;addWidget (new mainMenu_t{});

	videoWidget-&amp;gt;resize (640, 480);
	videoWidget-&amp;gt;show ();

	return app.exec ();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And here we go!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/qt_vulkan_widgets.png&quot; alt=&quot;screenshot&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Jul 2019 00:00:00 -0500</pubDate>
        <link>https://parich.us/blog/2019/07/02/qt-widgets-vulkan.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2019/07/02/qt-widgets-vulkan.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>A thread-safe factory template</title>
        <description>&lt;p&gt;I was playing around with my multi-threaded vulkan renderer today and I managed to build a nice tool for managing my shared resources (mesh, texture, pipeline, etc. data).&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;factory_t&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared_ptr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared_ptr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unique_lock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_mapGuard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_wk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;mapLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlock&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

		&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock_guard&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_wk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)};&lt;/span&gt;

		&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shared_ptr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_wk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

			&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_wk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;                                                      &lt;span class=&quot;n&quot;&gt;m_mapGuard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weak_ptr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just provide a key and make sure your &lt;code class=&quot;highlighter-rouge&quot;&gt;create_&lt;/code&gt; functor is thread-safe and you’ll get per-key factory allocations with thread safety.&lt;/p&gt;

&lt;p&gt;If you want to use it, license it under GPL, LGPL, or MIT and maybe say nice things about me to your friends. Happy coding!&lt;/p&gt;

</description>
        <pubDate>Fri, 24 May 2019 00:00:00 -0500</pubDate>
        <link>https://parich.us/blog/2019/05/24/cpp-factory.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2019/05/24/cpp-factory.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>A Few Basic Principles For System Design (Part 3)</title>
        <description>&lt;p&gt;Building complex systems is never simple, but there are a few things you can do to make your life a bit easier. One of the hardest parts in designing these things is to make them testable, so that work tomorrow doesn’t break work today. I’ll go over a few concepts to make life easier when doing this.&lt;/p&gt;

&lt;h1 id=&quot;immutability&quot;&gt;Immutability&lt;/h1&gt;

&lt;p&gt;One easily applied hard-and-fast rule you can make for yourself and any code you write is to take advantage of immutability.&lt;/p&gt;

&lt;p&gt;If we look up &lt;a href=&quot;https://www.merriam-webster.com/dictionary/immutable&quot;&gt;immutability&lt;/a&gt;, we see that it means something cannot be changed. Applied here, we mean to never mutate input. There are other ways to apply this, but the simplest rule is no mutation.&lt;/p&gt;

&lt;p&gt;If we take the code:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;modify_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;we can see one glaring area of needed maintenance. If &lt;code class=&quot;highlighter-rouge&quot;&gt;modify_string&lt;/code&gt;’s operation should ever change, we need to be absolutely sure that our modifications don’t influence the program’s correctness outside of &lt;code class=&quot;highlighter-rouge&quot;&gt;modify_string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s a potential implementation of &lt;code class=&quot;highlighter-rouge&quot;&gt;modify_string&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;modify_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This implementation overwrites the calling function’s understanding of the data, making this function and the caller very tightly coupled. If I am to call &lt;code class=&quot;highlighter-rouge&quot;&gt;modify_string&lt;/code&gt; from anywhere else in the program, I must be absolutely aware of the preconditions and postconditions of it’s execution, and replicate any setup procedures from the canonical use.&lt;/p&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Code duplication&lt;/li&gt;
  &lt;li&gt;Tight coupling&lt;/li&gt;
  &lt;li&gt;Difficulty optimizing&lt;/li&gt;
  &lt;li&gt;High knowledge overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s tweak this function to make it re-useable&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modify_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;modify_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// input is a copy, so safe&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, to_print never changes. If we need to mutate it, we just assign it back the result of &lt;code class=&quot;highlighter-rouge&quot;&gt;modify_string&lt;/code&gt;. No callers need to know the post-conditions of their inputs because the inputs don’t change. If the function has some precondition incantation that must be run to prepare it’s inputs, we can make an immutable function to do just that, and pass it in directly. Should &lt;code class=&quot;highlighter-rouge&quot;&gt;modify_string&lt;/code&gt; ever change, we are fully safe from the result in all callers and thus our maintenance burden has decreased significantly.&lt;/p&gt;

&lt;p&gt;There are practically no situations where parameter mutation is beneficial for the maintenance overhead it creates. The one situation is memory pressure. Cloning an object over and over can drastically reduce performance, and many immutable-first languages optimize these clone operations out where possible. If you absolutely MUST mutate inside a function, make sure to be aware of the following conditions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Thread safety&lt;/strong&gt; - the mutated parameter must not be shared, and if some property of it is mutated directly, re-factor your code to mutate that portion alone in a thread-safe manner.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Conciseness&lt;/strong&gt; - your mutation should be very small and explicit. Dozens of small mutations is far easier to reason about than one large multi-branch multi-loop recursive operation&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Unique&lt;/strong&gt; - your mutation should be an operation that only happens in this specific call-chain. If it happens in many places, consider a class member that does the mutation for you and hiding the mutated data behind an explicit interface. This reduces the chance of inflicting duplicate code on other callers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Final&lt;/strong&gt; - your mutation should be the last change that happens to this input, and potentially the last action that happens to this input. Callers of your mutating function shouldn’t rely on the function having side-effects or post-conditions on inputs for them to continue operating.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Obviousness&lt;/strong&gt; - many languages support the concept of out-bound parameters, C and C++ with &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;, C# with &lt;code class=&quot;highlighter-rouge&quot;&gt;ref&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;out&lt;/code&gt;. Consider annotating the value as explicitly being an outbound mutation so callers can know to expect it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A strong point to remember is that every function you write is an interface you or someone else will have to deal with in the future, without a cup of coffee, with haranguing managers and impending deadlines, with a hangover, etc. Try to make your functions as trivial to understand and reason about as possible, and try to never make future you spend 3 hours stepping through code with the debugger to figure out what just happend.&lt;/p&gt;
</description>
        <pubDate>Mon, 06 Nov 2017 00:00:00 -0600</pubDate>
        <link>https://parich.us/blog/2017/11/06/system-design-2.html</link>
        <guid isPermaLink="true">https://parich.us/blog/2017/11/06/system-design-2.html</guid>
        
        
        <category>blog</category>
        
      </item>
    
  </channel>
</rss>
