<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Bespoke Bytes</title><link href="https://bespokebytes.com/" rel="alternate"></link><link href="https://bespokebytes.com/feeds/all.atom.xml" rel="self"></link><id>https://bespokebytes.com/</id><updated>2023-08-11T07:53:00-07:00</updated><subtitle>
&lt;webring-swirl site="https://bespokebytes.com/"
     ringlist="https://ring.allknowingtrashheap.art/webring/sitelist.json" theme="low-profile"&gt;
     Make sure the &lt;pre&gt;webring.js&lt;/pre&gt; script is loaded.&lt;/webring-swirl&gt;
    &lt;script type="text/javascript"
    src="https://ring.allknowingtrashheap.art/webring/webring.js"&gt;&lt;/script&gt;
</subtitle><entry><title>Biscuits</title><link href="https://bespokebytes.com/2023/biscuits.html" rel="alternate"></link><published>2023-08-10T22:45:00-07:00</published><updated>2023-08-11T07:53:00-07:00</updated><author><name>dr_a</name></author><id>tag:bespokebytes.com,2023-08-10:/2023/biscuits.html</id><summary type="html">&lt;p class="first last"&gt;Biscuits are happiness&lt;/p&gt;
</summary><content type="html">&lt;div class="section" id="making-biscuits"&gt;
&lt;h2&gt;Making Biscuits&lt;/h2&gt;
&lt;p&gt;Biscuits are one of my favorite things to make, satisfying the urge to work with my hands and providing a reward for the labor at the end.&lt;/p&gt;
&lt;div class="section" id="basic-recipe"&gt;
&lt;h3&gt;Basic Recipe&lt;/h3&gt;
&lt;p&gt;&lt;img alt="Happy biscuits." src="/images/biscuits/regular.jpeg" style="width: 800px;" /&gt;&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;2 C all-purpose flour&lt;/div&gt;
&lt;div class="line"&gt;1 T baking powder&lt;/div&gt;
&lt;div class="line"&gt;2 t brown sugar&lt;/div&gt;
&lt;div class="line"&gt;1/2 t cream of tartar&lt;/div&gt;
&lt;div class="line"&gt;1/4 t salt&lt;/div&gt;
&lt;div class="line"&gt;1/2 C butter&lt;/div&gt;
&lt;div class="line"&gt;2/3 C milk&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;preheat oven  to 450˚F&lt;/li&gt;
&lt;li&gt;mix dry ingredients&lt;/li&gt;
&lt;li&gt;cut in butter to a coarse crumb texture&lt;/li&gt;
&lt;li&gt;mix in milk&lt;/li&gt;
&lt;li&gt;gently work to smooth dough&lt;/li&gt;
&lt;li&gt;flatten to about 1/4 inch thick&lt;/li&gt;
&lt;li&gt;fold and shape to rough rectangle  1/2 inch thick. you can repeat this, but avoid over working the dough&lt;/li&gt;
&lt;li&gt;cut into squares, placing on a baking sheet&lt;/li&gt;
&lt;li&gt;bake until golden brown, about 10-12 minutes&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="variations"&gt;
&lt;h3&gt;Variations&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="section" id="spam-cheese"&gt;
&lt;h3&gt;Spam &amp;amp; Cheese&lt;/h3&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;1 can spam, diced&lt;/div&gt;
&lt;div class="line"&gt;4 oz shredded cheese&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;toss in the spam and cheese before adding the milk&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="sweet-rockets"&gt;
&lt;h3&gt;Sweet Rockets&lt;/h3&gt;
&lt;p&gt;&lt;img alt="Rocket shaped biscuits." src="/images/biscuits/rocket_biscuits.jpeg" style="width: 800px;" /&gt;&lt;/p&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;1 T Butter&lt;/div&gt;
&lt;div class="line"&gt;1/4 C brown sugar&lt;/div&gt;
&lt;div class="line"&gt;1 t cinnamon&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;melt the butter and mix well with the cinnamon and sugar&lt;/li&gt;
&lt;li&gt;before the last fold, spread mixture over half of dough&lt;/li&gt;
&lt;li&gt;rather then cutting into squares, use a rocket shaped cutter&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;!-- Pictures --&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="cooking"></category><category term="art"></category><category term="cooking"></category><category term="biscuits"></category></entry><entry><title>Holiday Cards 2022</title><link href="https://bespokebytes.com/2023/holiday_cards_2022.html" rel="alternate"></link><published>2023-02-26T18:16:00-08:00</published><updated>2023-02-26T18:16:00-08:00</updated><author><name>dr_a</name></author><id>tag:bespokebytes.com,2023-02-26:/2023/holiday_cards_2022.html</id><summary type="html">&lt;p class="first last"&gt;Holiday cards for 2022&lt;/p&gt;
</summary><content type="html">&lt;p&gt;In 2022 I decided to send holiday cards to friends and family. The easy way to do this would have been to go to the store and buy a few boxes of season appropriate cards. This of course makes sense, is inexpensive, and super easy. Of course this didn't happen...&lt;/p&gt;
&lt;div class="section" id="setting-the-scene"&gt;
&lt;h2&gt;Setting the Scene&lt;/h2&gt;
&lt;p&gt;Professionally I spend a lot of time working on projects where there are few tangible outputs, and even fewer where there are visually interesting outputs that I can share with anyone. For these cards I decided that they should be computer generated, and should be visually interesting. Computer generated doesn't really narrow things down, so I decided to merge hobbies and have a robot draw the cards. In this case the robot in question was a CNC engraver that's been modified to serve as a janky pen plotter.&lt;/p&gt;
&lt;p&gt;&lt;img alt="CNC Engraving Machine with a pen holder in place of the spindle." src="/images/holiday_card_2022/cnc_plotter.jpeg" style="width: 800px;" /&gt;&lt;/p&gt;
&lt;p&gt;The spindle of the engraver was swapped out for a pen holder that was made from parts of the world's poorest quality bench grinder.&lt;/p&gt;
&lt;p&gt;On the software front the CNC machine is running &lt;a class="reference external" href="https://github.com/gnea/grbl"&gt;GRBL&lt;/a&gt; and is controlled via &lt;a class="reference external" href="https://github.com/LaserWeb/LaserWeb4"&gt;LaserWeb4&lt;/a&gt; running on a Raspberry Pi.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="coding-the-card"&gt;
&lt;h2&gt;Coding the Card&lt;/h2&gt;
&lt;p&gt;The card needed to capture the holiday spirit, and what better way to do that than have some pointy trees? The trees were generated by identifying points along the base of the tree and the trunk, then drawing a line from one side the base to the trunk and back to the other side of the trunk. &lt;a class="reference external" href="https://numpy.org/"&gt;Numpy&lt;/a&gt; for most of the calculations and &lt;a class="reference external" href="https://matplotlib.org"&gt;Matplotlib&lt;/a&gt; was used to render the card during development.&lt;/p&gt;
&lt;p&gt;The tree is fairly simple, generating a pleasing design:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;string_art&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="n"&gt;n_steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="n"&gt;base_x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]]]:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Construct a string art tree.&lt;/span&gt;

&lt;span class="sd"&gt;    The height of the tree is measured from the top of the trunk, with the&lt;/span&gt;
&lt;span class="sd"&gt;    trunk extending 0.1 * height below the tree.&lt;/span&gt;

&lt;span class="sd"&gt;    The output is a two-element tuple with the first element containing a&lt;/span&gt;
&lt;span class="sd"&gt;    list of lists of the x positions for the drawing segments. The second&lt;/span&gt;
&lt;span class="sd"&gt;    element is the positions.&lt;/span&gt;

&lt;span class="sd"&gt;    :param width: The width of the tree in millimeters&lt;/span&gt;
&lt;span class="sd"&gt;    :param height: The height of the tree in millimeters above the trunk.&lt;/span&gt;
&lt;span class="sd"&gt;    :param n_steps: The number of lines making up the tree.&lt;/span&gt;
&lt;span class="sd"&gt;    :param base_x: The x location of the tree&amp;#39;s origin.&lt;/span&gt;
&lt;span class="sd"&gt;    :param base_y: The y location of the tree&amp;#39;s origin.&lt;/span&gt;
&lt;span class="sd"&gt;    :param rotation: The rotation of the tree in radians.&lt;/span&gt;
&lt;span class="sd"&gt;    :return: The line segments representing the tree.&lt;/span&gt;

&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;segments_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;segments_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;thetas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;n_steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Construct the base tree lines&lt;/span&gt;
    &lt;span class="c1"&gt;# The drawing alternates direction. This reduces motion in the final drawing.&lt;/span&gt;
    &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;theta&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;thetas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;even&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;segments_x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;segments_x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
        &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;even&lt;/span&gt;
        &lt;span class="n"&gt;segments_y&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;# The Trunk&lt;/span&gt;
    &lt;span class="n"&gt;trunk_depth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;
    &lt;span class="n"&gt;trunk_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
    &lt;span class="n"&gt;segments_x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trunk_width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trunk_width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trunk_width&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;segments_y&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trunk_depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trunk_depth&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;segments_x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;trunk_width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trunk_width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trunk_width&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;segments_y&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;trunk_depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;transform_strokes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;segments_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;segments_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="n"&gt;base_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;base_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;base_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Feeding the tree generator a range of values for &lt;code&gt;n_steps&lt;/code&gt; makes a family of trees.&lt;/p&gt;
&lt;p&gt;&lt;img alt="String art trees drawn with 3, 6, 9, 12, 15, 18, 21, 24, and 27 segments." src="/images/holiday_card_2022/tree_samples.png" style="width: 800px;" /&gt;&lt;/p&gt;
&lt;p&gt;The other big element required for a card is words. In this case we can take a look at the history of technology, and we'll come across Hershey Fonts described in &lt;a class="reference external" href="https://archive.org/details/DTIC_AD0662398"&gt;DTIC AD0662398: CALLIGRAPHY FOR COMPUTERS&lt;/a&gt; by  Dr. Allen Vincent Hershey. While the Hershey fonts were originally aimed at vector cathode ray tube displays, they're well-suited for other vector display technologies. Since the plotter draws straight line segments it's really just a vector display so we can use these fonts.&lt;/p&gt;
&lt;p&gt;Putting the string art and fonts together we can start to compose a card. The planned card is 114 millimeters wide by 152 millimeters tall, since that fits nicely into a 4x6 inch envelope. The code that generates the outside of the card is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_outside_of_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script_font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_font&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# pylint: disable=too-many-locals&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="sd"&gt;    Generate the outside of the card.&lt;/span&gt;
&lt;span class="sd"&gt;    :param script_font: The font definition for the script font&lt;/span&gt;
&lt;span class="sd"&gt;    :param block_font: The font definition for the block font.&lt;/span&gt;
&lt;span class="sd"&gt;    :return: The segments that define the card&lt;/span&gt;
&lt;span class="sd"&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;x_segments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;y_segments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="c1"&gt;# Front&lt;/span&gt;
    &lt;span class="n"&gt;trees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;171&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;# width, height,n_lines, base_x, base_y&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trees&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tree_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tree_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string_art&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree_x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;y_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;construct_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Happy Holidays&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script_font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;171&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;y_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;construct_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;202012&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script_font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x_bbox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_bbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;construct_letter_bboxes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;202012&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script_font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cross_out&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;x_squiggle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_squiggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cross_out_bbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_bbox&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cross_out&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;y_bbox&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cross_out&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;cycles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_squiggle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;y_message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_squiggle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;171&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;y_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Back&lt;/span&gt;
    &lt;span class="n"&gt;x_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;construct_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;github.com/palbee/holiday_card_2022&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deg2rad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;x_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;y_segments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x_segments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_segments&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The actual code is fairly direct, with an attempt to make the code reasonably conversational. The card outside was rendered using MatPlotLib to make sure the design was within bounds. Note that the front and back of the card are plotted together.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Outside of plotted holiday card." src="/images/holiday_card_2022/holiday_card_outside.png" style="width: 800px;" /&gt;&lt;/p&gt;
&lt;p&gt;The inside of the card was constructed in a similar manner, and is shown below.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Inside of plotted holiday card." src="/images/holiday_card_2022/holiday_card_inside.png" style="width: 800px;" /&gt;&lt;/p&gt;
&lt;p&gt;After the card designs were finalized they needed to be plotted. This was done by converting the line segments to gcode and sending them off to the plotter. The gcode for a small portion of the outside of the card is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;221.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-16.25&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;171.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;121.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;121.03185871715041&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-16.25&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;171.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;49.21231004550824&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;220.9681412828496&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;220.87260573051267&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-16.25&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;171.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;52.420526487930914&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;121.12739426948733&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;121.28648491140513&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-16.25&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;171.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;55.62056094086015&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;220.71351508859487&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;220.49107209404664&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-16.25&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;171.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;58.80833544459566&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G1 &lt;/span&gt;&lt;span class="k"&gt;X&lt;/span&gt;&lt;span class="m"&gt;121.50892790595336&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Y&lt;/span&gt;&lt;span class="m"&gt;46.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;F&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
&lt;span class="nb"&gt;G0 &lt;/span&gt;&lt;span class="k"&gt;Z&lt;/span&gt;&lt;span class="m"&gt;-14.5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code above draws a total of 14 line segments, and takes about 12 minutes to complete the outside of the card. The inside of the card takes an additional 14 minutes, in part because the row of trees is fairly detailed. The text also adds significant complexity and time to the drawing.&lt;/p&gt;
&lt;p&gt;Once all the cards were drawn, it was time to send them. This required addressing envelopes, and since plotting is so much fun the envelopes were also plotted. The envelopes took an additional 18 minuted each to plot on average, due mostly to plotting text being time consuming.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Plotted envelope" src="/images/holiday_card_2022/envelope.png" style="width: 800px;" /&gt;&lt;/p&gt;
&lt;p&gt;All of the code for this project is available on &lt;a class="reference external" href="https://github.com/palbee/holiday_card_2022/"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;!-- Pictures --&gt;
&lt;/div&gt;
</content><category term="art-ish"></category><category term="art"></category><category term="cards"></category></entry><entry><title>Adventures in Logging</title><link href="https://bespokebytes.com/2017/adventures_in_logging_pt_1.html" rel="alternate"></link><published>2017-11-19T22:17:45-08:00</published><updated>2017-11-19T22:17:45-08:00</updated><author><name>dr_a</name></author><id>tag:bespokebytes.com,2017-11-19:/2017/adventures_in_logging_pt_1.html</id><summary type="html">&lt;p&gt;This post is the first in a series on using the logging facilities in Python. Logging is an incredibly powerful tool for developers during early system development, and also during deployment.&lt;/p&gt;
&lt;p&gt;One of the interesting features of the logging package is an &lt;a class="reference external" href="https://docs.python.org/3.10/howto/logging.html#optimization"&gt;optimization&lt;/a&gt; where rendering of the log message is …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This post is the first in a series on using the logging facilities in Python. Logging is an incredibly powerful tool for developers during early system development, and also during deployment.&lt;/p&gt;
&lt;p&gt;One of the interesting features of the logging package is an &lt;a class="reference external" href="https://docs.python.org/3.10/howto/logging.html#optimization"&gt;optimization&lt;/a&gt; where rendering of the log message is delayed as long as possible. What's not obvious is how this optimization will impact execution time.&lt;/p&gt;
&lt;p&gt;In order to understand the consequences of how we construct the arguments to a call to a logger, we're going to run three experiments. The first experiment will explore logging performance with a single logger, the second will use two loggers, and the third will use three loggers.&lt;/p&gt;
&lt;div class="section" id="logging-configuration"&gt;
&lt;h2&gt;Logging Configuration&lt;/h2&gt;
&lt;p&gt;In order to study only the effect of the arguments on logging performance, we use a custom &lt;code&gt;logging.Handler&lt;/code&gt; subclass that performs no I/O, but does go through the motions of preparing the text for a log message.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;
&lt;span class="normal"&gt;7&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FormattingNullHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Custom logging.Handler for performance measurements.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Ensure that the record is formatted, but avoid doing I/O. This&lt;/span&gt;
&lt;span class="sd"&gt;            ensures that our expensive argument processing always occurs.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
            &lt;span class="n"&gt;ignored_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Logging was configured as follows for the single handler experiment:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;    &lt;span class="c1"&gt;# Configure logging&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;    &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_srcfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# Disable file lookup.&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logThreads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Disable logging thread information&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logProcesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Disable logging process information&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logMultiprocessing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Disable logging multiprocess information&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;    &lt;span class="c1"&gt;# Configure a single log handler with a minimalist formatter.&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;    &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FormattingNullHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;    &lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;    &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="experimental-code"&gt;
&lt;h2&gt;Experimental Code&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="linenos"&gt; 1&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exercise_driver&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="linenos"&gt; 2&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Exercise the logging system, with different reporting levels.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="linenos"&gt; 3&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="linenos"&gt; 4&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;log_level&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LOGGING_LEVELS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt; 5&lt;/span&gt;            &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLevelName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt; 6&lt;/span&gt;            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt; 7&lt;/span&gt;            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exercise_log&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="linenos"&gt; 8&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;span class="linenos"&gt; 9&lt;/span&gt;
&lt;span class="linenos"&gt;10&lt;/span&gt;
&lt;span class="linenos"&gt;11&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exercise_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iteration_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expensive_iterations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2500000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="linenos"&gt;12&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Run the experiment with a logger that has been externally configured.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="linenos"&gt;13&lt;/span&gt;        &lt;span class="n"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Timer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="linenos"&gt;14&lt;/span&gt;        &lt;span class="n"&gt;running_total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="linenos"&gt;15&lt;/span&gt;        &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="linenos"&gt;16&lt;/span&gt;        &lt;span class="n"&gt;expensive_operation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ExpensiveCounter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expensive_iterations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;expensive_iterations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt;17&lt;/span&gt;
&lt;span class="linenos"&gt;18&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iteration_limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;19&lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expensive_operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;20&lt;/span&gt;                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LOGGING_LEVELS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;21&lt;/span&gt;                    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expensive_operation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="linenos"&gt;22&lt;/span&gt;            &lt;span class="n"&gt;running_total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="linenos"&gt;23&lt;/span&gt;            &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="linenos"&gt;24&lt;/span&gt;
&lt;span class="linenos"&gt;25&lt;/span&gt;        &lt;span class="n"&gt;object_counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expensive_operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="linenos"&gt;26&lt;/span&gt;        &lt;span class="n"&gt;object_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;running_total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;iteration_limit&lt;/span&gt;
&lt;span class="linenos"&gt;27&lt;/span&gt;
&lt;span class="linenos"&gt;28&lt;/span&gt;        &lt;span class="n"&gt;running_total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="linenos"&gt;29&lt;/span&gt;        &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="linenos"&gt;30&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;iteration_limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;31&lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expensive_operation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;32&lt;/span&gt;                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LOGGING_LEVELS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="linenos"&gt;33&lt;/span&gt;                    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expensive_operation&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="linenos"&gt;34&lt;/span&gt;            &lt;span class="n"&gt;running_total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="linenos"&gt;35&lt;/span&gt;            &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="linenos"&gt;36&lt;/span&gt;
&lt;span class="linenos"&gt;37&lt;/span&gt;        &lt;span class="n"&gt;invoked_counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;expensive_operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="linenos"&gt;38&lt;/span&gt;        &lt;span class="n"&gt;invoked_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;running_total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;iteration_limit&lt;/span&gt;
&lt;span class="linenos"&gt;39&lt;/span&gt;
&lt;span class="linenos"&gt;40&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;invoked_count&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;invoked_counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;41&lt;/span&gt;                &lt;span class="s1"&gt;&amp;#39;invoked_time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;invoked_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;42&lt;/span&gt;                &lt;span class="s1"&gt;&amp;#39;obj_count&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;object_counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="linenos"&gt;43&lt;/span&gt;                &lt;span class="s1"&gt;&amp;#39;obj_time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;object_time&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The experimental code makes 2 logging calls in &lt;code&gt;exercise_log&lt;/code&gt;. The first call, on line 21, passes an &lt;code&gt;expensive_operation&lt;/code&gt; object reference as an argument to the logging call, while the second call, on line 33, invokes the &lt;code&gt;expensive_operation&lt;/code&gt; object, passing the result to the logging call. In both cases the logging call is made for each of the standard log levels. The &lt;code&gt;exercise_log&lt;/code&gt; function is called for each of the standard log levels. The &lt;code&gt;expensive_operation&lt;/code&gt; object is just a while loop that counts from 0 to &lt;code&gt;expensive_iterations&lt;/code&gt; by 1s when it is invoked or converted to a string.&lt;/p&gt;
&lt;div class="section" id="tests"&gt;
&lt;h3&gt;Tests&lt;/h3&gt;
&lt;p&gt;The initial test uses one log handler and has the following results:&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;caption&gt;Execution times in seconds for logging when passing an object vs a method invocation as log message parameter to a single logger with one handler.&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col width="24%" /&gt;
&lt;col width="16%" /&gt;
&lt;col width="19%" /&gt;
&lt;col width="22%" /&gt;
&lt;col width="19%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Level Filter&lt;/th&gt;
&lt;th class="head"&gt;Obj Ref&lt;/th&gt;
&lt;th class="head"&gt;Avg. Time&lt;/th&gt;
&lt;th class="head"&gt;Method Call&lt;/th&gt;
&lt;th class="head"&gt;Avg. Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;CRITICAL&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0.0434&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2182&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;ERROR&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0.0861&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2177&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;WARNING&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0.1294&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2177&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;INFO&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0.1724&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2179&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DEBUG&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2427&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2450&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The first item of note is the Obj Ref column, which is the count of the number of times the object was converted to a string. In keeping with the behavior that message formatting is deferred as long as possible, we see that the string conversion only happened when the message would be rendered under the logging level configuration. When we passed the result of invoking the object, we performed the expensive operation every time, resulting in longer execution times.&lt;/p&gt;
&lt;p&gt;The second test uses two handlers associated with a single logger and had the following results:&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;caption&gt;Execution times seconds for logging when passing an object vs a method invocation as log message parameter to a single logger with two handlers.&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col width="24%" /&gt;
&lt;col width="16%" /&gt;
&lt;col width="19%" /&gt;
&lt;col width="22%" /&gt;
&lt;col width="19%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Level Filter&lt;/th&gt;
&lt;th class="head"&gt;Obj Ref&lt;/th&gt;
&lt;th class="head"&gt;Avg. Time&lt;/th&gt;
&lt;th class="head"&gt;Method Call&lt;/th&gt;
&lt;th class="head"&gt;Avg. Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;CRITICAL&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0.0864&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2175&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;ERROR&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0.1732&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2188&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;WARNING&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;0.2600&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2202&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;INFO&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;0.3466&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2186&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DEBUG&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;0.4310&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2181&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The third test uses three handlers associated with a single logger and had the following results:&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;caption&gt;Execution times in seconds for logging when passing an object vs a method invocation as log message parameter to a single logger with three handlers.&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col width="24%" /&gt;
&lt;col width="16%" /&gt;
&lt;col width="19%" /&gt;
&lt;col width="22%" /&gt;
&lt;col width="19%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Level Filter&lt;/th&gt;
&lt;th class="head"&gt;Obj Ref&lt;/th&gt;
&lt;th class="head"&gt;Avg. Time&lt;/th&gt;
&lt;th class="head"&gt;Method Call&lt;/th&gt;
&lt;th class="head"&gt;Avg. Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;CRITICAL&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0.1295&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2174&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;ERROR&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;0.2595&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2174&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;WARNING&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;0.3890&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2174&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;INFO&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;0.5198&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2180&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DEBUG&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;0.6494&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.2183&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Looking at the second and third tests we see that the number of times we convert an object to a string increases with the number of handlers. The initial test might have given the impression that object references are better, but we can see that the situation is more complicated.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="discussion"&gt;
&lt;h3&gt;Discussion&lt;/h3&gt;
&lt;p&gt;As we can see from the test results, minimizing the amount of time we spend in logging calls is not simple. We need to be mindful of the number of handlers, the logging level, and the cost of preparing the arguments for the logger. In general it will be better to have the arguments created once for a logging call, avoiding the need to perform expensive operations for each handler.&lt;/p&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://docs.python.org/3.10/howto/logging.html"&gt;logging cookbook&lt;/a&gt; recommends using the &lt;code&gt;logger.isEnabledFor(level)&lt;/code&gt; function to decide if a logging call should be made. This practice is unsatisfying as it encourages the use of expensive functions as arguments to logging calls. A better option would be to refactor your code so that the generation of arguments for logging calls is inexpensive, using the &lt;code&gt;logger.isEnabledFor(level)&lt;/code&gt; method only when inexpensive arguments cannot be used.&lt;/p&gt;
&lt;p&gt;An important caveat for logging calls, regardless of how computational expense is managed, is that they should not alter system state. If it is necessary to alter system state via functions that generate input for logging arguments, then those functions should be idempotent.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="tech-musings"></category></entry><entry><title>What Flow Control?</title><link href="https://bespokebytes.com/2016/what_flow_control.html" rel="alternate"></link><published>2016-09-29T14:44:12-07:00</published><updated>2016-09-29T14:44:12-07:00</updated><author><name>dr_a</name></author><id>tag:bespokebytes.com,2016-09-29:/2016/what_flow_control.html</id><summary type="html">&lt;div class="section" id="the-assert-macro-is-not-a-flow-control-mechanism"&gt;
&lt;h2&gt;The &lt;code&gt;assert()&lt;/code&gt; macro is not a flow control mechanism&lt;/h2&gt;
&lt;p&gt;An interesting &lt;a class="reference external" href="https://www.agwa.name/blog/post/how_to_crash_systemd_in_one_tweet"&gt;vulnerability&lt;/a&gt; in &lt;a class="reference external" href="http://www.freedesktop.org/wiki/Software/systemd/"&gt;systemd&lt;/a&gt; appears to be a consequence of using the assert() macro as a flow control construct. In the &lt;a class="reference external" href="https://github.com/systemd/systemd/blob/b8fafaf4a1cffd02389d61ed92ca7acb1b8c739c/src/core/manager.c#L1660-L1678"&gt;code&lt;/a&gt; the authors had the following function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12 …&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="section" id="the-assert-macro-is-not-a-flow-control-mechanism"&gt;
&lt;h2&gt;The &lt;code&gt;assert()&lt;/code&gt; macro is not a flow control mechanism&lt;/h2&gt;
&lt;p&gt;An interesting &lt;a class="reference external" href="https://www.agwa.name/blog/post/how_to_crash_systemd_in_one_tweet"&gt;vulnerability&lt;/a&gt; in &lt;a class="reference external" href="http://www.freedesktop.org/wiki/Software/systemd/"&gt;systemd&lt;/a&gt; appears to be a consequence of using the assert() macro as a flow control construct. In the &lt;a class="reference external" href="https://github.com/systemd/systemd/blob/b8fafaf4a1cffd02389d61ed92ca7acb1b8c739c/src/core/manager.c#L1660-L1678"&gt;code&lt;/a&gt; the authors had the following function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cm"&gt;/* Extract from systemd/src/core/manager.c */&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;manager_invoke_notify_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;pid_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FDSet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_cleanup_strv_free_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strv_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n\r&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;log_oom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UNIT_VTABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;notify_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;UNIT_VTABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;notify_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;log_unit_debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Got notification message for unit. Ignoring.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;In line 8 of the snippet there is an assertion to check if &lt;code&gt;n &amp;gt; 0&lt;/code&gt;, in this case &lt;code&gt;n&lt;/code&gt; is the size of a buffer. Since a buffer of size 0 causes systemd to crash on some systems, this is a good check. There are however two serious problems with the code as written:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;If systemd is compiled with the &lt;code&gt;-DNDEBUG&lt;/code&gt; compiler flag, then the &lt;code&gt;assert()&lt;/code&gt; macro will not generate any code so the check doesn't happen.&lt;/li&gt;
&lt;li&gt;If systemd is compiled without the &lt;code&gt;-DNDEBUG&amp;lt;/span&amp;gt;&lt;/code&gt; flag, then if the assertion fails the program will abort.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For a critical software component, both problems are undesirable. The core of the problem appears to be the use of the &lt;code&gt;assert()&lt;/code&gt; macro as a flow control mechanism. If it critically important for the value of &lt;code&gt;n&lt;/code&gt; to be checked, then use a real comparison with explicit error handling. An additional item of concern is the use of &lt;code&gt;assert()&lt;/code&gt; macros where there is an implicit assumption that &lt;code&gt;NULL == 0&lt;/code&gt; in lines 5 - 7. At a minimum, comparisons of a pointer to &lt;code&gt;NULL&lt;/code&gt; should be done explicitly.&lt;/p&gt;
&lt;p&gt;Assuming that the conditions implied by the &lt;code&gt;assert()&lt;/code&gt; macro usage is correct, the code should be rewritten as:&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;
&lt;span class="normal"&gt;24&lt;/span&gt;
&lt;span class="normal"&gt;25&lt;/span&gt;
&lt;span class="normal"&gt;26&lt;/span&gt;
&lt;span class="normal"&gt;27&lt;/span&gt;
&lt;span class="normal"&gt;28&lt;/span&gt;
&lt;span class="normal"&gt;29&lt;/span&gt;
&lt;span class="normal"&gt;30&lt;/span&gt;
&lt;span class="normal"&gt;31&lt;/span&gt;
&lt;span class="normal"&gt;32&lt;/span&gt;
&lt;span class="normal"&gt;33&lt;/span&gt;
&lt;span class="normal"&gt;34&lt;/span&gt;
&lt;span class="normal"&gt;35&lt;/span&gt;
&lt;span class="normal"&gt;36&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cm"&gt;/* Revised code. */&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;manager_invoke_notify_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Unit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;pid_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FDSet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_cleanup_strv_free_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// log as appropriate&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// log as appropriate&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// log as appropriate&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// log as appropriate&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strv_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n\r&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;log_oom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UNIT_VTABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;notify_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;UNIT_VTABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;notify_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;log_unit_debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Got notification message for unit. Ignoring.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;In keeping with good practice, this code will check important conditions regardless of the presence of the &lt;code&gt;-DNDEBUG&lt;/code&gt; compiler flag. Additionally, in keeping with the C11 standard &lt;a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf"&gt;ISO/IEC 9899:201x&lt;/a&gt; &lt;code&gt;NULL&lt;/code&gt; is not assumed to be a zero of any type.&lt;/p&gt;
&lt;/div&gt;
</content><category term="tech-musings"></category></entry><entry><title>Living with Exceptions</title><link href="https://bespokebytes.com/2014/exception_handling_patterns.html" rel="alternate"></link><published>2014-05-11T21:39:17-07:00</published><updated>2014-05-11T21:39:17-07:00</updated><author><name>dr_a</name></author><id>tag:bespokebytes.com,2014-05-11:/2014/exception_handling_patterns.html</id><summary type="html">&lt;p&gt;In Java, exceptions occur when some non-planned issue
occurs that interrupts the normal flow of execution. Exception handling is
accomplished in one of two general ways. The first is to simply allow the
exception to propagate up the call stack. This is accomplished by adding the
throws keyword and a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In Java, exceptions occur when some non-planned issue
occurs that interrupts the normal flow of execution. Exception handling is
accomplished in one of two general ways. The first is to simply allow the
exception to propagate up the call stack. This is accomplished by adding the
throws keyword and a list of exception types to the method declaration. The
second approach is to execute code that may throw an exception inside of a
try block. Immediately following the try block will be one or more catch
blocks that catch the different exception types that may occur in the
preceding try block. The catch block(s) may be followed by a finally block
that is used for cleanup.&lt;/p&gt;
&lt;p&gt;In the code sample below, an exception is raised at line 3 triggering a change in the expected flow
of control in the program. Since the exception in &lt;code&gt;some_method()&lt;/code&gt; was not in a try block, control
transfers back to &lt;code&gt;a_method()&lt;/code&gt;, which was invoked at line 8. In a normal (non-exceptional) situation
the program would advance to line 9. Since the exception is in a try block, execution will transfer
to the associated catch block to handle the exception. In the catch block the exception may be
handled, ignored, or re-thrown. Note that at line 12 there is a return statement. If this code was
not being executed as part of exception handling, control would return to the &lt;code&gt;main()&lt;/code&gt; method. However,
since this code is part of exception handling and there is a finally block, the code at line 15 will
be executed before the return takes effect. If line 12 was a &lt;code&gt;System.exit()&lt;/code&gt; invocation, the finally
block would still be executed prior to the exit occurring.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExceptionHandling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;some_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;throws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Manually Thrown Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;a_method&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Before Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;some_method&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;After Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Handling Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Entered Finally&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Calling Method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;a_method&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Returned From Method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Note in the output below that &lt;tt class="docutils literal"&gt;After Exception&lt;/tt&gt; is never printed. Once an exception has occurred,
the execution in the try block is done.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Calling Method
Before Exception
Handling Exception &amp;quot;Manually Thrown Exception&amp;quot;
Entered Finally
Returned From Method
&lt;/pre&gt;
&lt;p&gt;A common pattern of execution is to handle the exception, and then continue execution after the
try-catch-finally construct as shown below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;
&lt;span class="normal"&gt;22&lt;/span&gt;
&lt;span class="normal"&gt;23&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExceptionHandlingRecover&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;some_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;throws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Manually Thrown Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;a_method&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Before Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;some_method&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;After Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Handling Exception&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Entered Finally&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Continuing After try-catch-finally&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Calling Method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;a_method&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Returned From Method&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;pre class="literal-block"&gt;
Calling Method
Before Exception
Handling Exception
Entered Finally
Continuing After try-catch-finally
Returned From Method
&lt;/pre&gt;
&lt;p&gt;This is potentially dangerous since the execution context may not be what you expect, especially if
more than one exception is possible in try block.&lt;/p&gt;
&lt;div class="section" id="exception-handling-strategies"&gt;
&lt;h2&gt;Exception Handling Strategies&lt;/h2&gt;
&lt;p&gt;There are three basic strategies for managing exceptions. The first strategy is to ignore them, the
second is to address them, and the third is to make them someone else's problem. Each strategy has
some benefits and costs, and it is the responsibility of the developer to choose the correct
strategy.&lt;/p&gt;
&lt;div class="section" id="ignoring-exceptions"&gt;
&lt;h3&gt;Ignoring Exceptions&lt;/h3&gt;
&lt;p&gt;Simply ignoring the exception by having a catch block that does not change program state is a
tempting strategy that is unfortunately supported by many IDEs via code generation wizards.
A common form of ignoring exceptions is shown below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;some_exception_causing_method&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class="section" id="cost"&gt;
&lt;h4&gt;Cost&lt;/h4&gt;
&lt;p&gt;Ignoring exceptions is tempting since you can simply continue along as if nothing happened. In the
code sample a stack trace would be printed to the error console, but there is no guarantee that
anyone would ever see it. An exception may be an indication that system state is such that the
program cannot continue execution producing good results. Failure to appropriately address an
exception may result in undefined behavior that is extremely difficult to diagnose and correct since
the diagnostic information is only available in the error console. In some execution environments
that output is not preserved, rendering it useless for debugging.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="benefit"&gt;
&lt;h4&gt;Benefit&lt;/h4&gt;
&lt;p&gt;There may be cases where an exception simply does not matter, and may be safely ignored. This is
rare since exceptions are an indication that something is not working as expected. If an exception
is ignored, it is crucial to document why the exception was ignored.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="caveats"&gt;
&lt;h4&gt;Caveats&lt;/h4&gt;
&lt;p&gt;A common pattern for reading files is to use an infinite loop to read the file, relying on catching
an &lt;cite&gt;IOException&lt;/cite&gt; when the end of file is reached to exit the loop. While this works, it is extremely
poor practice. Reaching the end of a file is not the only reason an IOException could be thrown.
Additionally, using the exception handling mechanism to break loops can make tracing code execution
difficult.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="addressing-exceptions"&gt;
&lt;h3&gt;Addressing Exceptions&lt;/h3&gt;
&lt;p&gt;For applications, addressing exceptions is the common strategy. Addressing an exception may take the
form of recovering from the exceptional situation, or it may be alerting the user that there is a
problem and terminating the program.&lt;/p&gt;
&lt;div class="section" id="costs"&gt;
&lt;h4&gt;Costs&lt;/h4&gt;
&lt;p&gt;Addressing an exception by recovering may be challenging to the point of being impractical.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="benefits"&gt;
&lt;h4&gt;Benefits&lt;/h4&gt;
&lt;p&gt;If you are able to recover from an exception then the program does not need to terminate, thus
leading to a better user experience. In the case where recovery is not possible, capturing the
problem early and terminating may make debugging easier and also reduce the likelihood of data
corruption and spurious program behavior.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="caveats-1"&gt;
&lt;h4&gt;Caveats&lt;/h4&gt;
&lt;p&gt;While it is tempting to recover from exceptions, this is often not advisable. Unless the execution
context's validity is independent of the exception or can be repaired despite the exception, it may
be the case that the program cannot correctly execute after an exception. Continuing execution is a
good goal, but should only be attempted in cases when terminating the program is not an option or
the exception does not lead to an invalid program state.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="making-exceptions-someone-else-s-problem"&gt;
&lt;h3&gt;Making Exceptions Someone Else's Problem&lt;/h3&gt;
&lt;p&gt;For the developers of libraries and web services, this is often the correct strategy. An exception
may arise because of invalid input provided to a library function. It is inappropriate for a library
to attempt to correct an exception, but should instead indicate that an exception has occurred. In
the case of web services, exceptions may arise as a consequence of corrupted web requests. A viable
strategy for web services is to raise an exception to inform the web service container that there
was a problem and let the container alert the client in an appropriate manner.&lt;/p&gt;
&lt;div class="section" id="costs-1"&gt;
&lt;h4&gt;Costs&lt;/h4&gt;
&lt;p&gt;When throwing exceptions it is crucial that the exceptions be meaningful and provide diagnostic
information back to the calling methods so they can deal with the exception correctly.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="benefits-1"&gt;
&lt;h4&gt;Benefits&lt;/h4&gt;
&lt;p&gt;By making the exceptions the problem of the caller, the code raising the exceptions can be simpler
and focus on operating on correct inputs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="caveats-2"&gt;
&lt;h4&gt;Caveats&lt;/h4&gt;
&lt;p&gt;As with any time you cause problems for somebody else, be sure that is an appropriate action.
Additionally, when you are writing an application, simply re-throwing exceptions will likely result
in the application crashing. In Java (and other languages with exceptions) any exceptions that are
not caught by the application will be caught by the runtime environment and may result in
application termination without any cleanup.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusions"&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Exception handling introduces a mechanism for altering the flow-of-control when issues arise during
program execution. The proper response to exceptions depends on the context in which the exception
occurs. Regardless of the context exceptions should be dealt with deliberately ensuring that they
are not simply ignored.&lt;/p&gt;
&lt;p&gt;Many other languages have similar exception methods. While the syntax varies, the issues are largely the same.&lt;/p&gt;
&lt;/div&gt;
</content><category term="tech-musings"></category></entry></feed>