<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Binary Thoughts</title><link>https://riaan.hanekom.io/</link><description>Recent content on Binary Thoughts</description><generator>Hugo 0.154.5</generator><language>en</language><atom:link href="https://riaan.hanekom.io/index.xml" rel="self" type="application/rss+xml"/><item><title>The Magpie</title><link>https://riaan.hanekom.io/2018/04/14/the-magpie/</link><pubDate>Sat, 14 Apr 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/04/14/the-magpie/</guid><description>&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I split this post into two to make it more digestible. For background and context, see my post &lt;a href="https://riaan.hanekom.io/2018/03/27/shiny-things/"&gt;Shiny things&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="tl-dr" class="heading-anchor"&gt;TL; DR&lt;a href="#tl-dr" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#what-is-a-magpie"&gt;Background and definition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#an-old-wives-tale"&gt;The Magpie is misunderstood and provides a &lt;strong&gt;good model for learning&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-v-model-of-learning"&gt;The &lt;strong&gt;V model of learning&lt;/strong&gt; (contrasted to the model of T-shaped people) attempts to &lt;strong&gt;maximise intersection points&lt;/strong&gt; in knowledge to enable fast learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#build-a-solid-core"&gt;It&amp;rsquo;s vital to build a &lt;strong&gt;solid core&lt;/strong&gt; to enable the transfer of skills from one domain to another&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#intentional-learning"&gt;&lt;strong&gt;Haphazard&lt;/strong&gt; learning achieves little - &lt;strong&gt;intentional&lt;/strong&gt; learning is key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#in-conclusion"&gt;Practice &lt;strong&gt;learning, unlearning, and connecting ideas&lt;/strong&gt;. Look for intersection points and &lt;strong&gt;know what you &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; know&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr/&gt;
&lt;p&gt;Back in 2008 Jeff Atwood wrote &lt;a href="https://blog.codinghorror.com/the-magpie-developer/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;a popular blog post&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; speaking about the fast pace of change in technologies, and a specific class of developers attracted to new technologies, sometimes to their detriment. If you have not read it yet &lt;a href="https://blog.codinghorror.com/the-magpie-developer/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;do so now&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. It contains some gems.&lt;/p&gt;</description><content:encoded>&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I split this post into two to make it more digestible. For background and context, see my post &lt;a href="https://riaan.hanekom.io/2018/03/27/shiny-things/"&gt;Shiny things&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="tl-dr" class="heading-anchor"&gt;TL; DR&lt;a href="#tl-dr" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#what-is-a-magpie"&gt;Background and definition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#an-old-wives-tale"&gt;The Magpie is misunderstood and provides a &lt;strong&gt;good model for learning&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-v-model-of-learning"&gt;The &lt;strong&gt;V model of learning&lt;/strong&gt; (contrasted to the model of T-shaped people) attempts to &lt;strong&gt;maximise intersection points&lt;/strong&gt; in knowledge to enable fast learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#build-a-solid-core"&gt;It&amp;rsquo;s vital to build a &lt;strong&gt;solid core&lt;/strong&gt; to enable the transfer of skills from one domain to another&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#intentional-learning"&gt;&lt;strong&gt;Haphazard&lt;/strong&gt; learning achieves little - &lt;strong&gt;intentional&lt;/strong&gt; learning is key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#in-conclusion"&gt;Practice &lt;strong&gt;learning, unlearning, and connecting ideas&lt;/strong&gt;. Look for intersection points and &lt;strong&gt;know what you &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; know&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr/&gt;
&lt;p&gt;Back in 2008 Jeff Atwood wrote &lt;a href="https://blog.codinghorror.com/the-magpie-developer/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;a popular blog post&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; speaking about the fast pace of change in technologies, and a specific class of developers attracted to new technologies, sometimes to their detriment. If you have not read it yet &lt;a href="https://blog.codinghorror.com/the-magpie-developer/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;do so now&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. It contains some gems.&lt;/p&gt;
&lt;p&gt;If you read the comments on that post it seems like some people took away the idea that sticking with what is familiar is the right thing to do. The Magpie developer got a bad rap and the analogy is incomplete. It ignores the benefits this pattern has for learning if used responsibly. In this post we will take a deeper look at that definition. I will attempt to describe my (personal) mental model of approaching continuous learning. We all have models on how the world (and our brains) work. Knowing that &lt;a href="https://en.wikipedia.org/wiki/All_models_are_wrong" target="_blank" rel="noopener noreferrer" class="external-link"&gt;all models are wrong but some are useful&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; I will proceed with caution on this topic. This is &lt;em&gt;but one&lt;/em&gt; of &lt;em&gt;my&lt;/em&gt; mental models but &lt;em&gt;might&lt;/em&gt; be useful in &lt;em&gt;shaping&lt;/em&gt; your thinking.&lt;/p&gt;
&lt;h2 id="what-is-a-magpie" class="heading-anchor"&gt;What is a Magpie?&lt;a href="#what-is-a-magpie" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Someone who hangs at the train station or bus stop or anywhere public all day long, usually asking for a cigarette, spare change or pocket lint. Usually unemployed and unemployable, using nothing but slang, and usually impossible to get rid of, until threatened with violence.&lt;/p&gt;
&lt;p&gt;Called magpies because if they have gotten it once, they&amp;rsquo;ll expect it again, and again, regardless of who it is.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Oh wait. Not &lt;a href="https://www.urbandictionary.com/define.php?term=Magpie" target="_blank" rel="noopener noreferrer" class="external-link"&gt;that kind of Magpie&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let us have a look at &lt;a href="https://blog.codinghorror.com/the-magpie-developer/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Jeff&amp;rsquo;s definition&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve often thought that software developers were akin to &lt;a href="http://en.wikipedia.org/wiki/Magpie" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Magpies&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, birds notorious for stealing shiny items to decorate their complex nests. Like Magpies, software developers are unusually smart and curious creatures, almost by definition. But we are too easily distracted by shiny new toys and playthings.&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;I became a programmer because I love computers, and to love computers, you must love change. And I do. But I think the magpie developer sometimes loves change to the detriment of his own craft.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jeff closes off with the following advice:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That&amp;rsquo;s the beauty of new things: there&amp;rsquo;s always a new one coming along. Don&amp;rsquo;t let the pursuit of new, shiny things accidentally become your goal. Avoid becoming a magpie developer. Be selective in your pursuit of the shiny and new, and you may find yourself a better developer for it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I cannot agree more with the conclusion. Never let the pursuit of shiny things become a goal in itself to your detriment.&lt;/p&gt;
&lt;h2 id="an-old-wives-tale" class="heading-anchor"&gt;An old wives&amp;rsquo; tale&lt;a href="#an-old-wives-tale" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Magpies scrambling to collect shiny objects &lt;a href="http://www.bbc.com/news/science-environment-28797519" target="_blank" rel="noopener noreferrer" class="external-link"&gt;is a myth&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Researchers placed mounds of edible nuts just 30cm away from each of the collected objects. In 64 tests during feeding, magpies picked up a shiny object only twice - and discarded it immediately.&lt;/p&gt;
&lt;p&gt;The birds essentially ignored or avoided both shiny and blue objects, and often fed less when they were present.&lt;/p&gt;
&lt;p&gt;Lead author Dr Toni Shephard said: &amp;ldquo;We did not find evidence of an unconditional attraction to shiny objects in magpies. Instead, all objects prompted responses indicating neophobia – fear of new things.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While it&amp;rsquo;s interesting in itself that debunking this myth warranted a research topic, the conclusion appeals to me. Magpies seem to have an innate fear of new things and treat them with suspicion.&lt;/p&gt;
&lt;p&gt;People often see the world in black and white, in polar opposites, in extremes. I have learned over time that &lt;em&gt;nothing&lt;/em&gt; is black and white. Whenever you find an opinion on the &lt;a href="http://wiki.c2.com/?FalseDichotomy" target="_blank" rel="noopener noreferrer" class="external-link"&gt;extreme end of a spectrum of options&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; the truth is probably somewhere in the middle.&lt;/p&gt;
&lt;p&gt;Let us reign back these absolute statements:&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 424 57"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 8,16 L 408,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;circle cx='8' cy='16' r='6' stroke='currentColor' fill='#fff'&gt;&lt;/circle&gt;
&lt;circle cx='408' cy='16' r='6' stroke='currentColor' fill='#fff'&gt;&lt;/circle&gt;
&lt;text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'&gt;O&lt;/text&gt;
&lt;text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'&gt;b&lt;/text&gt;
&lt;text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'&gt;y&lt;/text&gt;
&lt;text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'&gt;b&lt;/text&gt;
&lt;text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'&gt;j&lt;/text&gt;
&lt;text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'&gt;F&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='376' y='36' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='384' y='36' fill='currentColor' style='font-size:1em'&gt;g&lt;/text&gt;
&lt;text text-anchor='middle' x='392' y='36' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;With a more plausible statement:&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 424 105"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 8,16 L 200,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 200,16 L 408,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 200,32 L 200,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;polygon points='16.000000,16.000000 4.000000,10.400000 4.000000,21.600000' fill='currentColor' transform='rotate(180.000000, 8.000000, 16.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='208.000000,32.000000 196.000000,26.400000 196.000000,37.599998' fill='currentColor' transform='rotate(270.000000, 200.000000, 32.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='416.000000,16.000000 404.000000,10.400000 404.000000,21.600000' fill='currentColor' transform='rotate(0.000000, 408.000000, 16.000000)'&gt;&lt;/polygon&gt;
&lt;circle cx='200' cy='16' r='6' stroke='currentColor' fill='#fff'&gt;&lt;/circle&gt;
&lt;text text-anchor='middle' x='120' y='84' fill='currentColor' style='font-size:1em'&gt;C&lt;/text&gt;
&lt;text text-anchor='middle' x='128' y='84' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'&gt;u&lt;/text&gt;
&lt;text text-anchor='middle' x='144' y='84' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='152' y='84' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='160' y='84' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='168' y='84' fill='currentColor' style='font-size:1em'&gt;u&lt;/text&gt;
&lt;text text-anchor='middle' x='176' y='84' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='184' y='84' fill='currentColor' style='font-size:1em'&gt;,&lt;/text&gt;
&lt;text text-anchor='middle' x='200' y='84' fill='currentColor' style='font-size:1em'&gt;b&lt;/text&gt;
&lt;text text-anchor='middle' x='208' y='84' fill='currentColor' style='font-size:1em'&gt;u&lt;/text&gt;
&lt;text text-anchor='middle' x='216' y='84' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='84' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='240' y='84' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='84' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='84' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='272' y='84' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='280' y='84' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='288' y='84' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='296' y='84' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;That is the advice I give my children - don&amp;rsquo;t be scared, be careful. Then make sure they know the safety rules to avoid death. Fear has lost its usefulness in modern society where we are not hunted down by lions in every day life.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;My philosophy is that worrying means you suffer twice.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Newt Scamander (J.K. Rowling, &lt;a href="https://www.youtube.com/watch?v=eh9QbjqbK4E" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Fantastic Beasts and Where to Find Them&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="the-v-model-of-learning" class="heading-anchor"&gt;The V model of learning&lt;a href="#the-v-model-of-learning" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Agile proponents talk about &lt;a href="https://en.wikipedia.org/wiki/T-shaped_skills" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&amp;ldquo;T-shaped&amp;rdquo;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; people. The general idea is that effective people have broad (but shallow) knowledge in various topics, but deep knowledge in specific ones. It espouses the idea that a person should be able to work in different disciplines and that is indicative of a persons adaptability in a work environment.&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 280 169"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 0,16 L 64,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 64,16 L 112,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 112,16 L 192,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 64,16 L 64,96' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 112,16 L 112,64' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;polygon points='72.000000,96.000000 60.000000,90.400002 60.000000,101.599998' fill='currentColor' transform='rotate(90.000000, 64.000000, 96.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='120.000000,64.000000 108.000000,58.400002 108.000000,69.599998' fill='currentColor' transform='rotate(90.000000, 112.000000, 64.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='200.000000,16.000000 188.000000,10.400000 188.000000,21.600000' fill='currentColor' transform='rotate(0.000000, 192.000000, 16.000000)'&gt;&lt;/polygon&gt;
&lt;text text-anchor='middle' x='64' y='4' fill='currentColor' style='font-size:1em'&gt;A&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='132' fill='currentColor' style='font-size:1em'&gt;D&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'&gt;k&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='132' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='88' y='132' fill='currentColor' style='font-size:1em'&gt;p&lt;/text&gt;
&lt;text text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='96' y='132' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='104' y='132' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='104' y='148' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'&gt;B&lt;/text&gt;
&lt;text text-anchor='middle' x='112' y='148' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='120' y='132' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='128' y='132' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='128' y='148' fill='currentColor' style='font-size:1em'&gt;g&lt;/text&gt;
&lt;text text-anchor='middle' x='136' y='148' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'&gt;k&lt;/text&gt;
&lt;text text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'&gt;B&lt;/text&gt;
&lt;text text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='216' y='52' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='52' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='52' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='240' y='52' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='52' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'&gt;g&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;While this model is simple to understand it fails to model the interconnectedness of concepts, that concepts build on each other. It represents a persons skillset as poorly as the &lt;a href="http://www.dummies.com/careers/project-management/how-to-create-a-skills-matrix/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;skills matrix&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; that recruiters keep asking me for and I refuse to provide.&lt;/p&gt;
&lt;p&gt;Knowledge models are better expressed through &lt;a href="https://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;graphs&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; than &lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;trees&lt;/a&gt;. Although this T-shaped person can do A and B reasonably well it&amp;rsquo;s safe to assume that they will struggle with other tasks without a significant time investment in learning. What it means to perform a job &amp;ldquo;reasonably well&amp;rdquo; is a subjective and religious topic and inconsequential to this discussion.&lt;/p&gt;
&lt;p&gt;What we need are &lt;strong&gt;V-shaped&lt;/strong&gt; people.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s assume a person knows technology A and now needs to learn technology B:&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 432 265"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 96,16 L 400,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 296,80 L 320,80' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 120,96 L 128,96' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 144,96 L 152,96' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 168,96 L 184,96' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 224,160 L 232,160' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 232,160 L 240,160' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 264,160 L 288,160' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 96,16 L 96,240' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,96 L 136,112' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 128,128 L 136,112' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 200,224 L 232,160' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 232,160 L 280,64' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,112 L 144,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 184,64 L 232,160' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 232,160 L 272,240' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;polygon points='104.000000,240.000000 92.000000,234.399994 92.000000,245.600006' fill='currentColor' transform='rotate(90.000000, 96.000000, 240.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='192.000000,96.000000 180.000000,90.400002 180.000000,101.599998' fill='currentColor' transform='rotate(0.000000, 184.000000, 96.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='272.000000,160.000000 260.000000,154.399994 260.000000,165.600006' fill='currentColor' transform='rotate(180.000000, 264.000000, 160.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='304.000000,80.000000 292.000000,74.400002 292.000000,85.599998' fill='currentColor' transform='rotate(180.000000, 296.000000, 80.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='408.000000,16.000000 396.000000,10.400000 396.000000,21.600000' fill='currentColor' transform='rotate(0.000000, 400.000000, 16.000000)'&gt;&lt;/polygon&gt;
&lt;circle cx='200' cy='224' r='6' stroke='currentColor' fill='#fff'&gt;&lt;/circle&gt;
&lt;circle cx='232' cy='160' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;circle cx='272' cy='240' r='6' stroke='currentColor' fill='#fff'&gt;&lt;/circle&gt;
&lt;text text-anchor='middle' x='16' y='164' fill='currentColor' style='font-size:1em'&gt;k&lt;/text&gt;
&lt;text text-anchor='middle' x='24' y='164' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='32' y='132' fill='currentColor' style='font-size:1em'&gt;D&lt;/text&gt;
&lt;text text-anchor='middle' x='32' y='164' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='132' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='148' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='164' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'&gt;p&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='148' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='164' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='164' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='64' y='132' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'&gt;g&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='164' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='120' y='148' fill='currentColor' style='font-size:1em'&gt;`&lt;/text&gt;
&lt;text text-anchor='middle' x='136' y='84' fill='currentColor' style='font-size:1em'&gt;O&lt;/text&gt;
&lt;text text-anchor='middle' x='152' y='148' fill='currentColor' style='font-size:1em'&gt;`&lt;/text&gt;
&lt;text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'&gt;B&lt;/text&gt;
&lt;text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'&gt;A&lt;/text&gt;
&lt;text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='4' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='4' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='4' fill='currentColor' style='font-size:1em'&gt;k&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='4' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='4' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='288' y='52' fill='currentColor' style='font-size:1em'&gt;B&lt;/text&gt;
&lt;text text-anchor='middle' x='296' y='4' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'&gt;g&lt;/text&gt;
&lt;text text-anchor='middle' x='312' y='4' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='328' y='164' fill='currentColor' style='font-size:1em'&gt;P&lt;/text&gt;
&lt;text text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='336' y='164' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='336' y='196' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='344' y='100' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='344' y='164' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='344' y='180' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='344' y='196' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='100' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='164' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='180' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'&gt;P&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='100' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='164' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='368' y='68' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='368' y='100' fill='currentColor' style='font-size:1em'&gt;p&lt;/text&gt;
&lt;text text-anchor='middle' x='368' y='196' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='376' y='68' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='376' y='100' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='376' y='196' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='384' y='100' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='384' y='196' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='392' y='68' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='392' y='100' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='392' y='196' fill='currentColor' style='font-size:1em'&gt;y&lt;/text&gt;
&lt;text text-anchor='middle' x='400' y='100' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='408' y='100' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='416' y='100' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;The deeper you go down, the more knowledge you have of how concepts work under the covers. You understand the underlying concepts and are able to transfer those learnings to other technologies or disciplines. The &lt;em&gt;point of competence&lt;/em&gt; is the theoretical point that you need to reach to be able to produce work with reasonable competence using technology B. The &lt;em&gt;point of commonality&lt;/em&gt; is where the knowledge base for these two branches intersect and where you can reason about them on the same level.&lt;/p&gt;
&lt;p&gt;If your understanding is where I&amp;rsquo;ve plotted it in technology A, you have two options on how to proceed with learning B. You could jump the cliff between A and B with the potential risk of falling to your death:&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 408 217"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 208,112 L 224,112' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 168,144 L 200,144' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 96,160 L 112,160' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 128,192 L 136,192' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,192 L 144,192' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 168,192 L 192,192' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 92,24 L 204,24' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 224,64 L 224,112' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 72,64 L 92,24' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,192 L 184,96' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 88,96 L 136,192' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 204,24 L 224,64' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;polygon points='176.000000,192.000000 164.000000,186.399994 164.000000,197.600006' fill='currentColor' transform='rotate(180.000000, 168.000000, 192.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='216.000000,112.000000 204.000000,106.400002 204.000000,117.599998' fill='currentColor' transform='rotate(180.000000, 208.000000, 112.000000)'&gt;&lt;/polygon&gt;
&lt;circle cx='72' cy='64' r='6' stroke='currentColor' fill='#fff'&gt;&lt;/circle&gt;
&lt;circle cx='136' cy='192' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;text text-anchor='middle' x='16' y='164' fill='currentColor' style='font-size:1em'&gt;U&lt;/text&gt;
&lt;text text-anchor='middle' x='24' y='164' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='32' y='164' fill='currentColor' style='font-size:1em'&gt;k&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='164' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='164' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='164' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='64' y='164' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='164' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='84' fill='currentColor' style='font-size:1em'&gt;A&lt;/text&gt;
&lt;text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'&gt;J&lt;/text&gt;
&lt;text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'&gt;u&lt;/text&gt;
&lt;text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'&gt;p&lt;/text&gt;
&lt;text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'&gt;!&lt;/text&gt;
&lt;text text-anchor='middle' x='192' y='84' fill='currentColor' style='font-size:1em'&gt;B&lt;/text&gt;
&lt;text text-anchor='middle' x='208' y='196' fill='currentColor' style='font-size:1em'&gt;P&lt;/text&gt;
&lt;text text-anchor='middle' x='216' y='148' fill='currentColor' style='font-size:1em'&gt;U&lt;/text&gt;
&lt;text text-anchor='middle' x='216' y='196' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='148' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='196' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='148' fill='currentColor' style='font-size:1em'&gt;k&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='196' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='240' y='148' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='240' y='196' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='116' fill='currentColor' style='font-size:1em'&gt;P&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='148' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='116' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='148' fill='currentColor' style='font-size:1em'&gt;w&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='196' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='116' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='148' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='196' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='272' y='116' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='272' y='148' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='280' y='116' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='280' y='196' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='288' y='196' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='296' y='196' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='304' y='196' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='312' y='196' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='320' y='196' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='328' y='196' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='336' y='116' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='336' y='196' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'&gt;p&lt;/text&gt;
&lt;text text-anchor='middle' x='344' y='196' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='196' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='196' fill='currentColor' style='font-size:1em'&gt;y&lt;/text&gt;
&lt;text text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='392' y='116' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;The jump is difficult, and the end result is that large gaps remain in your knowledge as you have not reached the point of commonality - you have no point of reference. It will be difficult to achieve full competence in any of these technologies since the underlying concepts are still not clear and no skill transfer between A and B has taken place. Don&amp;rsquo;t get me wrong - there is a time to skim a subject and get the job done - but if you are looking at longevity and productivity in a skill then this approach is sub-optimal. Even worse, the chance of failure to make the leap increases because the fundamentals are missing.&lt;/p&gt;
&lt;p&gt;Compare a different approach - starting from the &lt;em&gt;point of commonality&lt;/em&gt; and working your way up.&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 288 169"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 208,48 L 224,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 96,128 L 112,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 128,128 L 136,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,128 L 144,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,128 L 184,32' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 184,128 L 224,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 88,32 L 136,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;polygon points='120.000000,128.000000 108.000000,122.400002 108.000000,133.600006' fill='currentColor' transform='rotate(0.000000, 112.000000, 128.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='216.000000,48.000000 204.000000,42.400002 204.000000,53.599998' fill='currentColor' transform='rotate(180.000000, 208.000000, 48.000000)'&gt;&lt;/polygon&gt;
&lt;circle cx='136' cy='128' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;circle cx='184' cy='128' r='6' stroke='currentColor' fill='#fff'&gt;&lt;/circle&gt;
&lt;text text-anchor='middle' x='16' y='148' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='24' y='148' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='32' y='148' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='116' fill='currentColor' style='font-size:1em'&gt;P&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='148' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='116' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='132' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='148' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='116' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='132' fill='currentColor' style='font-size:1em'&gt;f&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='148' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='64' y='116' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='64' y='148' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='116' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='148' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='20' fill='currentColor' style='font-size:1em'&gt;A&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='148' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='88' y='148' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='96' y='148' fill='currentColor' style='font-size:1em'&gt;y&lt;/text&gt;
&lt;text text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'&gt;B&lt;/text&gt;
&lt;text text-anchor='middle' x='216' y='132' fill='currentColor' style='font-size:1em'&gt;S&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='132' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='132' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='240' y='132' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='132' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='52' fill='currentColor' style='font-size:1em'&gt;E&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='52' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='272' y='52' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;Note that I&amp;rsquo;m not suggesting a specific learning direction - having a point of commonality available accelerates the learning process. Whether you start with the details and work your way up to higher level abstractions or the other way around is a matter of personal preference.&lt;/p&gt;
&lt;p&gt;In reality there are V&amp;rsquo;s with intersection points:&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 208 169"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 88,48 L 96,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 96,48 L 104,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 104,80 L 112,80' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 112,80 L 120,80' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 56,112 L 64,112' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 64,112 L 72,112' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 128,128 L 136,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,128 L 144,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 72,144 L 80,144' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 80,144 L 88,144' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 64,112 L 96,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 96,48 L 112,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 80,144 L 112,80' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 112,80 L 128,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 136,128 L 184,32' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 16,16 L 64,112' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 64,112 L 80,144' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 80,16 L 96,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 96,48 L 112,80' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 112,80 L 136,128' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;circle cx='64' cy='112' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;circle cx='80' cy='144' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;circle cx='96' cy='48' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;circle cx='112' cy='80' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;circle cx='136' cy='128' r='6' stroke='currentColor' fill='currentColor'&gt;&lt;/circle&gt;
&lt;text text-anchor='middle' x='8' y='4' fill='currentColor' style='font-size:1em'&gt;A&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'&gt;B&lt;/text&gt;
&lt;text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'&gt;C&lt;/text&gt;
&lt;text text-anchor='middle' x='136' y='36' fill='currentColor' style='font-size:1em'&gt;D&lt;/text&gt;
&lt;text text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'&gt;E&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;The more intersection points there are the easier the learning process becomes. You can increase the intersection points available to you by increasing the number of V&amp;rsquo;s or deepening the learning of existing ones.&lt;/p&gt;
&lt;p&gt;The Magpie tries to maximize the potential number of intersection points they have at their disposal through continuous learning. It&amp;rsquo;s an investment that pays off over the long term.&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;Generalists are a useful team compliment where tech/product is new, since the core skill is learning and applying new tech fast leveraging fundamentals and the web. I joke and call them full stackoverflow devs&lt;/p&gt;&amp;mdash; Jacques de Vos (@jacdevos) &lt;a href="https://twitter.com/jacdevos/status/974803557378650112?ref_src=twsrc%5Etfw"&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;br/&gt;
&lt;h2 id="build-a-solid-core" class="heading-anchor"&gt;Build a solid core&lt;a href="#build-a-solid-core" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Back in 2006 I knew my trade or at least thought I did. .NET 2.0 was the flavour of the day and I made it my personal mission to learn every nook and cranny of the BCL off by heart.&lt;/p&gt;
&lt;p&gt;Then, .NET 3.0 got released. With it came &lt;a href="https://en.wikipedia.org/wiki/Windows_Presentation_Foundation" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Windows Presentation Foundation (WPF)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Windows_Workflow_Foundation" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Windows Workflow Foundation (WWF)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Windows_Communication_Foundation" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Windows Communication Foundation (WCF)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. These were &lt;strong&gt;massive&lt;/strong&gt; frameworks and it dawned on me that my current approach to learning was not sustainable. That was a hard blow for &lt;a href="https://www.enneagraminstitute.com/type-5/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;someone who hoards knowledge and whose basic fear in life is being incompetent&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In response, I &lt;a href="https://en.wikipedia.org/wiki/Lean_startup#Pivot" target="_blank" rel="noopener noreferrer" class="external-link"&gt;pivoted&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. I learned principles and techniques rather than focusing on the implementation details. &lt;strong&gt;I started building a &lt;a href="http://codebetter.com/jpboodhoo/2007/04/05/build-a-solid-core/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;solid core&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I learned how to &lt;a href="https://riaan.hanekom.io/2007/05/12/unit-testing-and-mocks/"&gt;achieve quality through testing&lt;/a&gt; and how to architect applications to accommodate change and scale. I learned how to communicate my intent better by changing the way I write code. I learned how to work and communicate in teams which led me to the &lt;a href="http://agilemanifesto.org/principles.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;principles&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; of &lt;a href="http://agilemanifesto.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;agile methods&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and the &lt;a href="http://www.springer.com/cda/content/document/cda_downloaddocument/9783319090177-c1.pdf?SGWID=0-0-45-1488361-p176835196" target="_blank" rel="noopener noreferrer" class="external-link"&gt;psychology behind it&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I became proficient at &lt;strong&gt;learning&lt;/strong&gt; and &lt;strong&gt;unlearning&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I became fascinated by people and how they see the world. I built up my leadership skills to lead and manage from both a technical perspective and with &lt;strong&gt;a human centric&lt;/strong&gt; approach. I &lt;a href="https://riaan.hanekom.io/2010/07/11/just-finished-reading-lean-edition/"&gt;delved into the principals&lt;/a&gt; of &lt;a href="https://en.wikipedia.org/wiki/Lean_manufacturing" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Lean manufacturing&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and opened up my eyes to the &lt;a href="https://en.wikipedia.org/wiki/Lean_startup" target="_blank" rel="noopener noreferrer" class="external-link"&gt;economics and methods of software development, product and business development&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I became a more well-rounded technologist which allowed me to perform well in management and strategic positions and still keep in touch with my technical side. And I&amp;rsquo;m still learning.&lt;/p&gt;
&lt;p&gt;The trick behind learning and unlearning is to have a solid core in place. Your solid core represents the skills that are transferable across technologies and paradigms. As a developer you need to carry a toolbox with a decent collection of tools so that you can use the appropriate one when the situation presents itself.&lt;/p&gt;
&lt;p&gt;Even if you don&amp;rsquo;t get to use a technology on a day to day basis, learning it might still be of benefit as you can apply what you&amp;rsquo;ve learned elsewhere. Having a solid core &lt;strong&gt;deepens&lt;/strong&gt; your V&amp;rsquo;s and increases the amount of intersection points you have available. Building on practices like TDD allows you to do this with confidence.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Programmers who program &lt;strong&gt;&amp;ldquo;in&amp;rdquo;&lt;/strong&gt; a language limit their thoughts to constructs that the language directly supports. If the language tools are primitive, the programmer’s thoughts will also be primitive.&lt;/p&gt;
&lt;p&gt;Programmers who program &lt;strong&gt;&amp;ldquo;into&amp;rdquo;&lt;/strong&gt; a language first decide what thoughts they want to express, and then they determine how to express those thoughts using the tools provided by their specific language.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;My favourite quote from &lt;a href="https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Steve McConnell’s Code Complete book&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="intentional-learning" class="heading-anchor"&gt;Intentional learning&lt;a href="#intentional-learning" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The responsible Magpie does not latch on to every shiny object. Life is too short to accumulate unused knowledge. Instead, the responsible Magpie follows a structured process.&lt;/p&gt;
&lt;div class="mermaid"&gt;graph LR
A[Shiny thing] --&gt;|Evaluate..| B{Useful now?}
B --&gt;|No.| C{In the future?}
C --&gt;|No.| D(Drop it)
C --&gt;|Yes.| E(Defer)
B --&gt;|Yes.| F{Effort vs Value}
F --&gt;|"Bad."| H(Defer)
F --&gt;|"Good."| G(Backlog)
classDef plain fill:#fff,stroke:#000,stroke-width:2px;
classDef question fill:#fff,stroke:#000,stroke-width:2px;
classDef conclusion fill:#FDFDF4,stroke:#000,stroke-width:3px;
class A plain;
class C,B,F question;
class D,E,G,H conclusion;
&lt;/div&gt;
&lt;p&gt;The core evaluation criteria is usefulness (now or in the future) and the effort to learn versus the potential returns.&lt;/p&gt;
&lt;p&gt;Haphazard learning isn&amp;rsquo;t useful. Identify a goal and a plan to achieve that goal. Learning has to be &lt;strong&gt;intentional&lt;/strong&gt; and &lt;strong&gt;deliberate&lt;/strong&gt;. I would recommend keeping a prioritised backlog.&lt;/p&gt;
&lt;p&gt;Once the goal is in place set aside some time for learning. Using your personal time for this can be difficult if you have children. But even a 2 hour slot once a week will yield good results.&lt;/p&gt;
&lt;p&gt;Set aside time for learning at work. Not making the time at work or your employer denying you that time will be detrimental to both of you.&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;Programming is in ways like playing a music instrument.&lt;br&gt;- You have your preferred instrument (language)&lt;br&gt;- It&amp;#39;s an advantage to know another instrument,but not a necessity&lt;br&gt;- Sometimes it&amp;#39;s boring,like practising scales&lt;br&gt;- Little compares to when you find your groove.&lt;/p&gt;&amp;mdash; Pieter Louw (@pieterlouw) &lt;a href="https://twitter.com/pieterlouw/status/975379167683411968?ref_src=twsrc%5Etfw"&gt;March 18, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;blockquote class="twitter-tweet" data-conversation="none" data-lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;Also, there’s a bunch of people running around tooting horns they’ve never practised on. And another bunch of people, who’ve never even picked up a instrument, trying to direct them on when to play and complaining if they stop to try tune their instruments.&lt;/p&gt;&amp;mdash; Kevin Trethewey (@KevinTrethewey) &lt;a href="https://twitter.com/KevinTrethewey/status/976031252896735232?ref_src=twsrc%5Etfw"&gt;March 20, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;br/&gt;
&lt;p&gt;Make peace with the fact that you can&amp;rsquo;t remember &lt;em&gt;everything&lt;/em&gt;. I&amp;rsquo;m at a point where it feels like as soon as I learn something new something gets discarded. My memory is full and I hope it operates in a &lt;a href="https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_%28LRU%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;LRU&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; fashion. Knowledge gets shipped off to long term storage if frequently used - which, in a way, is a good thing as unused knowledge is pretty worthless.&lt;/p&gt;
&lt;p&gt;My brain seems to respond pretty well to saving pointers instead of the actual information. I can&amp;rsquo;t remember the full content of that article I read but I can sure conjure up the search terms to Google it again.&lt;/p&gt;
&lt;p&gt;Do what works best for you.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id="in-conclusion" class="heading-anchor"&gt;In conclusion&lt;a href="#in-conclusion" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Practice &lt;strong&gt;learning&lt;/strong&gt;, &lt;strong&gt;unlearning&lt;/strong&gt;, and &lt;strong&gt;connecting&lt;/strong&gt; ideas. It&amp;rsquo;s the most important skill you will ever gain. &lt;strong&gt;Plan ahead&lt;/strong&gt; on what to learn and &lt;strong&gt;look for intersection points&lt;/strong&gt; as a guide. Try to &lt;strong&gt;know what you &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; know&lt;/strong&gt;. It will be worth your while in the long run.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m a Magpie, but a responsible one. &lt;strong&gt;And that&amp;rsquo;s ok.&lt;/strong&gt;&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/_zNv_Cs0EfI?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Marina Salles&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/magpie?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Shiny things</title><link>https://riaan.hanekom.io/2018/03/27/shiny-things/</link><pubDate>Tue, 27 Mar 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/03/27/shiny-things/</guid><description>&lt;h2 id="rabbit-holes" class="heading-anchor"&gt;Rabbit holes&lt;a href="#rabbit-holes" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I disappear from time to time. No, not in the physical sense. Rabbit holes are &lt;strong&gt;everywhere&lt;/strong&gt;. I follow them and emerge a couple of days (or weeks) later, hopefully wiser.&lt;/p&gt;
&lt;p&gt;For illustration, I wandered through &lt;a href="https://www.docker.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Docker&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; land for a whole 6 months. That particular rabbit hole went deep. The weird and wonderful container landscape is still maturing and changing fast. Below the surface of a seemingly simple virtualisation technology lies myriad tools, concepts and philosophies. We have built out a single, auto-scaling CI grid that runs in containers, using other containers to build new container images, spinning up containers from those newly built images and testing them before publishing them. It&amp;rsquo;s &lt;a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down" target="_blank" rel="noopener noreferrer" class="external-link"&gt;turtles all the way down&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;h2 id="rabbit-holes" class="heading-anchor"&gt;Rabbit holes&lt;a href="#rabbit-holes" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I disappear from time to time. No, not in the physical sense. Rabbit holes are &lt;strong&gt;everywhere&lt;/strong&gt;. I follow them and emerge a couple of days (or weeks) later, hopefully wiser.&lt;/p&gt;
&lt;p&gt;For illustration, I wandered through &lt;a href="https://www.docker.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Docker&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; land for a whole 6 months. That particular rabbit hole went deep. The weird and wonderful container landscape is still maturing and changing fast. Below the surface of a seemingly simple virtualisation technology lies myriad tools, concepts and philosophies. We have built out a single, auto-scaling CI grid that runs in containers, using other containers to build new container images, spinning up containers from those newly built images and testing them before publishing them. It&amp;rsquo;s &lt;a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down" target="_blank" rel="noopener noreferrer" class="external-link"&gt;turtles all the way down&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Other than the standard unit and integration testing, we have to add &lt;a href="https://www.sonarqube.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;static code analysis&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://www.owasp.org/index.php/OWASP_Dependency_Check" target="_blank" rel="noopener noreferrer" class="external-link"&gt;application vulnerability analysis&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="https://github.com/coreos/clair" target="_blank" rel="noopener noreferrer" class="external-link"&gt;image vulnerability analysis&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; before an image even makes it to a &lt;a href="https://docs.docker.com/registry/deploying/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;private registry&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Then there are production considerations - orchestration with &lt;a href="https://rancher.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Rancher&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="https://kubernetes.io/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Kubernetes&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (amongst other flavours), vulnerability analysis of production images and &lt;a href="http://www.openvas.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;network security scans&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, scaling across geographic locations with redundancy, logging infrastructure, monitoring and reporting. Inside environments you can have containers that do nothing but provide services for other containers - whether that be providing data volumes by being a &lt;a href="https://www.tricksofthetrades.net/2016/03/14/docker-data-volumes/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;data container&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; or providing signals for routing and scheduling through labels. Yes, it&amp;rsquo;s possible to build &lt;a href="https://blog.quickmediasolutions.com/2017/09/28/a-1-kb-docker-container.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;a container that is less than 1kb&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for those use cases.
&lt;em&gt;It&amp;rsquo;s mind blowing&lt;/em&gt;. &amp;ldquo;The Docker way&amp;rdquo; is &lt;a href="https://azure.microsoft.com/en-us/blog/design-patterns-for-microservices/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;an enabler for micro-services&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and has changed the way I architect applications. It&amp;rsquo;s difficult to explain until you&amp;rsquo;ve chosen the red pill.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You take the blue pill - the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill - you stay in Wonderland, and I show you how deep the rabbit hole goes. Remember: all I&amp;rsquo;m offering is the truth. Nothing more.&lt;/p&gt;
&lt;p&gt;Morpheus, &lt;a href="https://en.wikipedia.org/wiki/The_Matrix" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Matrix&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sometimes following rabbit holes lead to procrastination. I haven&amp;rsquo;t posted to this blog in a long time because I wanted to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;change my blog from &lt;a href="https://riaan.hanekom.io/2012/05/05/now-blogging-on-octopress/"&gt;Octopress&lt;/a&gt; to &lt;a href="https://riaan.hanekom.io/2018/02/22/setting-up-jekyll-the-basics/"&gt;pure Jekyll&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;convert all my old posts &lt;a href="https://riaan.hanekom.io/2018/02/25/converting-html-blog-posts-to-markdown/"&gt;from HTML to Markdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;migrate my blog to run on &lt;a href="https://www.docker.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Docker&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; in &lt;a href="https://aws.amazon.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;AWS&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;recreate my automated deployment workflow&lt;/li&gt;
&lt;li&gt;set up &lt;a href="https://riaan.hanekom.io/2018/03/05/setting-up-https-with-lets-encrypt/"&gt;SSL using Let&amp;rsquo;s Encrypt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It took me a while to get around to it. I also refused to post until I could do my writing on a mobile device:&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;The novelty of being able to do this on my phone never wears off for me. // &lt;a href="https://twitter.com/termux?ref_src=twsrc%5Etfw"&gt;@termux&lt;/a&gt; &lt;a href="https://t.co/S6x1AbuCnp"&gt;pic.twitter.com/S6x1AbuCnp&lt;/a&gt;&lt;/p&gt;&amp;mdash; Riaan Hanekom (@rhanekom) &lt;a href="https://twitter.com/rhanekom/status/966693661789622273?ref_src=twsrc%5Etfw"&gt;February 22, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;Soon after, I became &lt;a href="https://riaan.hanekom.io/2018/03/18/setting-up-jekyll-navigation-with-a-modern-site-map-and-r.i.p/"&gt;frustrated with the limitations of Jekyll&lt;/a&gt;. I found the excuse I was looking for to try out &lt;a href="https://www.gatsbyjs.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Gatsby.js&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. After all, by now I have stopped treating JavaScript like a toy language and delved deep into it. I got my hands dirty with &lt;a href="https://reactjs.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;React&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and had &lt;a href="http://graphql.org/learn/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;GraphQL&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on my todo list. Now, on top of linting my JavaScript code my workflow incorporates a &lt;a href="https://github.com/remarkjs/remark-lint" target="_blank" rel="noopener noreferrer" class="external-link"&gt;linter for Markdown&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/markdown-spellcheck" target="_blank" rel="noopener noreferrer" class="external-link"&gt;spelling&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="https://github.com/btford/write-good" target="_blank" rel="noopener noreferrer" class="external-link"&gt;prose&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. No reason exists not to treat your blog like you would any other production application.&lt;/p&gt;
&lt;p&gt;In preparation for coming posts I wrote a Gatsby plugin called &lt;a href="https://www.npmjs.com/package/gatsby-remark-draw" target="_blank" rel="noopener noreferrer" class="external-link"&gt;gatsby-remark-draw&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; to render static diagrams using &lt;a href="https://github.com/ivanceras/svgbobrus" target="_blank" rel="noopener noreferrer" class="external-link"&gt;SvgBob&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. I proceeded down the rabbit hole and added &lt;a href="https://www.graphviz.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Graphviz&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="https://mermaidjs.github.io/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Mermaid.js&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; support as well. Combine it with &lt;a href="https://github.com/gaearon/react-hot-loader" target="_blank" rel="noopener noreferrer" class="external-link"&gt;React hot loader&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="https://www.vim.org/scripts/script.php?script_id=40" target="_blank" rel="noopener noreferrer" class="external-link"&gt;DrawIt&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and you can see your ASCII drawings come to life as you hit save. It&amp;rsquo;s a beautiful thing.&lt;/p&gt;
&lt;h2 id="faster-and-faster" class="heading-anchor"&gt;Faster and faster&lt;a href="#faster-and-faster" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Technology is moving at an incredible pace. This is evident in the plethora of new languages, frameworks and paradigms we are coming up with. We are working with new tools and need to adapt to entire new ways of thinking and reasoning about solutions. The pace of innovation is accelerating and there is no sign of it dissipating.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve seen an entire transformation in web development over the last decade. JavaScript flourished as browsers matured aided by the increase of computing power in the hands of developers and consumers of software. Transpiling is now commonplace where we have &lt;a href="https://sass-lang.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;SASS&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://lesscss.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;LESS&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://coffeescript.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;CoffeeScript&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TypeScript&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and others. Tools like &lt;a href="https://babeljs.io/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Babel&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; allows us to use new JavaScript features by transpiling to older versions of the language. We can tie everything together with &lt;a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;webpack&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; to hide some of the inherit complexities in polyglot programming and large scale application development. We are challenging conventional wisdom with &lt;a href="https://acss.io/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Atomic CSS&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://github.com/styled-components/styled-components" target="_blank" rel="noopener noreferrer" class="external-link"&gt;CSS in JavaScript&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="https://github.com/paypal/glamorous" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Component Styles&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And then, the uber frameworks. &lt;a href="https://angularjs.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Angular.js&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="https://reactjs.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;React&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; have transformed the way we build user interfaces and handle data and user interaction. &lt;a href="https://nodejs.org/en/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Node.js&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; brought JavaScript to the server side and the desktop. Running a proper command line utility on my machine that was pure JavaScript was a humbling experience back in the day.&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;When npm was first released in 2010, the release cycle for typical nodeJS package was 4 months, and npm restore took 15-30 seconds on an average project. By early 2018, the average release cycle for a JS package was 11 days, and the average npm restore step took 3-4 minutes. 1/11&lt;/p&gt;&amp;mdash; Dylan Beattie 🇪🇺 (@dylanbeattie) &lt;a href="https://twitter.com/dylanbeattie/status/976761360897003521?ref_src=twsrc%5Etfw"&gt;March 22, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://twitter.com/dylanbeattie/status/976761360897003521" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The thread&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is worth reading.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;big data&amp;rdquo; revolution has spawned an industry by itself where open source solutions became ubiquitous. Data collection, analysis and prediction tools became accessible to the masses. General use databases are now commodity. &lt;a href="https://www.postgresql.org/?&amp;amp;amp;" target="_blank" rel="noopener noreferrer" class="external-link"&gt;PostgreSQL&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://www.mysql.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;MySql&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;MongoDB&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://basho.com/products/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Riak&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://redis.io/o" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Redis&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="http://cassandra.apache.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Cassandra&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (to mention some) gained widespread adoption.&lt;/p&gt;
&lt;p&gt;I have been around long enough to witness the server revolution first-hand:&lt;/p&gt;
&lt;div class="goat-diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg"
font-family="Menlo,Lucida Console,monospace"
viewBox="0 0 696 73"&gt;
&lt;g transform='translate(8,16)'&gt;
&lt;path d='M 16,16 L 112,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 152,16 L 288,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 328,16 L 416,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 464,16 L 552,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 592,16 L 680,16' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 120,32 L 144,32' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 296,32 L 320,32' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 424,32 L 456,32' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 560,32 L 584,32' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 16,48 L 112,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 152,48 L 288,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 328,48 L 416,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 464,48 L 552,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 592,48 L 680,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 16,16 L 16,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 112,16 L 112,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 152,16 L 152,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 288,16 L 288,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 328,16 L 328,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 416,16 L 416,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 464,16 L 464,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 552,16 L 552,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 592,16 L 592,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;path d='M 680,16 L 680,48' fill='none' stroke='currentColor'&gt;&lt;/path&gt;
&lt;polygon points='152.000000,32.000000 140.000000,26.400000 140.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 144.000000, 32.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='328.000000,32.000000 316.000000,26.400000 316.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 320.000000, 32.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='464.000000,32.000000 452.000000,26.400000 452.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 456.000000, 32.000000)'&gt;&lt;/polygon&gt;
&lt;polygon points='592.000000,32.000000 580.000000,26.400000 580.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 584.000000, 32.000000)'&gt;&lt;/polygon&gt;
&lt;text text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'&gt;p&lt;/text&gt;
&lt;text text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='48' y='36' fill='currentColor' style='font-size:1em'&gt;y&lt;/text&gt;
&lt;text text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'&gt;v&lt;/text&gt;
&lt;text text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='176' y='36' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='184' y='36' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='192' y='36' fill='currentColor' style='font-size:1em'&gt;u&lt;/text&gt;
&lt;text text-anchor='middle' x='200' y='36' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='208' y='36' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='224' y='36' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='232' y='36' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'&gt;h&lt;/text&gt;
&lt;text text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'&gt;u&lt;/text&gt;
&lt;text text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'&gt;d&lt;/text&gt;
&lt;text text-anchor='middle' x='384' y='36' fill='currentColor' style='font-size:1em'&gt;v&lt;/text&gt;
&lt;text text-anchor='middle' x='392' y='36' fill='currentColor' style='font-size:1em'&gt;m&lt;/text&gt;
&lt;text text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'&gt;c&lt;/text&gt;
&lt;text text-anchor='middle' x='480' y='36' fill='currentColor' style='font-size:1em'&gt;o&lt;/text&gt;
&lt;text text-anchor='middle' x='488' y='36' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'&gt;t&lt;/text&gt;
&lt;text text-anchor='middle' x='504' y='36' fill='currentColor' style='font-size:1em'&gt;a&lt;/text&gt;
&lt;text text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'&gt;i&lt;/text&gt;
&lt;text text-anchor='middle' x='520' y='36' fill='currentColor' style='font-size:1em'&gt;n&lt;/text&gt;
&lt;text text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='600' y='36' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='608' y='36' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='616' y='36' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='624' y='36' fill='currentColor' style='font-size:1em'&gt;v&lt;/text&gt;
&lt;text text-anchor='middle' x='632' y='36' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='640' y='36' fill='currentColor' style='font-size:1em'&gt;r&lt;/text&gt;
&lt;text text-anchor='middle' x='648' y='36' fill='currentColor' style='font-size:1em'&gt;l&lt;/text&gt;
&lt;text text-anchor='middle' x='656' y='36' fill='currentColor' style='font-size:1em'&gt;e&lt;/text&gt;
&lt;text text-anchor='middle' x='664' y='36' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;text text-anchor='middle' x='672' y='36' fill='currentColor' style='font-size:1em'&gt;s&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;&lt;/div&gt;
&lt;p&gt;These are &lt;em&gt;some&lt;/em&gt; examples. Don&amp;rsquo;t get me started on &lt;a href="https://en.wikipedia.org/wiki/List_of_programming_languages" target="_blank" rel="noopener noreferrer" class="external-link"&gt;languages&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The list goes &lt;em&gt;on&lt;/em&gt; and &lt;em&gt;on&lt;/em&gt;. &lt;strong&gt;Novelty only lasts so long before it becomes generalised.&lt;/strong&gt; There are so&amp;hellip; &amp;hellip;many&amp;hellip; &amp;hellip;shiny&amp;hellip; &amp;hellip;things. It&amp;rsquo;s exhausting and exhilarating at the same time.&lt;/p&gt;
&lt;p&gt;I am not surprised that developers feel overwhelmed. Building a modern web application requires knowledge of a thousand frameworks, tools and languages. Take a closer look at the dependencies of the &lt;a href="https://github.com/facebook/create-react-app" target="_blank" rel="noopener noreferrer" class="external-link"&gt;create-react-app&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; application to see what I mean. Staying on top of it all is hard for &lt;em&gt;anyone&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="nobody-knows-everything" class="heading-anchor"&gt;Nobody knows everything&lt;a href="#nobody-knows-everything" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let us deal with a common theme in technology community - &lt;a href="https://www.hanselman.com/blog/ImAPhonyAreYou.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;imposter syndrome&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Scott&amp;rsquo;s post from 2011 still resonates with me. In particular, Scott quotes &lt;a href="http://www.encosia.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Dave Ward&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I think the more you know, the more you realize just how much you don&amp;rsquo;t know.&lt;/strong&gt; So paradoxically, the deeper down the rabbit hole you go, the more you might tend to fixate on the growing collection of unlearned peripheral concepts that you become conscious of along the way.&lt;/p&gt;
&lt;p&gt;That can manifest itself as feelings of fraudulence when people are calling you a &amp;ldquo;guru&amp;rdquo; or &amp;ldquo;expert&amp;rdquo; while you&amp;rsquo;re internally overwhelmed by the ever-expanding volumes of things you&amp;rsquo;re learning that you don&amp;rsquo;t know.&lt;/p&gt;
&lt;p&gt;However, I think it&amp;rsquo;s important to tamp those insecurities down and continue on with confidence enough to continue learning. &lt;strong&gt;After all, you&amp;rsquo;ve got the advantage of having this long list of things you know you don&amp;rsquo;t know, whereas most people haven&amp;rsquo;t even taken the time to uncover that treasure map yet.&lt;/strong&gt; What&amp;rsquo;s more, no one else has it all figured out either. &lt;strong&gt;We&amp;rsquo;re all just fumbling around in the adjacent possible, grasping at whatever good ideas and understanding we can manage to wrap our heads around.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The first part is an adaption from a quote widely attributed to &lt;a href="https://en.wikipedia.org/wiki/Albert_Einstein" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Albert Einstein&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; but Dave adds beautiful context to it. That statement made a profound impact on my life, my career, and my self-image.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The more I learn, the more I realize how much I don&amp;rsquo;t know.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Albert Einstein&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I cannot stress this point enough. &lt;strong&gt;Nobody knows everything&lt;/strong&gt;. People who boast about their knowledge and abilities are unaware of what they &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; know. It&amp;rsquo;s healthy to keep your skills up to date and increase your knowledge, but comparing yourself to others leads to increased anxiety. Attempting to know more than everyone else is an exercise in futility.&lt;/p&gt;
&lt;p&gt;Here is what is more important. Have confidence in what you do know while keeping to the spirit of &lt;a href="https://blog.codinghorror.com/strong-opinions-weakly-held/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&amp;ldquo;strong opinions, weakly held&amp;rdquo;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Make a decent attempt at knowing what you don&amp;rsquo;t know.&lt;/p&gt;
&lt;p&gt;In a world with too much information and too little time, focus on your ability to digest and process what matters. Let go of what is not useful any more.&lt;/p&gt;
&lt;p&gt;In this industry, if you are not moving forward you are moving backwards. Become good at &lt;strong&gt;learning&lt;/strong&gt; and &lt;strong&gt;unlearning&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;See how to do that in the follow up post - &lt;a href="https://riaan.hanekom.io/2018/04/14/the-magpie/"&gt;The Magpie&lt;/a&gt;.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/RLw-UC03Gwc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Glenn Carstens-Peters&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/procrastinate?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Setting up Jekyll - navigation with a modern site-map (and R.I.P)</title><link>https://riaan.hanekom.io/2018/03/18/setting-up-jekyll-navigation-with-a-modern-site-map-and-r.i.p/</link><pubDate>Sun, 18 Mar 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/03/18/setting-up-jekyll-navigation-with-a-modern-site-map-and-r.i.p/</guid><description>&lt;h2 id="preface" class="heading-anchor"&gt;Preface&lt;a href="#preface" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;In previous posts in this series I&amp;rsquo;ve used categories rather than tags. I have now switched these around because naming matters. If you need to do this, a quick sed execution will do the trick:&lt;/p&gt;</description><content:encoded>&lt;h2 id="preface" class="heading-anchor"&gt;Preface&lt;a href="#preface" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;In previous posts in this series I&amp;rsquo;ve used categories rather than tags. I have now switched these around because naming matters. If you need to do this, a quick sed execution will do the trick:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sed -i &lt;span style="color:#e6db74"&gt;&amp;#39;s/categories:/tags:/g&amp;#39;&lt;/span&gt; *.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Having changed the variable of tags we also need to change the include for displaying tags to replace categories with tags.&lt;/p&gt;
&lt;h2 id="autopages" class="heading-anchor"&gt;Autopages&lt;a href="#autopages" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The jekyll-paginate-v2 gem has &lt;a href="https://github.com/sverrirs/jekyll-paginate-v2/blob/master/README-AUTOPAGES.md" target="_blank" rel="noopener noreferrer" class="external-link"&gt;built-in support for generating pages&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; based on the tags and categories in posts. First, we need enable Autopages through our site configuration:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;YAML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;autopages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;categories&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;layouts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#39;home.html&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;title&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;Posts in category :cat&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;permalink&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;/category/:cat&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;collections&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tags&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;layouts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#39;home.html&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;title&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;Posts tagged with :tag&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;permalink&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;/tag/:tag&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I don&amp;rsquo;t use collections on this blog right now so I&amp;rsquo;ve left that as disabled. I&amp;rsquo;ve updated the &lt;code&gt;home.html&lt;/code&gt; file from the Minima theme to display excerpts when Jekyll recognises a page as auto-generated and to add the title specified in the configuration file. This means that there is a single page to maintain for the front page as well as the generated content:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;h1&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;page-heading&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if page.title and page.title != site.title %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ page.title | escape }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% else %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Posts
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ content }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;post-list&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for post in paginator.posts %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;span&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;post-meta&amp;#34;&lt;/span&gt;&amp;gt;{{ post.date | date: &amp;#34;%b %-d, %Y&amp;#34; }}&amp;lt;/&lt;span style="color:#f92672"&gt;span&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h2&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;post-link&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ post.url | relative_url }}&amp;#34;&lt;/span&gt;&amp;gt;{{ post.title | escape }}&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;h2&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if page.autopages %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;{{ post.excerpt }}&amp;lt;/&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ post.url }}&amp;#34;&lt;/span&gt;&amp;gt;READ MORE &amp;amp;gt;&amp;amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% else %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;{{ post.content }}&amp;lt;/&lt;span style="color:#f92672"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% include page_tags.html tags=post.tags %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We can then add a link to the tag page in the permalink format we specified in the config file which will take us to a page with the tag title and excerpts (with paging) from all the blog posts with the specified tag.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/tag/{{tag}}&amp;#34;&lt;/span&gt;&amp;gt;{{ tag }}&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The tags on this blog are simplistic. If you have some special characters in your tags the link will require some more filtering as the paginate gem performs transformations on the tag name in the URL.&lt;/p&gt;
&lt;h2 id="improving-performance-for-local-build" class="heading-anchor"&gt;Improving performance for local build&lt;a href="#improving-performance-for-local-build" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Enabling autopages can have a noticeable impact on the site build time since it needs to generate many pages. I&amp;rsquo;ve added a separate configuration file that disables expensive features so that I can get faster feedback on changes made, &lt;code&gt;_config_dev.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;YAML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## Disable features to speed up the build locally #&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;###################################################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Disable autopages&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;autopages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;categories&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;collections&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tags&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Disable noscript feature for gists as this makes an API call to Github for every gist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;gist&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;noscript&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Disable LSI because this can be dog slow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;lsi&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## Development features #&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Enable showing drafts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;show_drafts&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Enable showing future posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;future&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Enable incremental builds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;incremental&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With this config in hand we need to direct jekyll to the configuration files to use. In this example, any values specified in &lt;code&gt;_config_dev.yml&lt;/code&gt; will override the values in &lt;code&gt;_config.yml&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jekyll serve --config _config.yml,_config_dev.yml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href="https://jekyllrb.com/docs/configuration/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;configuration documentation&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for a list of options available.&lt;/p&gt;
&lt;h2 id="a-site-map" class="heading-anchor"&gt;A site map&lt;a href="#a-site-map" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start building a site map to add some extra options for navigation. Yes, I&amp;rsquo;m old school like that.&lt;/p&gt;
&lt;p&gt;Create a page in the root of the source content ( &lt;code&gt;map.md&lt;/code&gt; in my case) so that Jekyll can process it. With the Minima theme this will automatically show up in the main menu.&lt;/p&gt;
&lt;p&gt;To start off we&amp;rsquo;ll generate a list of tags and size the elements according to their usage frequency using inline styles. Following the advice on &lt;a href="https://superdevresources.com/tag-cloud-jekyll/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;this post&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and borrowing some code from it,&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;layout: page
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;title: Map
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;permalink: /map/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;## All tags
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% assign tags = site.tags | sort %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;post-tags&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for tag in tags %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/tag/{{ tag | first | slugify }}/&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;font-size: {{ tag | last | size | times: 6 | plus: 80 }}%&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ tag[0] | replace:&amp;#39;-&amp;#39;, &amp;#39; &amp;#39; }} ({{ tag | last | size }})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To avoid overflows of the tag text to the next line and cropped borders, we add some margins to the top and bottom, set &lt;code&gt;white-space&lt;/code&gt; to &lt;code&gt;nowrap&lt;/code&gt; and set the list item style to &lt;code&gt;inline-block&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;CSS&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;post-tags&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;ul&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;list-style&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;none&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;li&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;display&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;inline-block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;margin-top&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;margin-bottom&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;a&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;padding&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;border-radius&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;background&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;#EEEEFF&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;white-space&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;nowrap&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The results look promising, though a bit unpolished:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="tagcloud.jpg" alt="Tag cloud" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I have some cleaning up to do.&lt;/p&gt;
&lt;h1 id="most-recent" class="heading-anchor"&gt;Most recent&lt;a href="#most-recent" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;We can display an index to the most recent posts. We&amp;rsquo;ll do this by starting off with a generic component to display a list of posts given to it.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% if include.items %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;post-mini-list&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if include.heading %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;{{ include.heading }}&amp;lt;/&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for post in include.items limit: 5 %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ post.url }}&amp;#34;&lt;/span&gt;&amp;gt;{{ post.date | date: site.dateformat }} - {{ post.title }}&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This partial expects page to provide two variables - &lt;code&gt;include.items&lt;/code&gt; which contain some posts, and &lt;code&gt;include.heading&lt;/code&gt; which could contain an optional heading. Note the limit on 5 posts when iterating over the posts so that we don&amp;rsquo;t end up with a massive list of posts. Also note the variable usage of &lt;code&gt;site.dateformat&lt;/code&gt;, which I&amp;rsquo;ve set in the &lt;code&gt;_config.yml&lt;/code&gt; file. You can find a good reference to specifying date formats to use in Liquid tags &lt;a href="http://alanwsmith.com/jekyll-liquid-date-formatting-examples" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We can include this into the about page:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% include post-list.html items = site.posts heading = &amp;#34;Latest&amp;#34; %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;br/&gt;
&lt;h2 id="rip-jekyll" class="heading-anchor"&gt;R.I.P. Jekyll&lt;a href="#rip-jekyll" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This would have been part of this article if I did not rage quit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List of series&lt;/li&gt;
&lt;li&gt;Most popular&lt;/li&gt;
&lt;li&gt;Most recent&lt;/li&gt;
&lt;li&gt;By date buckets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s &lt;strong&gt;hard&lt;/strong&gt; to build advanced features in Jekyll. The API exposed by the framework impose limitations to the point where any sufficiently advanced plugin becomes a mess of spaghetti code in time. Back in the day when static site generators were a novelty, Jekyll was &lt;strong&gt;the&lt;/strong&gt; solution. Times have moved on and there are hoards of good alternatives available.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve moved this blog over to &lt;a href="https://github.com/gatsbyjs/gatsby" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Gatsby.js&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Gatsby is super fast, fully customisable and spits out a Progressive Web App built on top of React. The migration process was seamless other than having to fix some posts&amp;rsquo; frontmatter. Customisation takes a while longer as you find your way around the starter pack. On that note, I tried hard not to break any permalinks but one or two mistakes might have slipped through. I&amp;rsquo;ll leave advanced Gatsby.js topics for another post and move on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Fuj9pNrZpYQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Jeremy Bishop&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/site-map?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Setting up HTTPS with Let's Encrypt</title><link>https://riaan.hanekom.io/2018/03/05/setting-up-https-with-lets-encrypt/</link><pubDate>Mon, 05 Mar 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/03/05/setting-up-https-with-lets-encrypt/</guid><description>&lt;p&gt;Chrome 68, due in July 2018, &lt;a href="https://security.googleblog.com/2018/02/a-secure-web-is-here-to-stay.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;will mark all non-HTTPS sites as insecure&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Instead of buying a certificate it seemed like an apt opportunity to use &lt;a href="https://letsencrypt.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Let&amp;rsquo;s Encrypt&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, a free and automated Certificate Authority. It&amp;rsquo;s easy enough to get started with &lt;a href="https://certbot.eff.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Certbot supporting most platforms&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Chrome 68, due in July 2018, &lt;a href="https://security.googleblog.com/2018/02/a-secure-web-is-here-to-stay.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;will mark all non-HTTPS sites as insecure&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Instead of buying a certificate it seemed like an apt opportunity to use &lt;a href="https://letsencrypt.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Let&amp;rsquo;s Encrypt&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, a free and automated Certificate Authority. It&amp;rsquo;s easy enough to get started with &lt;a href="https://certbot.eff.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Certbot supporting most platforms&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="getting-started" class="heading-anchor"&gt;Getting started&lt;a href="#getting-started" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;By far the easiest way of getting started is if you have access to the web content directory. Certbot will generate a file in a well known path and handle the handshaking process between Let&amp;rsquo;s Encrypt and the website to verify the websites identity. Google Analytics has a similar approach to prove site ownership and the &lt;a href="https://ietf-wg-acme.github.io/acme/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ACME protocol&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; documents the process.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using an &lt;a href="https://alpinelinux.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Alpine Linux&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; image for my blog container and a package for Certbot exists in the standard repositories. This installs other dependencies (notably Python) which bloats the image somewhat but it&amp;rsquo;s a small price to pay in this instance. Here&amp;rsquo;s the amended Dockerfile:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Dockerfile&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;nginx:alpine&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Copy content&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; ./_site /usr/share/nginx/html&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Copy config&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; nginx.conf /etc/nginx/nginx.conf&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; default.conf /etc/nginx/conf.d/default.conf&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;VOLUME&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/letsencrypt&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;RUN&lt;/span&gt; apk add --no-cache bash certbot&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXPOSE&lt;/span&gt; &lt;span style="color:#e6db74"&gt;80&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXPOSE&lt;/span&gt; &lt;span style="color:#e6db74"&gt;443&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;!-- more --&gt;
&lt;p&gt;First we create a volume for &lt;code&gt;/etc/letsencrypt&lt;/code&gt; where Certbot will save the certificates. This allows other containers to use the same certificate by mounting the same volume. On the server I&amp;rsquo;ve manually created a volume with the following command:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker volume create --name certificates&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We add the &lt;code&gt;certbot&lt;/code&gt; package using &lt;code&gt;apk&lt;/code&gt; for later use and of course expose port 443 for SSL. When we run the container we need to mount the newly created volume at the location specified in the Dockerfile:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker run -d --name blog -p 80:80 -p 443:443 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -v certificates:/etc/letsencrypt blog:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With this container built and running, we need to get the initial certificates manually. Inside the container we ask Certbot to generate a certificate for us. I&amp;rsquo;ve included both &lt;em&gt;yourdomain.com&lt;/em&gt; and &lt;em&gt;&amp;lt;www.yourdomain.com&amp;gt;&lt;/em&gt; as I have a redirect from &lt;em&gt;www&lt;/em&gt; to &lt;em&gt;non-www&lt;/em&gt;. The &lt;code&gt;--webroot&lt;/code&gt; directive makes Certbot use the file system for certificate generation and validation and not integrate directly with the web server through a plugin - I prefer to edit the website configuration by hand.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;--agree-tos&lt;/code&gt; and &lt;code&gt;--email&lt;/code&gt; flags are necessary to avoid interactive prompts for this information on first registration.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;certbot --webroot -d yourdomain.com -d www.yourdomain.com &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --webroot-path /usr/share/nginx/html &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --email youemail@domain.com --agree-tos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You should see the output shown below. Take note of the renewal instructions - we&amp;rsquo;ll get back to that.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Congratulations! Your certificate and chain have been saved at:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /etc/letsencrypt/live/yourdomain.com/fullchain.pem
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Your key file has been saved at:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /etc/letsencrypt/live/yourdomain.com/privkey.pem
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Your cert will expire on xxxx-xx-xx. To obtain a new or tweaked
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; version of this certificate in the future, simply run certbot
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; again. To non-interactively renew *all* of your certificates, run
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;certbot renew&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - Your account credentials have been saved in your Certbot
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; configuration directory at /etc/letsencrypt. You should make a
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; secure backup of this folder now. This configuration directory will
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; also contain certificates and private keys obtained by Certbot so
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; making regular backups of this folder is ideal.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - If you like Certbot, please consider supporting our work by:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Donating to ISRG / Let&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;s Encrypt: https://letsencrypt.org/donate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Donating to EFF: https://eff.org/donate-le&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can find the generated certificates inside the &lt;em&gt;/etc/letsencrypt/live&lt;/em&gt; folder.&lt;/p&gt;
&lt;h2 id="nginx-setup" class="heading-anchor"&gt;NGINX setup&lt;a href="#nginx-setup" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Now that we have the certificates we can set up the web server (NGINX in my case) to use them. First, let&amp;rsquo;s redirect all traffic from port 80 to port 443:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Nginx&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listen&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;server_name&lt;/span&gt; &lt;span style="color:#e6db74"&gt;www.yourdomain.com&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;301&lt;/span&gt; &lt;span style="color:#e6db74"&gt;https://yourdomain.com&lt;/span&gt;$request_uri;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listen&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;server_name&lt;/span&gt; &lt;span style="color:#e6db74"&gt;yourdomain.com&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;301&lt;/span&gt; &lt;span style="color:#e6db74"&gt;https://yourdomain.com&lt;/span&gt;$request_uri;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will return a &lt;em&gt;301 moved&lt;/em&gt; status code and keep the original sub-URI for redirection. Now to set up HTTPS :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Nginx&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listen&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;443&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ssl&lt;/span&gt; &lt;span style="color:#e6db74"&gt;default&lt;/span&gt; &lt;span style="color:#e6db74"&gt;deferred&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;server_name&lt;/span&gt; &lt;span style="color:#e6db74"&gt;yourdomain.com&lt;/span&gt; &lt;span style="color:#e6db74"&gt;www.yourdomain.com&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_certificate&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/letsencrypt/live/yourdomain.com/fullchain.pem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_certificate_key&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/letsencrypt/live/yourdomain.com/privkey.pem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Session resumption
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_session_cache&lt;/span&gt; &lt;span style="color:#e6db74"&gt;shared:SSL:10m&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_session_timeout&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5m&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Specify types of TLS, specifically avoiding SSL3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_protocols&lt;/span&gt; &lt;span style="color:#e6db74"&gt;TLSv1&lt;/span&gt; &lt;span style="color:#e6db74"&gt;TLSv1.1&lt;/span&gt; &lt;span style="color:#e6db74"&gt;TLSv1.2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Disable insecure ciphers
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ssl_ciphers&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;EECDH+ECDSA+AESGCM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EECDH+aRSA+AESGCM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EECDH+ECDSA+SHA384&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EECDH+ECDSA+SHA256&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EECDH+aRSA+SHA384&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EECDH+aRSA+SHA256&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EECDH+aRSA+RC4&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EECDH&lt;/span&gt; &lt;span style="color:#e6db74"&gt;EDH+aRSA&lt;/span&gt; &lt;span style="color:#e6db74"&gt;RC4&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!aNULL&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!eNULL&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!LOW&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!3DES&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!MD5&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!EXP&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!PSK&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!SRP&lt;/span&gt; &lt;span style="color:#e6db74"&gt;!DSS&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# HTTP Strict Transport Security
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;add_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Strict-Transport-Security&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;max-age=63072000&lt;/span&gt;; &lt;span style="color:#f92672"&gt;includeSubdomains&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ....
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s important to disable SSLv3 as &lt;a href="http://disablessl3.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the protocol is vulnerable to attacks&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; so we specify TLSv1, TLSv1.1, and TLSv1.2 explicitly as the allowed versions.&lt;/p&gt;
&lt;p&gt;Furthermore we add HSTS as another layer of defence &lt;a href="https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security" target="_blank" rel="noopener noreferrer" class="external-link"&gt;to avoid access of the website over HTTP by default&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The HTTP Strict Transport Security header informs the browser that it
should never load a site using HTTP and should automatically convert all
attempts to access the site using HTTP to HTTPS requests instead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, once the browser spots this header and once it confirms that the site has HTTPS enabled it will always use HTTPS for future requests. We can set the &lt;code&gt;max-age&lt;/code&gt; parameter as high as it can go as I&amp;rsquo;m not planning on rolling this back to HTTP any time soon.&lt;/p&gt;
&lt;p&gt;We also need to disable insecure ciphers to avoid downgrading of the connection to a less secure cipher. SSLlabs have &lt;a href="https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices" target="_blank" rel="noopener noreferrer" class="external-link"&gt;a great article that they frequently update with best practices in this regard&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We enable &lt;a href="https://blog.cloudflare.com/tls-session-resumption-full-speed-and-secure/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;session resumption&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for performance reasons. The server will store a session id of the client so that future connections with the same session id (in a short time frame) the client can resume the session instead of going through the whole negotiation process again.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: The &lt;a href="https://www.ssllabs.com/ssltest/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;SSLlabs TLS testing tool&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is the best tool to test your SSL implementation and will highlight any potential issues. While using it read the notes about compatibility - it&amp;rsquo;s essential to get the balance right between security and compatibility.&lt;/p&gt;
&lt;h2 id="renewing-certificates" class="heading-anchor"&gt;Renewing certificates&lt;a href="#renewing-certificates" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s Encrypt certificates are valid for three months so we need to run the renew process frequently to avoid sitting with an expired certificate. Certbot has this built in with the &lt;code&gt;certbot renew&lt;/code&gt; command, mentioned in the initial output after first creation of the certificates. There are a couple of different ways to do this with containers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Running a sidekick container to renew the certificates&lt;/li&gt;
&lt;li&gt;Installing the dependencies on the host and running the command directly on the volume&lt;/li&gt;
&lt;li&gt;Running crontab on the host machine and exec&amp;rsquo;ing into the container&lt;/li&gt;
&lt;/ol&gt;
&lt;br/&gt;
&lt;p&gt;(2) is way too dirty and spoils all the isolation benefits we have with containerisation and (1) is the way I would do it with serious production applications abiding to &amp;ldquo;the Docker way&amp;rdquo;. In the spirit of doing the simplest thing possible I opted for (3). On the host machine you can edit the crontab file via the command&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo crontab -e&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We can create a simple entry to run the renew command in the container on a schedule:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt; * * * docker exec blog certbot renew --post-hook &lt;span style="color:#e6db74"&gt;&amp;#34;nginx -s reload&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will run the renew process and if the script renewed the certificate execute the post hook, which restarts the web server and let the change take effect.&lt;/p&gt;
&lt;h2 id="note" class="heading-anchor"&gt;Note&lt;a href="#note" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s Encrypt applies rate limiting on requests to their services. While you are testing you can use &lt;a href="https://letsencrypt.org/docs/staging-environment/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;their staging area&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; to avoid hitting the request ceiling.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/FqaybX9ZiOU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;James Sutton&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/padlock?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Setting up Jekyll - related posts and series</title><link>https://riaan.hanekom.io/2018/03/01/setting-up-jekyll-related-posts-and-series/</link><pubDate>Thu, 01 Mar 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/03/01/setting-up-jekyll-related-posts-and-series/</guid><description>&lt;p&gt;By default, the related_posts feature of Jekyll returns the newest 10 posts rather than related posts. This is to speed up generation of the site by not using it&amp;rsquo;s Latent Semantic Indexing (LSI) capabilities implemented by &lt;a href="https://github.com/jekyll/classifier-reborn" target="_blank" rel="noopener noreferrer" class="external-link"&gt;classifier-reborn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; since that takes a while to run.&lt;/p&gt;</description><content:encoded>&lt;p&gt;By default, the related_posts feature of Jekyll returns the newest 10 posts rather than related posts. This is to speed up generation of the site by not using it&amp;rsquo;s Latent Semantic Indexing (LSI) capabilities implemented by &lt;a href="https://github.com/jekyll/classifier-reborn" target="_blank" rel="noopener noreferrer" class="external-link"&gt;classifier-reborn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; since that takes a while to run.&lt;/p&gt;
&lt;p&gt;To use LSI, you need to add the &lt;code&gt;--lsi&lt;/code&gt; flag. Out of the box, it takes an incredibly long time to run. On my small blog, it took over an hour to complete the build process with LSI included. We&amp;rsquo;re in luck though - installing &lt;a href="http://www.gnu.org/software/gsl/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;GSL&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and the &lt;em&gt;rb-gsl&lt;/em&gt; gem speeds up the process (down to less than a minute for my blog). Advice from the &lt;em&gt;rb-gsl&lt;/em&gt; gem after installation is that you could install the &lt;em&gt;nmatrix&lt;/em&gt; and &lt;em&gt;narray&lt;/em&gt; gems as well, but do this before &lt;em&gt;rb-gsl&lt;/em&gt; installation.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve found that adding the &lt;em&gt;nmatrix&lt;/em&gt; and &lt;em&gt;narray&lt;/em&gt; gems to your Gemfile causes runtime dependency issues (specifically, duplicate definitions of classes). To automate the process, I&amp;rsquo;ve added a separate &lt;em&gt;Gemfile.preinstall&lt;/em&gt; with these gems included to aid in the automated deployment on my web server. You can do this by taking advantage of the &lt;code&gt;--gemfile&lt;/code&gt; parameter to bundler:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bundle install --gemfile Gemfile.preinstall&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;!-- more --&gt;
&lt;p&gt;To install &lt;em&gt;rb-gsl&lt;/em&gt;, install gsl as well as the development libraries:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt-get install gsl-bin libgsl2 libgsl-dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And then add the &lt;em&gt;rb-gsl&lt;/em&gt; to your Gemfile and install it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You can also directly install from source:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;wget ftp://ftp.gnu.org/gnu/gsl/gsl-latest.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tar -xvf gsl-latest.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd gsl*
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./configure
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo make install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To link to the library, add the following to your .bashrc (or .zshrc, whichever shell you are using):&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;export LD_LIBRARY_PATH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$LD_LIBRARY_PATH:/usr/local/lib/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now that we have installation completed we can use the &lt;code&gt;related_posts&lt;/code&gt; property with confidence. Note that this property is not supported by GitHub pages, a common hosting platform, and by default contains the &lt;em&gt;x&lt;/em&gt; most recent posts if the &lt;code&gt;--lsi&lt;/code&gt; flag is not passed to the generator.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll start off with a simple list of related posts in the main post page, limiting it to three recommendations:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% if site.related_posts.size &amp;gt; 0 %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;aside&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;Related:&amp;lt;/&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for related in site.related_posts limit:3 %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{related.url}}&amp;#34;&lt;/span&gt;&amp;gt;{{ related.title }}&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;aside&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The final result looks pretty accurate:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="related_posts.jpg" alt="Related posts" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="post-series" class="heading-anchor"&gt;Post series&lt;a href="#post-series" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Another thing that is missing is to automatically link a series of posts together. We can achieve this by adding a custom series variable in the front matter of a post. This variable specifies the name of the series which we can find posts with and group them together. For lack of a better name we will call the variable series:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Markdown&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;title: &amp;#34;Setting up Jekyll - related posts and series&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tags: jekyll ruby blog
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;series: building-a-blog
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The include for this looks something like the following:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% if include.series %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;aside&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;series&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;Choose your own adventure! This post is part of the series &amp;lt;&lt;span style="color:#f92672"&gt;strong&lt;/span&gt;&amp;gt;&amp;amp;quot;{{ include.series | replace: &amp;#39;-&amp;#39;, &amp;#39; &amp;#39;| capitalize }}&amp;amp;quot;&amp;lt;/&lt;span style="color:#f92672"&gt;strong&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ol&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for post in site.posts reversed %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if post.series == include.series %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if post.url == include.url %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ post.title }} &amp;amp;lt;-- &amp;lt;&lt;span style="color:#f92672"&gt;strong&lt;/span&gt;&amp;gt;this post&amp;lt;/&lt;span style="color:#f92672"&gt;strong&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% else %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ post.url }}&amp;#34;&lt;/span&gt;&amp;gt;{{ post.title }}&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ol&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;aside&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;SCSS&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-scss" data-lang="scss"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;aside&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.series&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-color&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;#BABDB6&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-style&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; solid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;margin&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And the final result:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="series.jpg" alt="Series posts" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/AJCNM8JrzT8?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/design?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Setting up Jekyll - prettier paging and categories</title><link>https://riaan.hanekom.io/2018/02/28/setting-up-jekyll-prettier-paging-and-categories/</link><pubDate>Wed, 28 Feb 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/02/28/setting-up-jekyll-prettier-paging-and-categories/</guid><description>&lt;p&gt;Following up from the previous post on &lt;a href="https://riaan.hanekom.io/2018/02/22/setting-up-jekyll-the-basics/"&gt;setting up Jekyll&lt;/a&gt;, we take out our tools and customize it some more. When reading any of my posts you should realise I&amp;rsquo;m after &lt;em&gt;utility&lt;/em&gt; rather than &lt;em&gt;beauty&lt;/em&gt;. That said, we&amp;rsquo;ll try to improve the appearance to an acceptable level as we go along.&lt;/p&gt;
&lt;h2 id="prettier-paging" class="heading-anchor"&gt;Prettier paging&lt;a href="#prettier-paging" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The next/previous paging is functional, but rather ugly. The &lt;a href="https://github.com/sverrirs/jekyll-paginate-v2" target="_blank" rel="noopener noreferrer" class="external-link"&gt;jekyll-pagination-v2&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; gem has what we need with support for pagination trails. We need to update our config for this:&lt;/p&gt;</description><content:encoded>&lt;p&gt;Following up from the previous post on &lt;a href="https://riaan.hanekom.io/2018/02/22/setting-up-jekyll-the-basics/"&gt;setting up Jekyll&lt;/a&gt;, we take out our tools and customize it some more. When reading any of my posts you should realise I&amp;rsquo;m after &lt;em&gt;utility&lt;/em&gt; rather than &lt;em&gt;beauty&lt;/em&gt;. That said, we&amp;rsquo;ll try to improve the appearance to an acceptable level as we go along.&lt;/p&gt;
&lt;h2 id="prettier-paging" class="heading-anchor"&gt;Prettier paging&lt;a href="#prettier-paging" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The next/previous paging is functional, but rather ugly. The &lt;a href="https://github.com/sverrirs/jekyll-paginate-v2" target="_blank" rel="noopener noreferrer" class="external-link"&gt;jekyll-pagination-v2&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; gem has what we need with support for pagination trails. We need to update our config for this:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;YAML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;pagination&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;trail&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;before&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;after&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And replace our previous paging with a more functional one, unceremoniously borrowed from &lt;a href="https://github.com/sverrirs/jekyll-paginate-v2/blob/master/examples/03-tags/_layouts/home.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the example page&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% if paginator.total_pages &amp;gt; 1 %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;pager&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if paginator.first_page %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;previous&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ paginator.first_page_path | prepend: site.baseurl | replace: &amp;#39;//&amp;#39;, &amp;#39;/&amp;#39; }}&amp;#34;&lt;/span&gt;&amp;gt;First&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if paginator.previous_page %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;previous&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ paginator.previous_page_path | prepend: site.baseurl | replace: &amp;#39;//&amp;#39;, &amp;#39;/&amp;#39; }}&amp;#34;&lt;/span&gt;&amp;gt;&amp;amp;larr; Newer Posts&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if paginator.page_trail %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for trail in paginator.page_trail %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;{%&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;page&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;url &lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;trail&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;%}&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;selected&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;{%&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;endif&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;%}&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ trail.path | prepend: site.baseurl | replace: &amp;#39;//&amp;#39;, &amp;#39;/&amp;#39; }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{trail.title}}&amp;#34;&lt;/span&gt;&amp;gt;{{ trail.num }}&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if paginator.next_page %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;next&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ paginator.next_page_path | prepend: site.baseurl | replace: &amp;#39;//&amp;#39;, &amp;#39;/&amp;#39; }}&amp;#34;&lt;/span&gt;&amp;gt;Older Posts &amp;amp;rarr;&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if paginator.last_page %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;previous&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ paginator.last_page_path | prepend: site.baseurl | replace: &amp;#39;//&amp;#39;, &amp;#39;/&amp;#39; }}&amp;#34;&lt;/span&gt;&amp;gt;Last&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We&amp;rsquo;ll add some styling to make it look slightly prettier:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;SCSS&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-scss" data-lang="scss"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.pager&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;list-style&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; none;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;li&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;display&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; inline;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-color&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;#BABDB6&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-style&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; solid;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-width&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;li&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;.selected&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;background-color&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;#EEEEFF&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And voilà!&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="pager.jpg" alt="Styled pager" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="displaying-categories" class="heading-anchor"&gt;Displaying categories&lt;a href="#displaying-categories" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Displaying categories on pages are a useful way of navigating a website to find related content in collections curated by the author. These are also known as &lt;em&gt;tags&lt;/em&gt; in blog nomenclature but I&amp;rsquo;ve opted to use the tags variable (pre-defined in Jekyll) for internal organization of pages (more on this later in a later post). With categories already a native concept in Jekyll we can iterate over them on a page level (&lt;code&gt;_layouts/post.html&lt;/code&gt; in the &lt;em&gt;Minima&lt;/em&gt; theme):&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;post-categories&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;Posted in:&amp;lt;/&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for category in page.categories %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;{{ category }}&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And then add some rounded corners and pretty colours via CSS:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;SCSS&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-scss" data-lang="scss"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;.post-categories&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ul&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;list-style&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; none;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;li&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;display&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; inline;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;padding&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-radius&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;background&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;#EEEEFF&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="tags.jpg" alt="Jekyll tags" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I changed this home page to display full post content and not the excerpts so that one can read in peace without having to click through to an article. To display the categories on the home page as well we need to edit the home layout (&lt;code&gt;_layouts/home.html&lt;/code&gt; in the &lt;em&gt;Minima&lt;/em&gt; theme). Instead of copying and pasting, let&amp;rsquo;s move the categories markup to an &lt;a href="https://jekyllrb.com/docs/includes/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;include file&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;code&gt;_includes/page_categories.html&lt;/code&gt; in my case:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% if include.categories %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;class&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;post-categories&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;Posted in:&amp;lt;/&lt;span style="color:#f92672"&gt;h3&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% for category in include.categories %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;{{ category }}&amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endfor %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Notice that the variable we loop over is now &lt;code&gt;include.categories&lt;/code&gt;. The different pages/layouts pass this as &lt;a href="https://jekyllrb.com/docs/includes#using-variables-names-for-the-include-file" target="_blank" rel="noopener noreferrer" class="external-link"&gt;an include variable&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; as such:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% include page_categories.html categories=post.categories %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In a future post we&amp;rsquo;ll explore category pages and tag clouds.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/iacpoKgpBAM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Goran Ivos&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code-couch?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Converting HTML blog posts to Markdown</title><link>https://riaan.hanekom.io/2018/02/25/converting-html-blog-posts-to-markdown/</link><pubDate>Sun, 25 Feb 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/02/25/converting-html-blog-posts-to-markdown/</guid><description>&lt;p&gt;I am reviving some projects - this blog as well as some open source work. They desperately need some TLC&amp;hellip;&lt;/p&gt;
&lt;p&gt;Since this blog has travelled through &lt;a href="https://riaan.hanekom.io/2011/12/17/blog-moved/"&gt;different&lt;/a&gt; &lt;a href="https://riaan.hanekom.io/2012/05/05/now-blogging-on-octopress/"&gt;hosting options&lt;/a&gt; and &lt;a href="https://riaan.hanekom.io/2018/02/22/setting-up-jekyll-the-basics/"&gt;technologies&lt;/a&gt; I still had some legacy posts formatted in HTML. I&amp;rsquo;ve taken the plunge to refactor them into much cleaner Markdown syntax.&lt;/p&gt;
&lt;p&gt;This turned out easier than expected. With a couple of good libraries to lean on I wrote a quick Node application to do the dirty work. This aspect of the Node.js community is the same reason why I fell in love with Ruby in the first place - the wealth of small, well-crafted libraries/gems/packages that focus on solving specific problems eloquently.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I am reviving some projects - this blog as well as some open source work. They desperately need some TLC&amp;hellip;&lt;/p&gt;
&lt;p&gt;Since this blog has travelled through &lt;a href="https://riaan.hanekom.io/2011/12/17/blog-moved/"&gt;different&lt;/a&gt; &lt;a href="https://riaan.hanekom.io/2012/05/05/now-blogging-on-octopress/"&gt;hosting options&lt;/a&gt; and &lt;a href="https://riaan.hanekom.io/2018/02/22/setting-up-jekyll-the-basics/"&gt;technologies&lt;/a&gt; I still had some legacy posts formatted in HTML. I&amp;rsquo;ve taken the plunge to refactor them into much cleaner Markdown syntax.&lt;/p&gt;
&lt;p&gt;This turned out easier than expected. With a couple of good libraries to lean on I wrote a quick Node application to do the dirty work. This aspect of the Node.js community is the same reason why I fell in love with Ruby in the first place - the wealth of small, well-crafted libraries/gems/packages that focus on solving specific problems eloquently.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll design the app with stream input and output, taking HTML input from stdin and outputting the resulting Markdown on stdout. In this way we can use it in conjunction with other tools, true to the &lt;a href="http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/c1089.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unix tools philosophy&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. First, let&amp;rsquo;s start with &lt;code&gt;package.json&lt;/code&gt; file. We can create one with &lt;code&gt;npm init&lt;/code&gt; and fill in the blanks:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;JSON&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;htmlconvert&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;main&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;index.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;echo \&amp;#34;Error: no test specified\&amp;#34; &amp;amp;&amp;amp; exit 1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;turndown&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;^4.0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;get-stdin&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;^5.0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;turndown-plugin-gfm&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;^1.0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;gray-matter&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;^3.1.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;htmlconvert&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;index.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Riaan Hanekom&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;license&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ISC&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We make use of these great packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sindresorhus/get-stdin" target="_blank" rel="noopener noreferrer" class="external-link"&gt;get-stdin&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; : gets stdin as a string or buffer&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/domchristie/turndown" target="_blank" rel="noopener noreferrer" class="external-link"&gt;turndown&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; : convert HTML to Markdown using JavaScript&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/domchristie/turndown-plugin-gfm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;turndown-plugin-gfm&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; : a plugin for turndown to enable GitHub Flavoured Markdown&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jonschlinkert/gray-matter" target="_blank" rel="noopener noreferrer" class="external-link"&gt;gray-matter&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; : a library that parses different types of front-matter&lt;/li&gt;
&lt;/ul&gt;
&lt;br/&gt;
&lt;p&gt;Note the bin section in the &lt;code&gt;package.json&lt;/code&gt; file. This allows us to run &lt;code&gt;npm link&lt;/code&gt; and have the convenience of not having to type in &lt;code&gt;node index.js&lt;/code&gt; every time we want to run the app. If we decided to publish this application as an official npm package we would have to set the &lt;code&gt;preferGlobal&lt;/code&gt; flag to &lt;code&gt;true&lt;/code&gt; as well so that a user gets warned if the package is not installed with the &lt;code&gt;--global&lt;/code&gt; flag [&lt;a href="https://javascriptplayground.com/node-command-line-tool/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;further reading&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;].&lt;/p&gt;
&lt;p&gt;Here is the &lt;code&gt;index.js&lt;/code&gt; file marked for execution in all its (quick and dirty) glory:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;JavaScript&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#! /usr/bin/env node
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getStdin&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;get-stdin&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TurndownService&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;turndown&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;turndownPluginGfm&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;turndown-plugin-gfm&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;matter&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;gray-matter&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;getStdin&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt; =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;turndown&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;TurndownService&lt;/span&gt;( {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;codeBlockStyle&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fenced&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;linkStyle&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;referenced&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;gfm&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;turndownPluginGfm&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;gfm&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;turndown&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;use&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;gfm&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;parsed&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;matter&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;str&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;content&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;parsed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;parsed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;markdown&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;turndown&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;turndown&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;matter&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stringify&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;markdown&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;First we retrieve all the input from stdin. The turndown package is nicely customizable and I&amp;rsquo;ve set the output format styles to what I prefer where it differs from &lt;a href="https://github.com/domchristie/turndown" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the defaults&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We ask the turndown library to use the gfm plugin to support GitHub Flavoured Markdown. The turndown library strips out newlines from the Jekyll front-matter at the moment. &lt;a href="https://github.com/domchristie/turndown/issues/211" target="_blank" rel="noopener noreferrer" class="external-link"&gt;This issue&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; provides a simple workaround - use the &lt;a href="https://github.com/jonschlinkert/gray-matter" target="_blank" rel="noopener noreferrer" class="external-link"&gt;gray-matter&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; library to parse the front matter.&lt;/p&gt;
&lt;p&gt;Now that we have the input and output mechanisms ready, we can write&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;b&amp;gt;ICanHaz Bold!&amp;lt;/b&amp;gt;&amp;#34;&lt;/span&gt; | htmlconvert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The output will be:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Markdown&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;**ICanHazBold!**&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s pipe a sample blog post with front matter in:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;STR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;$&amp;#39;---\n title: stufff \n---\n&amp;lt;b&amp;gt;ICanHazBold\!&amp;lt;/b&amp;gt;&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$STR&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; | htmlconvert&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Markdown&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;title: stufff
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;**ICanHazBold!**&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Beautiful!&lt;/p&gt;
&lt;p&gt;We can now convert our posts in bulk by iterating over all the HTML posts:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; file in *.html; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cat &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$file&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; | htmlconvert &amp;gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;basename &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$file&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; .html&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;.md&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And then we dutifully proceed with QA on each converted post before deleting the original. This code will not handle some of the edge cases that I was coding up in HTML back in 2005. To be honest, I&amp;rsquo;m not sure whether this was intentionally bad markup or signs of scars received while fighting with Wordpress, but inline styles for italics and bold text and auto-closing paragraph tags (&amp;lt;p/&amp;gt;) are some examples. Those cases are rare so I chose to handle them manually rather than diving into the &lt;a href="https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454" target="_blank" rel="noopener noreferrer" class="external-link"&gt;insanity which is HTML parsing&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/yEAOfWSdzgM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Pankaj Patel&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Setting up Jekyll - the basics</title><link>https://riaan.hanekom.io/2018/02/22/setting-up-jekyll-the-basics/</link><pubDate>Thu, 22 Feb 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/02/22/setting-up-jekyll-the-basics/</guid><description>&lt;h2 id="introduction" class="heading-anchor"&gt;Introduction&lt;a href="#introduction" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Since Octopress has been deprecated for pure use of Jekyll, I switched this blog to use Jekyll. See this post as a walkthrough on creating a functional blog via Jekyll (part 1). This is yet another collation of snippets I have found useful, as a reference for my future self - and perhaps others.&lt;/p&gt;</description><content:encoded>&lt;h2 id="introduction" class="heading-anchor"&gt;Introduction&lt;a href="#introduction" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Since Octopress has been deprecated for pure use of Jekyll, I switched this blog to use Jekyll. See this post as a walkthrough on creating a functional blog via Jekyll (part 1). This is yet another collation of snippets I have found useful, as a reference for my future self - and perhaps others.&lt;/p&gt;
&lt;h2 id="starting-off" class="heading-anchor"&gt;Starting off&lt;a href="#starting-off" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can find the installation instructions for Jekyll in the &lt;a href="https://jekyllrb.com/docs/installation/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;official documentation&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After you install the Jekyll gem, scaffolding a new site is as easy as&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jekyll new blog_name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This will create a new folder with a starter site. To serve your site to preview it, run the&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;jekyll --serve&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;command and navigate to &lt;a href="http://localhost:4000" target="_blank" rel="noopener noreferrer" class="external-link"&gt;http://localhost:4000&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (the default port) with your favourite browser.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="defaults-excerpts-and-url-structures" class="heading-anchor"&gt;Defaults, excerpts and URL structures&lt;a href="#defaults-excerpts-and-url-structures" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;By default the home page will display the full list of posts with all it&amp;rsquo;s glorious content. This might be a bit too much for longer posts. To enable excerpts with links to the full post you need to configure the excerpt_seperator. You can specify this in the front matter of each post. We can also specify the format of the permalink to the posts, with a sane URL structure including the date and title of the post.&lt;/p&gt;
&lt;p&gt;Instead of repeating ourselves in the frontmatter of each post we can DRY it up a bit by specifying defaults in the config.yml file:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;YAML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;defaults&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;scope&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;path&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# an empty string here means all files in the project&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;posts&amp;#34;&lt;/span&gt; &lt;span style="color:#75715e"&gt;# previously `post` in Jekyll 2.2.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;values&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;layout&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;post&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;excerpt_separator&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;lt;!`--` more `--`&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;comments&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;permalink&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;/blog/:year/:month/:day/:title&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The format &lt;em&gt;YYmmDD&lt;/em&gt; is locale specific - but one advantage with using this format is that your posts can be chronologically ordered even on the file system. The final URL for a post would look something like this:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;http://riaanhanekom.com/2018/01/21/travis-with-sonarcloud&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With the configuration above applied, content displays on the home page up to where the content processor finds the &lt;code&gt;&amp;lt;!--more --&amp;gt;&lt;/code&gt; marker:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="jekyll_excerpt.jpg" alt="Jekyll excerpt" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="override-the-look-and-feel" class="heading-anchor"&gt;Override the look and feel&lt;a href="#override-the-look-and-feel" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We can create a main stylesheet in the &lt;em&gt;assets&lt;/em&gt; directory in your source folder. main.scss will be the Sass file included after everything else so you can override any styles that you want. Since we&amp;rsquo;ve used the minima theme it&amp;rsquo;s important that we import it at the top. Let&amp;rsquo;s put in a separator between the posts:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;SCSS&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-scss" data-lang="scss"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;minima&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;.post-list&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;border-bottom&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; solid &lt;span style="color:#ae81ff"&gt;#b6b6b6&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;padding-bottom&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;margin&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;m not a big fan of the 800px fixed-width style - by adding the following CSS into &lt;em&gt;assets/main.scss&lt;/em&gt; we can take up more real-estate on the screen:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;CSS&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#a6e22e"&gt;wrapper&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;max-width&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;none&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;margin-right&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;margin-left&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;auto&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;padding-right&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;padding-left&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;%&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To override the markup provided by the default theme you can &amp;ldquo;eject&amp;rdquo;, copy the files from the gem installation directory into your own source directory and change them at will.&lt;/p&gt;
&lt;p&gt;The command&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bundle show minima&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;will show you the source directory to copy the files from.&lt;/p&gt;
&lt;h2 id="productionise-it" class="heading-anchor"&gt;Productionise it&lt;a href="#productionise-it" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;As with any software development it&amp;rsquo;s important to get the production aspects out of the way. You can always change this later, but doing this early in the process avoids a bunch of &amp;ldquo;whoops, didn&amp;rsquo;t think about that&amp;rdquo; moments. Deploying to GitHub pages is a popular method of serving a blog made with Jekyll, but since I&amp;rsquo;ll be deploying this on a private server we&amp;rsquo;ll focus on building and running a docker container for this purpose. Let&amp;rsquo;s create a simple NGINX server to host our application with this Dockerfile:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Dockerfile&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; &lt;span style="color:#e6db74"&gt;nginx&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; ./_site /usr/share/nginx/html&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; nginx.conf /etc/nginx/nginx.conf&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;COPY&lt;/span&gt; default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Simple enough. Jekyll generates the site static content under the _site directory which can we can copy into the default serving directory of NGINX. I&amp;rsquo;ve added a configuration file to add cache control headers for static content (images, js, css). HTML pages are still set for the browser to check back to server if any content has changed. We also enable gzip and set up NGINX to scan for the index.html file in directories to have nice file-less URLs:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Nginx&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;42
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;43
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;user&lt;/span&gt; &lt;span style="color:#e6db74"&gt;nginx&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;worker_processes&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;error_log&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/var/log/nginx/error.log&lt;/span&gt; &lt;span style="color:#e6db74"&gt;warn&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;pid&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/var/run/nginx.pid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;events&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;worker_connections&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;http&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;server&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;location&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;try_files&lt;/span&gt; $uri $uri/index.html $uri.html =&lt;span style="color:#ae81ff"&gt;404&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;location&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/assets&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;expires&lt;/span&gt; &lt;span style="color:#e6db74"&gt;1M&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;add_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Cache-Control&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;public,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;max-age=691200,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;s-maxage=691200&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;location&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/images&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;expires&lt;/span&gt; &lt;span style="color:#e6db74"&gt;1M&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;add_header&lt;/span&gt; &lt;span style="color:#e6db74"&gt;Cache-Control&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;public,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;max-age=691200,&lt;/span&gt; &lt;span style="color:#e6db74"&gt;s-maxage=691200&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;rewrite&lt;/span&gt; &lt;span style="color:#e6db74"&gt;^/(.*)/&lt;/span&gt;$ &lt;span style="color:#e6db74"&gt;/&lt;/span&gt;$1 &lt;span style="color:#e6db74"&gt;permanent&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;expires&lt;/span&gt; $expires;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;include&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/nginx/mime.types&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;default_type&lt;/span&gt; &lt;span style="color:#e6db74"&gt;application/octet-stream&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;log_format&lt;/span&gt; &lt;span style="color:#e6db74"&gt;main&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;$remote_addr &lt;span style="color:#e6db74"&gt;-&lt;/span&gt; $remote_user &lt;span style="color:#e6db74"&gt;[&lt;/span&gt;$time_local] &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$request&amp;#34; &lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;$status $body_bytes_sent &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$http_referer&amp;#34; &lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#34;&lt;/span&gt;$http_user_agent&amp;#34; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$http_x_forwarded_for&amp;#34;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;access_log&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/var/log/nginx/access.log&lt;/span&gt; &lt;span style="color:#e6db74"&gt;main&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sendfile&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;keepalive_timeout&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;65&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;gzip&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;on&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;include&lt;/span&gt; &lt;span style="color:#e6db74"&gt;/etc/nginx/conf.d/*.conf&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;At this point don&amp;rsquo;t forget to update the header include template to add a cache buster for the stylesheet:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ &amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;assets&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;css&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;relative_url&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;}}?{{&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;site&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;time&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;|&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;date:&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;%&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;%&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;N&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;}}&amp;#34;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The generated link to the stylesheet would look something like &lt;em&gt;/assets/main.css?1519308247603964426&lt;/em&gt;. The time value at the point of generation gets appended to the stylesheet URL allowing us to cache the asset on clients until it changes.&lt;/p&gt;
&lt;h2 id="working-with-drafts" class="heading-anchor"&gt;Working with drafts&lt;a href="#working-with-drafts" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;To work on draft posts without publishing them, create a &amp;lsquo;&lt;em&gt;drafts&lt;/em&gt;&amp;rsquo; folder in your source folder per the &lt;a href="https://jekyllrb.com/docs/drafts/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;documentation&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. When running &lt;em&gt;jekyll serve&lt;/em&gt;, pass in the &lt;em&gt;&amp;ndash;draft&lt;/em&gt; parameter to show drafts. Depending on your needs it might also be useful to add the &lt;em&gt;&amp;ndash;future&lt;/em&gt; parameter to display posts that have a date in the future.&lt;/p&gt;
&lt;h2 id="paging" class="heading-anchor"&gt;Paging&lt;a href="#paging" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;No good blog should be without paging. By default my installation came with the jekyll-paginate gem installed. I&amp;rsquo;ve found that the next iteration of the gem, &lt;a href="https://github.com/sverrirs/jekyll-paginate-v2" target="_blank" rel="noopener noreferrer" class="external-link"&gt;jekyll-paginate-v2&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; works better and is simpler to set up.&lt;/p&gt;
&lt;p&gt;To activate, add the jekyll-paginate-v2 to the plugins section of the config and your &lt;em&gt;Gemfile&lt;/em&gt;. There are tons of configuration options for pagination, but here were the ones I found important for now:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;YAML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;pagination&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;collection&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;posts&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;per_page&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;permalink&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#39;/page/:num/&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Where you display your posts you will need to iterate over the paginator.posts instead of posts:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Ruby&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; post &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; paginator&lt;span style="color:#f92672"&gt;.&lt;/span&gt;posts&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If you are using the minima theme, it&amp;rsquo;s time to copy over the home.html file from the layouts folder and update it. We also shouldn&amp;rsquo;t forget to add the pagination links at the bottom:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;HTML&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% if paginator.total_pages &amp;gt; 1 %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if paginator.previous_page %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ paginator.previous_page_path | prepend: site.baseurl }}&amp;#34;&lt;/span&gt;&amp;gt;Newer&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% if paginator.next_page %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#f92672"&gt;a&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ paginator.next_page_path | prepend: site.baseurl }}&amp;#34;&lt;/span&gt;&amp;gt;Older&amp;lt;/&lt;span style="color:#f92672"&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#f92672"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {% endif %}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This gives us an easy way to navigate between pages:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="jekyll_pagination.jpg" alt="Jekyll pagination" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Hmmm, functional, but not pretty. We&amp;rsquo;ll improve on this in future posts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/ED7FewvIb8k?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/typewriter?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Using Sonar Cloud on .NET Core with Travis</title><link>https://riaan.hanekom.io/2018/01/21/using-sonar-cloud-on-.net-core-with-travis/</link><pubDate>Sun, 21 Jan 2018 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2018/01/21/using-sonar-cloud-on-.net-core-with-travis/</guid><description>&lt;p&gt;Note to self since I spent a frustratingly long time on this. To analyse your .NET Core project with Sonar on Linux (using Travis in my case since it&amp;rsquo;s an open source project), you need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a machine with Mono and .NET Core installed&lt;/li&gt;
&lt;li&gt;Download the MSBuild Sonar Analyzer and ensure that the scripts are executable&lt;/li&gt;
&lt;li&gt;Execute it with the right amount of parameters&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- more --&gt;
&lt;p&gt;For reference, some build steps out of a Travis YAML file I&amp;rsquo;ve been working for &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;</description><content:encoded>&lt;p&gt;Note to self since I spent a frustratingly long time on this. To analyse your .NET Core project with Sonar on Linux (using Travis in my case since it&amp;rsquo;s an open source project), you need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a machine with Mono and .NET Core installed&lt;/li&gt;
&lt;li&gt;Download the MSBuild Sonar Analyzer and ensure that the scripts are executable&lt;/li&gt;
&lt;li&gt;Execute it with the right amount of parameters&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- more --&gt;
&lt;p&gt;For reference, some build steps out of a Travis YAML file I&amp;rsquo;ve been working for &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- mono ../tools/sonar/SonarQube.Scanner.MSBuild.exe begin /n:NGenerics /k:ngenerics-github /d:sonar.login&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;SONAR_TOKEN&lt;span style="color:#e6db74"&gt;}&lt;/span&gt; /d:sonar.host.url&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://sonarcloud.io&amp;#34;&lt;/span&gt; /d:sonar.cs.vstest.reportsPaths&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;*/TestResults/.trx&amp;#34;&lt;/span&gt; /v:&lt;span style="color:#e6db74"&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- dotnet build
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- dotnet test NGenerics.Tests --logger:trx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- dotnet test NGenerics.Examples --logger:trx
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- mono ../tools/sonar/SonarQube.Scanner.MSBuild.exe end /d:sonar.login&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;SONAR_TOKEN&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The CLI scanner does &lt;em&gt;not&lt;/em&gt; work for C# code at the time of writing. The MSBuild scanner works.&lt;/li&gt;
&lt;li&gt;The MSBuild scanner requires Mono as the SonarQube team is still in the progress of migrating some dependencies.&lt;/li&gt;
&lt;li&gt;${SONAR_TOKEN} is an environment variable injected by Travis that contains an authentication token. The VSTest reports come from NUnit tests via the &amp;ldquo;&amp;ndash;logger:trx&amp;rdquo; parameter passed to dotnet run.&lt;/li&gt;
&lt;li&gt;You need to pass the property sonar.login to the &amp;ldquo;end&amp;rdquo; step of the MSBuild scanner since that information is not persisted to disk when running &amp;ldquo;begin&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hope this saves someone some time - the feedback cycle is incredibly long as the Sonar scan tends to break on the last step.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/znM0ujn2RUA?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Shane Colella&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/cactus?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Still alive</title><link>https://riaan.hanekom.io/2016/12/25/still-alive/</link><pubDate>Sun, 25 Dec 2016 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2016/12/25/still-alive/</guid><description>&lt;p&gt;I&amp;rsquo;m still alive. And so will this blog be once again.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s an interesting feeling to notice that your last post dates back to 4 years (4 YEARS!) ago.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve done the migration from Octopress to vanilla Jekyll now and in the spirit of doing the smallest thing possible, this is the MVP.&lt;/p&gt;
&lt;p&gt;Since my last post I have made the leap to Software Development Manager, and then to General Manager - Technology and Development at DStv Digital Media. It&amp;rsquo;s been an interesting journey and I have some scars to show and some stories to tell.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;m still alive. And so will this blog be once again.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s an interesting feeling to notice that your last post dates back to 4 years (4 YEARS!) ago.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve done the migration from Octopress to vanilla Jekyll now and in the spirit of doing the smallest thing possible, this is the MVP.&lt;/p&gt;
&lt;p&gt;Since my last post I have made the leap to Software Development Manager, and then to General Manager - Technology and Development at DStv Digital Media. It&amp;rsquo;s been an interesting journey and I have some scars to show and some stories to tell.&lt;/p&gt;
&lt;p&gt;For now, let&amp;rsquo;s consider this is a kickstart of a habit &lt;strong&gt;before&lt;/strong&gt; new years resolutions kick in.&lt;/p&gt;
&lt;p&gt;Hold thumbs. Let&amp;rsquo;s see how this goes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/JfUNA4kKn5g?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Josh Withers&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Acceptance testing with SpecFlow and Selenium</title><link>https://riaan.hanekom.io/2012/05/27/acceptance-testing-with-specflow-and-selenium/</link><pubDate>Sun, 27 May 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/05/27/acceptance-testing-with-specflow-and-selenium/</guid><description>&lt;p&gt;I&amp;rsquo;m an &lt;a href="http://riaanhanekom.com/2007/05/12/unit-testing-and-mocks/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;avid believer in testing&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TDD&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; helps drive design, and having a test suite available to verify behaviour while maintaining an application is worth a million bucks. Even the most complete unit test suite still doesn&amp;rsquo;t guarantee that the integration between different components is correct, nor does it test the value a system delivers from a user perspective. Does a feature do what a user expects it to do? Does your application fulfil it&amp;rsquo;s functional and non-functional requirements? Does it even run?&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;m an &lt;a href="http://riaanhanekom.com/2007/05/12/unit-testing-and-mocks/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;avid believer in testing&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TDD&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; helps drive design, and having a test suite available to verify behaviour while maintaining an application is worth a million bucks. Even the most complete unit test suite still doesn&amp;rsquo;t guarantee that the integration between different components is correct, nor does it test the value a system delivers from a user perspective. Does a feature do what a user expects it to do? Does your application fulfil it&amp;rsquo;s functional and non-functional requirements? Does it even run?&lt;/p&gt;
&lt;p&gt;Acceptance testing tests features as if a user was interacting with them. This means testing the system through the user interface, a system driver layer, or a combination of the two. This could be useful in a couple of ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As a &lt;a href="http://en.wikipedia.org/wiki/Smoke_testing" target="_blank" rel="noopener noreferrer" class="external-link"&gt;smoke test&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for a deployed application.&lt;/li&gt;
&lt;li&gt;As part of your &lt;a href="http://en.wikipedia.org/wiki/Continuous_integration" target="_blank" rel="noopener noreferrer" class="external-link"&gt;continuous integration&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; build.&lt;/li&gt;
&lt;li&gt;As part of your &lt;a href="http://continuousdelivery.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;deployment pipeline&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; strategy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Acceptance testing can be implemented as a form of &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development" target="_blank" rel="noopener noreferrer" class="external-link"&gt;BDD&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - in a user story we should be able to express the requirements in a format that we can use to write an &lt;a href="http://www.agilemodeling.com/essays/executableSpecifications.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;executable specification&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I liked the following simple distinction between what BDD and TDD aims for:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TDD&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; implements and verifies details - did I build the &lt;em&gt;thing&lt;/em&gt; right?
&lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development" target="_blank" rel="noopener noreferrer" class="external-link"&gt;BDD&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; specifies features and scenarios - did I build the &lt;em&gt;right&lt;/em&gt; thing?
&lt;em&gt;Armando Fox and David Patterson, &lt;a href="http://www.amazon.com/gp/product/B006WU5G4C" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Engineering Long-Lasting Software&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To enable BDD, &lt;a href="http://rspec.info/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;RSpec&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; does a beautiful job in setting up context and &lt;a href="http://cukes.info/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Cucumber&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; guides you down the &lt;em&gt;&lt;a href="https://github.com/cucumber/cucumber/wiki/Given-When-Then" target="_blank" rel="noopener noreferrer" class="external-link"&gt;given when then&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/em&gt; path. Both (as well as other testing frameworks) can be used to write acceptance tests, but Cucumber makes sense if you have a business facing person looking at your specs. If not, writing your tests in English is a complete waste of time.&lt;/p&gt;
&lt;p&gt;The .NET world does not have the same amount of tooling support for this kind of thing. &lt;a href="http://stackoverflow.com/questions/307895/what-is-the-most-mature-bdd-framework-for-net" target="_blank" rel="noopener noreferrer" class="external-link"&gt;This Stack Overflow question&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; gives a nice summary on the current state of BDD libraries for .NET. For the xSpec (context / specification) flavour, we have &lt;a href="http://nspec.org" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NSpec&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://github.com/machine/machine.specifications" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Machine.Specifications&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and &lt;a href="http://nspecify.sourceforge.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NSpecify&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Because of the constraints of a statically typed language, the syntax of these libraries sucks. We could try and &lt;a href="http://weblogs.asp.net/rashid/archive/2010/06/18/write-your-tests-in-rspec-with-ironruby.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;use RSpec with IronRuby&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, but it will add an extra, unneeded paradigm in a project.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;For the xBehave family we are in luck - &lt;a href="http://www.specflow.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;SpecFlow&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, is a BSD licensed library that allows us to write specifications like Cucumber in the popular &lt;a href="https://github.com/cucumber/cucumber/wiki/Gherkin" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Gherkin&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; language on .NET. SpecFlow integrates well with Visual Studio, providing support for auto completion in feature files. Features compile down to &lt;a href="http://www.nunit.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NUnit&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; tests, which can be run with your stock standard testing tool set.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve written a small web application that allows you to search through an in-memory list of fruit, to test out the tool set:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="specflow-sampleapp.jpg" alt="Sample application" loading="lazy" title="Sample application"&gt;
&lt;figcaption&gt;Sample application&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;This is what my feature looks like:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Cucumber&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;36
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;37
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;38
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;39
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;40
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;41
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-cucumber" data-lang="cucumber"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Feature:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt; Search
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; In order to avoid scanning through a long list
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; As a user
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; I want to be able to search for fruit by it&amp;#39;s name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Background:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; Given &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I have the following fruit available:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Name&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Banana&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Pear&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Kiwi&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Watermelon&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Orange&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Naartjie&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Lemon&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Apple&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; &lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Given &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I am on the &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Home Page&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Scenario:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt; Browse search page
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; Then &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I should see &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Search Fruit&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;@search&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Scenario:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt; Search for a specific fruit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; When &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I search for &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;apple&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; &lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Then &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I should see &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Apple&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;@search&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Scenario:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt; Search for a partial fruit name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; When &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I search for &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;on&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; &lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Then &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I should see &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Watermelon&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; &lt;/span&gt;&lt;span style="color:#66d9ef"&gt;And &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I should see &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;Lemon&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;@search&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Scenario:&lt;/span&gt;&lt;span style="color:#a6e22e"&gt; No search results
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; When &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I search for &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;nonexistentfruit&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt; &lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Then &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I should see &amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;No Results&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Behind the scenes, SpecFlow matches the Gherkin sentences to methods using regular expressions, which then drives the browser using &lt;a href="http://seleniumhq.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Selenium&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; backed by &lt;a href="http://code.google.com/p/selenium/wiki/ChromeDriver" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ChromeDriver&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for speed. For example, the following code drives navigation:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&amp;gt; paths = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&amp;gt; { { &lt;span style="color:#e6db74"&gt;&amp;#34;Home Page&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt; } };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; appUrl = &lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:51553&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[Given(@&amp;#34;I am on the &amp;#34;&amp;#34;(.*)&amp;#34;&amp;#34;&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; GivenIAmOnThe(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; name)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.WhenIGoTo(name);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[When(@&amp;#34;I go to the &amp;#34;&amp;#34;(.*)&amp;#34;&amp;#34;&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; WhenIGoTo(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; name)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; path;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (!paths.TryGetValue(name, &lt;span style="color:#66d9ef"&gt;out&lt;/span&gt; path))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ScenarioContext.Current.Pending();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SeleniumDriver.NavigateTo(appUrl + path);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note that if the path does not exist, yet the test is marked as pending and not failing - this allows us to write the specifications ahead of the actual code. We can of course also interact with the page:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[When(@&amp;#34;I set &amp;#34;&amp;#34;(.*)&amp;#34;&amp;#34; to &amp;#34;&amp;#34;(.*)&amp;#34;&amp;#34;&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; WhenISetField(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; field, &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SeleniumDriver.SetTextBoxValue(field, text);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Following &lt;a href="https://github.com/jnicklas/capybara" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Capybara&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, the code backing this will attempt to find the element by its id or the text of the label referencing the input element. This style of locating elements shows how we can write our tests from a user point of view. Another such example is finding text on a page:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[Then(@&amp;#34;I should see &amp;#34;&amp;#34;(.*)&amp;#34;&amp;#34;&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; ThenIShouldSee(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; textIndex = SeleniumDriver.PageSource.IndexOf(text, StringComparison.InvariantCulture);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Assert.IsTrue(textIndex &amp;gt;= &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Could not find text \&amp;#34;&amp;#34;&lt;/span&gt; + text + &lt;span style="color:#e6db74"&gt;&amp;#34;\&amp;#34; in the document.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With these tests, keep them &lt;a href="http://en.wikipedia.org/wiki/Don&amp;amp;#39;t_repeat_yourself" target="_blank" rel="noopener noreferrer" class="external-link"&gt;DRY&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; by composing bigger steps out of little steps. This also helps us to stay in sync with the &lt;a href="http://domaindrivendesign.org/node/132" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ubiquitous language&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[When(@&amp;#34;I search for &amp;#34;&amp;#34;(.*)&amp;#34;&amp;#34;&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; WhenISearchFor(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; what)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; steps.WhenISetField(&lt;span style="color:#e6db74"&gt;&amp;#34;Search For&amp;#34;&lt;/span&gt;, what);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.WhenIClickSearch();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[When(@&amp;#34;I click &amp;#34;&amp;#34;Search&amp;#34;&amp;#34;&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; WhenIClickSearch()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SeleniumDriver.ClickButton(&lt;span style="color:#e6db74"&gt;&amp;#34;Search&amp;#34;&lt;/span&gt;, driver =&amp;gt; driver.FindSingleElement(&lt;span style="color:#e6db74"&gt;&amp;#34;searchHeading&amp;#34;&lt;/span&gt;).IsVisible());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;For any kind of test to be repeatable, we need to have full control over the environment. This might entail setting up data, or even mocking out certain components in the application. Notice the setting up of the dataset for all of the tests:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Cucumber&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-cucumber" data-lang="cucumber"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Given &lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I have the following fruit available:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Name&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Banana&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Pear&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Kiwi&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Watermelon&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Orange&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Naartjie&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Lemon&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;span style="color:#e6db74"&gt; Apple&lt;/span&gt;&lt;span style="color:#66d9ef"&gt; |&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In this example I&amp;rsquo;ve used the fantastic &lt;a href="http://blog.stevensanderson.com/2010/03/09/deleporter-cross-process-code-injection-for-aspnet/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Deleporter&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; library to reach into the running application and change its&amp;rsquo; internals. This trick comes in useful when mocking dependencies that are difficult to control, like external web services.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;[Given(@&amp;#34;I have the following fruit available:&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; GivenIHaveTheFollowingFruitAvailable(Table table)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Fruit[] fruit = table.Rows.Select(x =&amp;gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Fruit { Name = x[&lt;span style="color:#e6db74"&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;] }).ToArray();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Deleporter.Run(() =&amp;gt; Fruit.SetFruit(fruit));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;My initial impression of SpecFlow has been great. It&amp;rsquo;s also nice to bring a little of the Ruby tooling into my day to day .NET work . I&amp;rsquo;m now trying it out on a much bigger project - stay tuned for lessons learned.&lt;/p&gt;
&lt;h2 id="further-reading" class="heading-anchor"&gt;Further Reading&lt;a href="#further-reading" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Some of this code is based on the official MVC example - you can find a complete example (and more) in the &lt;a href="https://github.com/techtalk/SpecFlow-Examples" target="_blank" rel="noopener noreferrer" class="external-link"&gt;repository&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Almost every platform has an implementation of Cucumber - see the list of implementations &lt;a href="https://github.com/cucumber/cucumber/wiki/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. On the Java platform, &lt;a href="http://jbehave.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;JBehave&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is pretty good.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/tY1QwoLAJQ4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Jared Erondu&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/bridge?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Saving the environment with Vagrant</title><link>https://riaan.hanekom.io/2012/05/23/saving-the-environment-with-vagrant/</link><pubDate>Wed, 23 May 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/05/23/saving-the-environment-with-vagrant/</guid><description>&lt;p&gt;I&amp;rsquo;ve been playing with &lt;a href="http://vagrantup.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Vagrant&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, an easy way to set up virtual machines for development purposes. Vagrant provides a simple command line interface paired with a setup script (VagrantFile) in Ruby to &lt;a href="http://vagrantup.com/docs/getting-started/boxes.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;provision virtual machines&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, share folders between the host and the virtual machine and to provide &lt;a href="http://vagrantup.com/docs/getting-started/ports.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;port forwarding&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. I&amp;rsquo;ve been using it to set up some Linux development environments on Windows, as well as for keeping my development machine clean, and running different versions of otherwise incompatible packages/gems.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve been playing with &lt;a href="http://vagrantup.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Vagrant&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, an easy way to set up virtual machines for development purposes. Vagrant provides a simple command line interface paired with a setup script (VagrantFile) in Ruby to &lt;a href="http://vagrantup.com/docs/getting-started/boxes.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;provision virtual machines&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, share folders between the host and the virtual machine and to provide &lt;a href="http://vagrantup.com/docs/getting-started/ports.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;port forwarding&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. I&amp;rsquo;ve been using it to set up some Linux development environments on Windows, as well as for keeping my development machine clean, and running different versions of otherwise incompatible packages/gems.&lt;/p&gt;
&lt;p&gt;To illustrate how easy Vagrant makes this process, let us set up a &lt;a href="http://lucene.apache.org/solr/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Solr&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; development environment. After &lt;a href="http://downloads.vagrantup.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;downloading and installing Vagrant&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, we can initialise a project with the &lt;em&gt;init&lt;/em&gt; command :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This command creates a VagrantFile with some Ruby code in it that acts as configuration for your virtual machine. Vagrant builds a virtual machine from a &lt;a href="http://vagrantup.com/docs/getting-started/boxes.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;base box&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. You can find a list of publicly available boxes &lt;a href="http://vagrantbox.es" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. For this machine, we can base it on the Ubuntu Lucid 32 bit image:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Ruby&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# -*- mode: ruby -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# vi: set ft=ruby :&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;Vagrant&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Config&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;config&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;box &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;lucid32&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;box_url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;http://files.vagrantup.com/lucid32.box&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;!-- more --&gt;
&lt;p&gt;That&amp;rsquo;s all you need for a complete virtual machine. Running the &lt;em&gt;up&lt;/em&gt; command will create and initialise it:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ vagrant up
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Importing base box &lt;span style="color:#e6db74"&gt;&amp;#39;lucid32&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Matching MAC address &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; NAT networking...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Clearing any previously set forwarded ports...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Forwarding ports...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; -- 22 &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&amp;gt; &lt;span style="color:#ae81ff"&gt;2222&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;adapter 1&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Creating shared folders metadata...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Clearing any previously set network interfaces...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Booting VM...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; VM to boot. This can take a few minutes.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; VM booted and ready &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; use!
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Mounting shared folders...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;default&lt;span style="color:#f92672"&gt;]&lt;/span&gt; -- v-root: /vagrant
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Vagrant imported the hard drives from an existing box in my profile - if you have not downloaded the &lt;em&gt;lucid32&lt;/em&gt; box before, it will happen on initialisation.&lt;/p&gt;
&lt;p&gt;Note the port forwarding bit in the snippet above. Vagrant makes it easy to forward network traffic from a port on the host to one on the virtual machine - by default it will create a forwarding port 2222 to forward traffic to SSH port 22. On operating systems that come with SSH, Vagrant can open an SSH session to the box by using the &lt;em&gt;ssh&lt;/em&gt; command:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant ssh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Since SSH is not shipped with Windows out of the box, the &lt;em&gt;ssh&lt;/em&gt; command is not available on that platform:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;vagrant ssh&lt;span style="color:#e6db74"&gt;`&lt;/span&gt; isn&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;t available on the Windows platform. You are still able
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;to SSH into the virtual machine &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; you get a Windows SSH client &lt;span style="color:#f92672"&gt;(&lt;/span&gt;such as
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PuTTY&lt;span style="color:#f92672"&gt;)&lt;/span&gt;. The authentication information is shown below:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Host: 127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Port: &lt;span style="color:#ae81ff"&gt;2222&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Username: vagrant
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Private key: C:/Users/&lt;span style="color:#f92672"&gt;[&lt;/span&gt;user&lt;span style="color:#f92672"&gt;]&lt;/span&gt;/.vagrant.d/insecure_private_key&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Windows users can use &lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Putty&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (or any other SSH client) to connect to the virtual machine with the private key provided. Vagrant automatically shares the current folder between the host and the virtual machine:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant@lucid32:~$ cd /vagrant/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant@lucid32:/vagrant$ ls
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Vagrantfile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant@lucid32:/vagrant$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We now have a functional Ubuntu machine with sudo access to it, but we still need to customize it for our development purposes. Vagrant integrates well with &lt;a href="http://puppetlabs.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Puppet&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="http://www.opscode.com/chef/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Chef&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; to install software and to manage it. In the enterprise you could integrate this with your existing Puppet or Chef infrastructure, enabling you to create a clone of your production environment. In this example we&amp;rsquo;ll use Puppet to set up Solr running in a Tomcat container. We&amp;rsquo;ll create a directory called &amp;ldquo;modules&amp;rdquo; to hold pre-developed puppet modules, and a directory called &amp;ldquo;manifests&amp;rdquo; to hold our manifest. We need to point Vagrant to the manifest and the modules directory.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Ruby&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;provision &lt;span style="color:#e6db74"&gt;:puppet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt;puppet&lt;span style="color:#f92672"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; puppet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;manifests_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;manifests&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; puppet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;manifest_file &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;solr_tomcat.pp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; puppet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;module_path &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;modules&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We need to ensure a package refresh (aka &lt;em&gt;apt-get update&lt;/em&gt;) to install the solr-tomcat package - there&amp;rsquo;s a good example of how to do that &lt;a href="http://johnleach.co.uk/words/771/puppet-dependencies-and-run-stages" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. After we&amp;rsquo;ve added the package dependency, our manifest file looks like this:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Puppet&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-puppet" data-lang="puppet"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;apt&lt;/span&gt; {&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;exec&lt;/span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;apt-update&amp;#34;&lt;/span&gt;:&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;command&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/usr/bin/apt-get update&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; # Ensure apt is setup before running apt-get update&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Apt&lt;/span&gt;::&lt;span style="color:#a6e22e"&gt;Key&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Exec&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;apt-update&amp;#34;&lt;/span&gt;]&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Apt&lt;/span&gt;::&lt;span style="color:#a6e22e"&gt;Source&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Exec&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;apt-update&amp;#34;&lt;/span&gt;]&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; # Ensure apt-get update has been run before installing any packages&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Exec&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;apt-update&amp;#34;&lt;/span&gt;] &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;Package&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;|&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&amp;gt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;package&lt;/span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#39;solr-tomcat&amp;#39;&lt;/span&gt;:&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ensure&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;present&lt;/span&gt;,&lt;span style="color:#960050;background-color:#1e0010"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;vagrant reload&lt;/em&gt; will reboot our machine and apply the configuration, and we should have Tomcat installed with Solr running on top of it. By adding the following line to our VagrantFile, we can get Vagrant to forward all communication from our local port 8181 on the host to the VM port 8080 where Tomcat is listening:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Ruby&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;forward_port &lt;span style="color:#ae81ff"&gt;8080&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;8181&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;When you go to &lt;a href="http://localhost:8181/solr/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;http://localhost:8181/solr/&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; in your local browser, you should now see Solr up and running, congratulations! Now all that&amp;rsquo;s left is to share some files between the guest and host operating systems, specifically the configuration files in &lt;em&gt;/etc/solr/conf&lt;/em&gt;. Vagrant shares the project folder with the guest OS by default under the directory &lt;em&gt;/vagrant&lt;/em&gt;. Let&amp;rsquo;s start by copying the files we want to the host machine.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd /etc/solr/conf/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir /vagrant/solr
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cp -R * /vagrant/solr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Once we have the files locally, we can mount this local directory over the one in the VM by adding this line to the VagrantFile :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Ruby&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;config&lt;span style="color:#f92672"&gt;.&lt;/span&gt;vm&lt;span style="color:#f92672"&gt;.&lt;/span&gt;share_folder &lt;span style="color:#e6db74"&gt;&amp;#34;solr&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/etc/solr/conf&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;solr&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can reload the virtual machine by running &lt;em&gt;vagrant reload&lt;/em&gt;. You are now able to do some Solr development while maintaining a clean running environment for your indexes. Best of all, you should now be able to reproduce the environment reliably, so you can feel free to experiment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/uVX0tmFdNEg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Katy Belcher&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/key?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Now blogging on Octopress</title><link>https://riaan.hanekom.io/2012/05/05/now-blogging-on-octopress/</link><pubDate>Sat, 05 May 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/05/05/now-blogging-on-octopress/</guid><description>&lt;p&gt;A week ago, I wrote :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sigh, I can&amp;rsquo;t seem to make up my mind about the platform to host my blog on. You can find my new blog over at &amp;lt;www.riaanhanekom.com&amp;gt;.&lt;/p&gt;
&lt;p&gt;Will post the details soon over there. This blog will self-destruct in a week or so.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My first blog was at &lt;a href="http://www.blogger.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Blogger&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, back when Google just bought it. What pained me then, was the lack of control - I couldn&amp;rsquo;t customize it to do what I wanted it too. After that, I tried &lt;a href="http://ienumerable.wordpress.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Wordpress&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, where I was happy for some time but the workflow of editing posts in html or via the rich text editor didn&amp;rsquo;t work out - I realised that I was spending more time formatting posts (images, code, etc.) then writing them.&lt;/p&gt;</description><content:encoded>&lt;p&gt;A week ago, I wrote :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sigh, I can&amp;rsquo;t seem to make up my mind about the platform to host my blog on. You can find my new blog over at &amp;lt;www.riaanhanekom.com&amp;gt;.&lt;/p&gt;
&lt;p&gt;Will post the details soon over there. This blog will self-destruct in a week or so.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My first blog was at &lt;a href="http://www.blogger.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Blogger&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, back when Google just bought it. What pained me then, was the lack of control - I couldn&amp;rsquo;t customize it to do what I wanted it too. After that, I tried &lt;a href="http://ienumerable.wordpress.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Wordpress&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, where I was happy for some time but the workflow of editing posts in html or via the rich text editor didn&amp;rsquo;t work out - I realised that I was spending more time formatting posts (images, code, etc.) then writing them.&lt;/p&gt;
&lt;p&gt;This drove me to &lt;a href="http://riaanhanekom.posterous.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Posterous&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, where I could write in &lt;a href="http://daringfireball.net/projects/markdown/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markdown&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, have &lt;a href="https://gist.github.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;gist&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; support, and &lt;a href="http://howdoi.posterous.com/how-to-get-the-most-out-of-posting-by-email" target="_blank" rel="noopener noreferrer" class="external-link"&gt;post by email&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. This helped me to blog more regularly since it lowered the friction in posting considerably. There were some bugs here and there, but nothing too dramatic. Over time, I was more and more convinced that I should move again due to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Death by a thousand paper cuts - little features that &lt;em&gt;worked&lt;/em&gt; in other blogging platforms were not functional (or plain non-existent) in Posterous.&lt;/li&gt;
&lt;li&gt;The &lt;a href="http://blog.posterous.com/big-news" target="_blank" rel="noopener noreferrer" class="external-link"&gt;acquisition of Posterous by Twitter&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; puts the platform at risk of stagnating.&lt;/li&gt;
&lt;li&gt;Lack of control (again).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve decided to host my own instance of a blogging platform that I can control. This blog is now running on &lt;a href="http://octopress.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Octopress&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, the &amp;ldquo;blogging framework for hackers&amp;rdquo;, and I&amp;rsquo;ve never been happier.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;It features :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Built on &lt;a href="http://github.com/mojombo/jekyll" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Jekyll&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, the blog aware static site generator. There is nothing dynamic about the content served - these pages have been pre-rendered as static html files. This makes it &lt;em&gt;fast&lt;/em&gt; and &lt;em&gt;easy to scale&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;An awesome starter template that looks well on mobile and desktop. Easy to customize, override, and replace.&lt;/li&gt;
&lt;li&gt;Supports &lt;a href="http://daringfireball.net/projects/markdown/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markdown&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="http://www.textism.com/tools/textile/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Textile&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Personally I prefer writing in Markdown, but Textile is also a viable alternative to HTML.&lt;/li&gt;
&lt;li&gt;A bunch of &lt;a href="http://octopress.org/docs/plugins/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;plugins&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and &lt;a href="http://liquidmarkup.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Liquid templating&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; support.&lt;/li&gt;
&lt;li&gt;A collection of custom Rake tasks to help with previewing, generating and creating content.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Revision control support comes out of the box with &lt;a href="http://riaanhanekom.com/2012/03/25/moving-to-git" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; once you clone the &lt;a href="https://github.com/imathis/octopress" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Octopress repository&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. This is useful in versioning and restoring posts (and the entire site, including styles and plugins), but also serves as a backup in &lt;a href="http://www.codinghorror.com/2009/12/international-backup-awareness-day.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;case of emergency&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For writing posts, I now have a much more minimalistic toolset. I use &lt;a href="http://www.vim.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Vim&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, with the &lt;a href="https://github.com/carlhuda/janus" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Janus pack&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; to provide markdown support and much more. To test rendering of Markdown, I use &lt;a href="https://github.com/nelstrom/vim-markdown-preview" target="_blank" rel="noopener noreferrer" class="external-link"&gt;vim-markdown-preview&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - a simple [:Mm] command brings up a browser with the rendered html.&lt;/p&gt;
&lt;p&gt;When pushing to my remote git repository a git hook clones the repository, generates the site, and copies the static files to where it gets served from - rudimentary &lt;a href="http://martinfowler.com/articles/continuousIntegration.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;CI&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for blogging.&lt;/p&gt;
&lt;p&gt;Octopress is truly the blogging platform for hackers. I think I&amp;rsquo;ll stick with it for a while.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/gp8BLyaTaA0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Thomas Lefebvre&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Moving to Git</title><link>https://riaan.hanekom.io/2012/03/25/moving-to-git/</link><pubDate>Sun, 25 Mar 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/03/25/moving-to-git/</guid><description>&lt;p&gt;&lt;a href="http://git-scm.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Git&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, the distributed source control system is fast becoming the de facto standard, at least in the open source arena. Although it comes with a bit of a learning curve, the advantages of using Git over more traditional SCMs like Subversion and TFS far outweighs the investment of time necessary to learn it.&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;a href="http://git-scm.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Git&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, the distributed source control system is fast becoming the de facto standard, at least in the open source arena. Although it comes with a bit of a learning curve, the advantages of using Git over more traditional SCMs like Subversion and TFS far outweighs the investment of time necessary to learn it.&lt;/p&gt;
&lt;h2 id="tldr" class="heading-anchor"&gt;TL;DR&lt;a href="#tldr" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A quick introduction to Git, with a basic command reference. If you are familiar with Git, you probably won&amp;rsquo;t learn anything new. If not, please continue reading.&lt;/p&gt;
&lt;h2 id="the-pros-and-cons" class="heading-anchor"&gt;The Pros and cons&lt;a href="#the-pros-and-cons" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Why switch to Git?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s fast. Repository history is stored locally, so we can diff and traverse history at a whim without having to involve the server.&lt;/li&gt;
&lt;li&gt;Cheap local branches. Ever wanted to branch per feature? Git is your friend.&lt;/li&gt;
&lt;li&gt;Merges are almost magical. Git does a much better job of merging than any other SCM I&amp;rsquo;ve seen.&lt;/li&gt;
&lt;li&gt;Since commits are done locally, you can commit as often as you like. Because history for your local repository can be rewritten, commits become more of a checkpoint than something permanent.&lt;/li&gt;
&lt;li&gt;Awesome command line flow. Although Git has plenty of commands available, you need a couple to get the job done on a daily basis. Git integrates well with various command line and GUI tools, and you can jump to the GUI for more complex operations like merging.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The downside to Git is with binary assets - if you store and change binary assets in your repository, it will grow to an unwieldy size. An alternative way to manage binary files with git is using &lt;a href="http://git-annex.branchable.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git-annex&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. See &lt;a href="http://stackoverflow.com/questions/540535/managing-large-binary-files-with-git" target="_blank" rel="noopener noreferrer" class="external-link"&gt;this Stack Overflow question&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for details.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="getting-started" class="heading-anchor"&gt;Getting started&lt;a href="#getting-started" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;On Linux operating systems, use your favourite package manager to install the git client. On Windows, the easiest way to get Git is to install &lt;a href="http://code.google.com/p/gitextensions/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;GitExtensions&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, which installs &lt;a href="http://code.google.com/p/msysgit/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;msysgit&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://kdiff3.sourceforge.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;kdiff&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Putty&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; or &lt;a href="http://www.openssh.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;openssh&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. GitExtensions also includes Visual Studio integration which is useful every now and then.&lt;/p&gt;
&lt;p&gt;Git on Windows runs in Git bash, which is &lt;a href="http://www.gnu.org/software/bash/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;bash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; ported to Windows. For something that feels more native to the Windows platform, &lt;a href="https://github.com/dahlbyk/posh-git" target="_blank" rel="noopener noreferrer" class="external-link"&gt;PoshGit&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; allows for functional usage of Git inside a &lt;a href="http://en.wikipedia.org/wiki/Windows_PowerShell" target="_blank" rel="noopener noreferrer" class="external-link"&gt;PowerShell&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; shell. &lt;a href="http://code.google.com/p/tortoisegit/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TortoiseGit&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (based on the popular &lt;a href="http://tortoisesvn.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TortoiseSvn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) integrates Git functions into Windows Explorer, allowing you to drive Git in a more graphical way. For browsing the history of a repository, &lt;a href="http://lostechies.com/joshuaflanagan/2010/09/03/use-gitk-to-understand-git/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;gitk&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on Windows (should come installed with Git Extensions), and &lt;a href="http://gitready.com/advanced/2009/07/31/tig-the-ncurses-front-end-to-git.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;tig&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on Debian based systems can provide a graphical way of performing this task.&lt;/p&gt;
&lt;p&gt;Avoiding the command line and relying on the GUI for driving Git makes you miss out on the cross-platform experience, and means that you will need to drop down to an uncomfortable place for some of the more advanced operations, so I highly recommend starting out at the command line and using the GUI pieces for convenience where it makes sense.&lt;/p&gt;
&lt;h2 id="where-to-get-help" class="heading-anchor"&gt;Where to get help&lt;a href="#where-to-get-help" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Git has an awesome built-in help system, accessed by calling&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &amp;ndash;&lt;a href="http://schacon.github.com/git/git-help.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;help&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can get help on specific commands by adding the &lt;strong&gt;&amp;ndash;help&lt;/strong&gt; parameter after the command :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git add &amp;ndash;&lt;a href="http://schacon.github.com/git/git-help.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;help&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="basic-commands" class="heading-anchor"&gt;Basic commands&lt;a href="#basic-commands" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;At its most basic Git works like more traditional SCMs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://gitref.org/remotes/#fetch" target="_blank" rel="noopener noreferrer" class="external-link"&gt;pull&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pulls down the latest version of the source code from the remote repository, and merges it into the current working set.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://gitref.org/remotes/#push" target="_blank" rel="noopener noreferrer" class="external-link"&gt;push&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pushes (commits) the locally performed commits to the remote repository. After it&amp;rsquo;s been pushed, other team members can pull your changes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://gitref.org/basic/#add" target="_blank" rel="noopener noreferrer" class="external-link"&gt;add&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; -A
git &lt;a href="http://gitref.org/basic/#commit" target="_blank" rel="noopener noreferrer" class="external-link"&gt;commit&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; -m &amp;ldquo;My detailed commit message.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Git has the concept of a &lt;a href="http://gitready.com/beginner/2009/01/18/the-staging-area.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;staging area&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, which is a holding area for the changes that you would like to commit. The &lt;strong&gt;add&lt;/strong&gt; command adds either a specific file to the staging area, or all detected changes with the &lt;strong&gt;-A&lt;/strong&gt; parameter.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;commit&lt;/strong&gt; command performs a local commit, while the &lt;strong&gt;-m&lt;/strong&gt; parameter specifies a message for the commit. If the &lt;strong&gt;-m&lt;/strong&gt; parameter is not provided, Git will open up a text editor for you to edit the commit message.&lt;/p&gt;
&lt;p&gt;Should a pull or a push result in merge conflicts, you can start a manual merge process by running the following command :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://gitguru.com/2009/02/22/integrating-git-with-a-visual-merge-tool/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;mergetool&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To view the history of the repository, you can query the log via&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://gitref.org/branching/#log" target="_blank" rel="noopener noreferrer" class="external-link"&gt;log&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The commands above is all you need to get started with Git - once you get those under your belt, the true power of this distributed source control provider can kick in with some more advanced commands.&lt;/p&gt;
&lt;h2 id="more-advanced-usage" class="heading-anchor"&gt;More advanced usage&lt;a href="#more-advanced-usage" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;One of the features I like most about Git is its cheap, local branches. With these, there is no reason not to branch for even the simplest change. To create a new branch and switch to it, run the following :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://linux.die.net/man/1/git-checkout" target="_blank" rel="noopener noreferrer" class="external-link"&gt;checkout&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; -b &amp;ldquo;newbranch&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;strong&gt;-b&lt;/strong&gt; parameter lets Git know to create a new branch, with name &lt;strong&gt;newbranch&lt;/strong&gt;. Change and commit as normal, and when you are ready to merge back into the master (trunk in traditional terms), you can do the following to merge the changes in :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://linux.die.net/man/1/git-checkout" target="_blank" rel="noopener noreferrer" class="external-link"&gt;checkout&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; master
git &lt;a href="http://linux.die.net/man/1/git-merge" target="_blank" rel="noopener noreferrer" class="external-link"&gt;merge&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; newbranch&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can then delete the branch if not needed any more:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://linux.die.net/man/1/git-branch" target="_blank" rel="noopener noreferrer" class="external-link"&gt;branch&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; -d newbranch&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Because the repository is local, switching branches is fast and painless - unlike more traditional SCM&amp;rsquo;s that need to talk to the server to achieve this.&lt;/p&gt;
&lt;p&gt;Git does not like having uncommitted changes lying around between operations like branching and merging. Git provides a &amp;ldquo;stashing&amp;rdquo; mechanism where it temporarily stores away changes that you can reapply later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://book.git-scm.com/4_stashing.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;stash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; save &amp;ldquo;stashname&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Saves the current changes into a stash with the specified name, and check outs the most recent commit on that branch. You can run&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://book.git-scm.com/4_stashing.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;stash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; apply&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To apply these changes to the file set again.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://book.git-scm.com/4_rebasing.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Rebase&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is worthy of &lt;a href="http://gitready.com/intermediate/2009/01/31/intro-to-rebase.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;its own post&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - there is so much power in being able to rewrite history.&lt;/p&gt;
&lt;h2 id="using-git-with-other-source-control-systems" class="heading-anchor"&gt;Using Git With Other Source Control Systems&lt;a href="#using-git-with-other-source-control-systems" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;If for some reason, you can&amp;rsquo;t use Git on the server, you might still be able to use it on the client. Git works well with other source control systems like &lt;a href="http://en.wikipedia.org/wiki/Team_Foundation_Server" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TFS&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and &lt;a href="http://subversion.tigris.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Subversion&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; through the use of plugins. Git integrates with these SCM&amp;rsquo;s by &amp;ldquo;cloning&amp;rdquo; the remote repository locally, and then pushing local changes back to the remote servers when needed.&lt;/p&gt;
&lt;p&gt;For TFS support, after installing &lt;a href="http://git-tfs.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git-tfs&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, you&amp;rsquo;ll have access to the following commands :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://git-tfs.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;tfs&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; clone &lt;a href="http://tfs:8080/tfs/collection" target="_blank" rel="noopener noreferrer" class="external-link"&gt;http://tfs:8080/tfs/collection&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; $/project_name&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Clones the project with the specified name contained in that collection.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://git-tfs.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;tfs&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; checkintool&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Brings up the check in tool with the changes available to commit to TFS.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://git-tfs.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;tfs&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; shelve name&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Creates a shelve set with the changes since the last commit to TFS.&lt;/p&gt;
&lt;p&gt;Integrating with Subversion works in a similar way - with the &lt;a href="http://schacon.github.com/git/git-svn.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git-svn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; package you can perform the following operations :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://schacon.github.com/git/git-svn.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;svn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; clone [repositoryurl]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Creates a &amp;ldquo;cloned&amp;rdquo; local Git repository based of the remote Subversion repository. In the local repository, Subversion commits become Git commits.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://schacon.github.com/git/git-svn.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;svn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; rebase&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Performs an update, and rebases your change sets on top of it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git &lt;a href="http://schacon.github.com/git/git-svn.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;svn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; dcommit&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Takes your Git commits and streams your changes to the Subversion server.&lt;/p&gt;
&lt;h2 id="tips-and-tricks" class="heading-anchor"&gt;Tips and tricks&lt;a href="#tips-and-tricks" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;When I started out with Git, it took me a while to realize that some of the situations I ran into resulted from me not adhering to the &lt;a href="http://sandofsky.com/git-workflow.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git workflow&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. I recommend reading up on it before you do any serious work with Git.&lt;/p&gt;
&lt;p&gt;If you have a complex release strategy, it will be worth your time to familiarize yourself with &lt;a href="https://github.com/nvie/gitflow" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git-flow&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and the &lt;a href="http://nvie.com/posts/a-successful-git-branching-model/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;successful branching model&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; behind it.&lt;/p&gt;
&lt;p&gt;Also learn what &lt;em&gt;git pull&lt;/em&gt; does, and read up about why &lt;em&gt;git fetch&lt;/em&gt; &lt;a href="http://longair.net/2009/04/16/git-fetch-and-merge/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;works better&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="making-learning-fun" class="heading-anchor"&gt;Making learning fun&lt;a href="#making-learning-fun" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Git, being a power tool, is feature rich. For encouragement on exploring all it&amp;rsquo;s features, and to make the learning process fun I recommend these two tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/icefox/git-achievements" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git-achievements&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; tracks your usage of features, and unlocks &amp;ldquo;achievements&amp;rdquo;, much like &lt;a href="http://stackoverflow.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Stack Overflow&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; badges.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Gazler/githug" target="_blank" rel="noopener noreferrer" class="external-link"&gt;githug&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (Linux and macOS) provides a game like environment where you perform specific operations to get to the next level. Levels vary in difficulty, so this is a great way of exercising your Git chops.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="further-reading" class="heading-anchor"&gt;Further reading&lt;a href="#further-reading" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://gitready.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Git ready&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; provides clear explanations of git features, and some more advanced tweaks.&lt;/li&gt;
&lt;li&gt;The &lt;a href="http://book.git-scm.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;git book&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is the official, community driven reference for Git.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/3igHRe7QTdg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Caleb Jones&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/bridge?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>How Small is Small Enough</title><link>https://riaan.hanekom.io/2012/02/27/how-small-is-small-enough/</link><pubDate>Mon, 27 Feb 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/02/27/how-small-is-small-enough/</guid><description>&lt;p&gt;As developers, we are good at breaking up components into sub-components - sometimes excessively so. When confronted with a larger than average chunk of work, we make a choice: either consider the work as indivisible to be delivered in its entirety, or break it up smaller pieces. Most of us already experience a sense of foreboding when confronted with a piece of work that is too large. Whether you are estimating in hours or &lt;a href="https://riaan.hanekom.io/2012/02/13/the-humble-story-point/"&gt;in story points&lt;/a&gt; the question is: when breaking up work items into smaller pieces - how small is small enough?&lt;/p&gt;</description><content:encoded>&lt;p&gt;As developers, we are good at breaking up components into sub-components - sometimes excessively so. When confronted with a larger than average chunk of work, we make a choice: either consider the work as indivisible to be delivered in its entirety, or break it up smaller pieces. Most of us already experience a sense of foreboding when confronted with a piece of work that is too large. Whether you are estimating in hours or &lt;a href="https://riaan.hanekom.io/2012/02/13/the-humble-story-point/"&gt;in story points&lt;/a&gt; the question is: when breaking up work items into smaller pieces - how small is small enough?&lt;/p&gt;
&lt;h2 id="delivering-software-one-piece-at-a-time" class="heading-anchor"&gt;Delivering software, one piece at a time&lt;a href="#delivering-software-one-piece-at-a-time" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;By now, we know that the best way to write software is to evolve it bit by bit. Doing work in small chunks allows us to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;free our minds of details that are not relevant to the here and now&lt;/li&gt;
&lt;li&gt;make small, certain steps towards a goal&lt;/li&gt;
&lt;li&gt;measure progress as soon as it happens&lt;/li&gt;
&lt;li&gt;get feedback as soon as possible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Too much of a good thing can also be bad for you - too few small tasks could cause the overhead of managing these tasks to become significant in itself, and measuring progress could become a nightmare. Also, when estimating on fine-grained (low-level) tasks, &lt;a href="http://www.informit.com/articles/article.aspx?p=102317&amp;amp;seqNum=6" target="_blank" rel="noopener noreferrer" class="external-link"&gt;local safety&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; becomes a problem.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="how-small-is-small-enough" class="heading-anchor"&gt;How small is small enough?&lt;a href="#how-small-is-small-enough" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;One way of determining the appropriate size for a piece of work could be to link it to the notion of testability - the smallest piece of functionality that could be finished and pushed through the delivery pipeline. This approach produces too fine-grained work items, linked to their technical implementation.&lt;/p&gt;
&lt;p&gt;Rather, a story should represent a single piece of &lt;a href="http://www.chiefsimplicityofficer.com/2011/07/user-story-sizing-how-small-is-small-enough/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;deliverable business value&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The rule here is to make the story as small as possible, yet that it retains some measurable amount of intrinsic value - something that, when demonstrated to the end users, they&amp;rsquo;ll agree is an improvement to the system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can test work item size by looking at the value delivered:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Conversely, if you break a story into two pieces, but there is no value to be had until both pieces are completed, then that is too small. The stories should be recombined - or split another way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="optimizing-the-flow" class="heading-anchor"&gt;Optimizing the flow&lt;a href="#optimizing-the-flow" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Consider also the idea of single piece flow. In &lt;a href="http://www.pqa.net/ProdServices/leanmfg/1-pieceFlow.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;manufacturing terms&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Single piece flow is the ideal state where parts are manufactured one at a time, and flow throughout the manufacturing and supply chain as a single unit, transferred as customers order.&lt;/p&gt;
&lt;p&gt;Manufacturing large batches of parts simultaneously, or accumulating parts in a bin for shipping or transferring 2 or more parts at the same time is opposite or contrasted to the definition of Single Piece Flow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The idea is that large batches of work (&lt;a href="http://en.wikipedia.org/wiki/Waterfall_model" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the waterfall way&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) equate to rework (waste), inventory (also considered waste), and delayed delivery time (loss of profit). There are times when work items should not be split up into smaller pieces. Since the existence of software is solely linked to profit (businesses &lt;em&gt;do&lt;/em&gt; want to make money, don&amp;rsquo;t they?), it makes sense to &lt;a href="http://www.poppendieck.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;optimize for flow and profitability&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; by&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sharing setup costs, that is, group items where setup cost can be shared, and&lt;/li&gt;
&lt;li&gt;maximizing flow by minimizing batch size.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When breaking work into chunks, you must strike a careful balance between the two.&lt;/p&gt;
&lt;p&gt;​&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/DwpmtAo01fY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Céline Haeberly&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/small?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>The Humble Story Point</title><link>https://riaan.hanekom.io/2012/02/13/the-humble-story-point/</link><pubDate>Mon, 13 Feb 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/02/13/the-humble-story-point/</guid><description>&lt;p&gt;I&amp;rsquo;ve had some interesting discussions on the management of work through user stories. A lot of teams, those starting to use agile techniques, seem to have some uncertainty around common topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The theory behind story points and why they are preferred over estimations in hours&lt;/li&gt;
&lt;li&gt;Why story points and velocity are self-correcting measures&lt;/li&gt;
&lt;li&gt;The sizing process and appropriate sizes for stories&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The problems with sizing in units of time&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve had the opportunity of working on some waterfall projects. I feel blessed to have been in these teams because I now recognize that:&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve had some interesting discussions on the management of work through user stories. A lot of teams, those starting to use agile techniques, seem to have some uncertainty around common topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The theory behind story points and why they are preferred over estimations in hours&lt;/li&gt;
&lt;li&gt;Why story points and velocity are self-correcting measures&lt;/li&gt;
&lt;li&gt;The sizing process and appropriate sizes for stories&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The problems with sizing in units of time&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve had the opportunity of working on some waterfall projects. I feel blessed to have been in these teams because I now recognize that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most estimations in hours are thumb-sucked. Given that &lt;a href="https://riaan.hanekom.io/2012/01/29/complexity-in-software/"&gt;software development is a complex beast&lt;/a&gt;, how can we possibly forecast time to be spent on a specific task in an accurate fashion?&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Work_breakdown_structure" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Work break down structures&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; are frequently used to aid in estimations, even though they exasperate inaccuracies of estimation at lower levels.&lt;/li&gt;
&lt;li&gt;As teams typically contain members at different skill levels, how long a task takes depends on which members of the team actually do the work. An estimate based on time does not make sense in this context.&lt;/li&gt;
&lt;li&gt;Traditional project management focuses on getting projects on time, sometimes sending teams on a death march and severely compromising on quality.&lt;/li&gt;
&lt;li&gt;Waterfall based software teams are held to inaccurate estimations. The &lt;a href="http://en.wikipedia.org/wiki/Gantt_chart" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Gantt chart&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; proves to be inflexible as the focus of the traditional project manager is on staying true to the original plan.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It should be obvious that I&amp;rsquo;m not a big believer in time-based estimations. Apart from the above, one should also watch out for the problem of &lt;a href="http://www.informit.com/articles/article.aspx?p=102317&amp;amp;seqNum=6" target="_blank" rel="noopener noreferrer" class="external-link"&gt;local safety&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If asked how long a small task will take, a developer will naturally not want to deliver it late. After all, this is a small task, it should be on time or the developer wouldn&amp;rsquo;t be professional. Hence, the estimate will include a buffer to absorb the developer&amp;rsquo;s uncertainty about the task.&lt;/p&gt;
&lt;p&gt;The estimate given by the developer will depend on how confident that developer is that he has understood the task and knows how to perform it. If there is uncertainty in the understanding of the task, then the estimated time to completion is likely to be significantly longer. No one wants to be late with such a small task.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!-- more --&gt;
&lt;p&gt;The &lt;a href="http://www.informit.com/store/product.aspx?isbn=0131424602" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Agile Management for Software Engineering&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; book also describes the need for a &amp;ldquo;relative&amp;rdquo; estimation method :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Accurate project planning techniques must avoid asking developers to estimate small tasks based on effort. The tasks to be performed must be broken out based on some form of (relative) complexity and risk. To work best, this requires a codification scheme for assessing the complexity and risk. An analysis method that enables small pieces of client-valued functionality to be codified for complexity or risk is required. This enables the inventory in the system of software production to be estimated without the psychological effect of local safety.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We have an alternate estimation method available in the form of story points. Jeff Sutherland explains &lt;a href="http://scrum.jeffsutherland.com/2010/04/story-points-why-are-they-better-than.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;why story points are better than hourly estimates&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The way we do story point estimation gives better estimates than hourly estimates as they are more accurate and have less variation. A CMMI Level 5 company determined that story point estimation cuts estimation time by 80% allowing teams to do more estimation and tracking than a typical waterfall team. A telecoms company noticed that estimated story points with planning poker was 48 times faster than waterfall estimation practices in the company and gave as good or better estimates.&lt;/p&gt;
&lt;p&gt;Story points are therefore faster, better, and cheaper than hours and the highest performing teams completely abandon any hourly estimation as they view it as waste that just slows them down.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Measures that work for the team&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Given that story points are better than time-based measures, what is the unit of a story point? The most common sizing measures are &lt;a href="http://www.brighthub.com/office/project-management/articles/22847.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;T-Shirt sizing&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (S, M, L, XL), and the &lt;a href="http://en.wikipedia.org/wiki/Fibonacci_number" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Fibonacci series&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (1, 2, 3, 5, 8, 13, 21, 34).&lt;/p&gt;
&lt;p&gt;I prefer having less numbers to choose from since we can complete sizing faster by eliminating debate on the exact size of a story. My vote goes to the limited Fibonacci sequence (1, 2, 3, 5, 8), also in use by one of my &lt;a href="http://pivotaltracker.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;favourite online tracking tools&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. I&amp;rsquo;m not impartial to the other estimation units though - even a simple scale of (1, 2, 3) could be of use to a team.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It&amp;rsquo;s all about averages&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Points are about &lt;a href="http://blog.mountaingoatsoftware.com/its-effort-not-complexity" target="_blank" rel="noopener noreferrer" class="external-link"&gt;effort, not complexity&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. A team&amp;rsquo;s &lt;a href="http://www.versionone.com/Agile101/velocity.asp" target="_blank" rel="noopener noreferrer" class="external-link"&gt;velocity&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is the amount of points completed in a sprint. Based on the velocity of the team in a previous sprint, we can forecast the amount of work the team should be able to do in a following sprint with reasonable certainty.&lt;/p&gt;
&lt;p&gt;Velocity and story points are based on the environment and members of the team. A new addition to the team, for example, might change the definition of a story point, and will have a direct effect on the team&amp;rsquo;s velocity. An awesome property of velocity and story points though, is that they are self-correcting measures. Since the team&amp;rsquo;s workload is derived from them, it will also adjust accordingly to any change in the team or environment. Wrong estimates also tend to average out - while we underestimate some stories, we also overestimate others.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Estimating in story points&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With story points being an arbitrary measurement, how do we estimate in a consistent manner? There is no hard answer to this, except that you get a &amp;ldquo;feel&amp;rdquo; for the effort represented by a story point. The definition of a story point is unique per team, and it will take a while before a team synchronizes on the magnitude of a story point.&lt;/p&gt;
&lt;p&gt;For teams new to story points, Chris Sims &lt;a href="http://blog.technicalmanagementinstitute.com/2009/06/story-sizing-a-better-start-than-planning-poker.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;details an approach to sizing&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; by sorting stories according to size that will make it easy to get started.&lt;/p&gt;
&lt;p&gt;One can also try creating a personalised relative scale for points, with reference to previous/familiar work. For example, the following scale might be used to size stories :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Adding a button to a page&lt;/li&gt;
&lt;li&gt;A form with a single text box, required validation.&lt;/li&gt;
&lt;li&gt;A form with various inputs, required validation, saved to the database.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And so forth. &lt;a href="https://twitter.com/#!/checkrath" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Craig Heckrath&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; introduced me to this technique, and it seems to work well in teams new to agile.&lt;/p&gt;
&lt;p&gt;More experienced teams tend to play &lt;a href="http://planningpoker.com/detail.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;planning poker&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; since it&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;limits discussion and gets stories sized faster&lt;/li&gt;
&lt;li&gt;keeps everyone in the team contributing to the discussion&lt;/li&gt;
&lt;li&gt;is fun!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More on story sizing later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/aHoHjaLWayk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;sydney Rae&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/number?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Complexity in Software</title><link>https://riaan.hanekom.io/2012/01/29/complexity-in-software/</link><pubDate>Sun, 29 Jan 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/01/29/complexity-in-software/</guid><description>&lt;p&gt;In a discussion with &lt;a href="https://twitter.com/#!/KeaganPhillips" target="_blank" rel="noopener noreferrer" class="external-link"&gt;a former colleague of mine&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on the organization of components and on system boundaries, we focused on the complexity inherent to software building. It hit me that we can learn from physics here.&lt;/p&gt;
&lt;h2 id="the-law" class="heading-anchor"&gt;The law&lt;a href="#the-law" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The &lt;a href="http://en.wikipedia.org/wiki/First_law_of_thermodynamics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;first law of thermodynamics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; states that&lt;/p&gt;</description><content:encoded>&lt;p&gt;In a discussion with &lt;a href="https://twitter.com/#!/KeaganPhillips" target="_blank" rel="noopener noreferrer" class="external-link"&gt;a former colleague of mine&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on the organization of components and on system boundaries, we focused on the complexity inherent to software building. It hit me that we can learn from physics here.&lt;/p&gt;
&lt;h2 id="the-law" class="heading-anchor"&gt;The law&lt;a href="#the-law" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The &lt;a href="http://en.wikipedia.org/wiki/First_law_of_thermodynamics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;first law of thermodynamics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; states that&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;energy can be transformed, i.e. changed from one form to another, but cannot be created or destroyed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This law, in my mind, can be applied to software development broadly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Complexity in software&lt;/em&gt; can be transformed, i.e. changed from one form to another, but cannot be created or destroyed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was about to make this law my own, but on writing this I found that another named this &lt;a href="http://madbean.com/2003/mb2003-43" target="_blank" rel="noopener noreferrer" class="external-link"&gt;back in 2003&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Matt&amp;rsquo;s first law of software complexity states :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The underlying complexity of a given problem is constant.&lt;/strong&gt; It can be hidden, but it does not go away.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Or:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Complexity is conserved by abstractions.&lt;/strong&gt; In fact, apparent complexity can be increased by abstractions, but the underlying complexity can never be reduced.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!-- more --&gt;
&lt;h2 id="why-manage-complexity" class="heading-anchor"&gt;Why manage complexity?&lt;a href="#why-manage-complexity" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The way we construct software is influenced on all levels by complexity. Yes, user requirements, even functional requirements drive us towards a certain design when building software - but any requirement introduces further complexity that we need to manage. A software developer&amp;rsquo;s primary role is to &lt;em&gt;manage complexity&lt;/em&gt; to provide anything useful.&lt;/p&gt;
&lt;p&gt;In short, complexity&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;makes software more difficult to write&lt;/li&gt;
&lt;li&gt;makes software more difficult to maintain&lt;/li&gt;
&lt;li&gt;makes it almost impossible to communicate intent to a fellow programmer (or the next)&lt;/li&gt;
&lt;li&gt;makes it progressively more difficult to construct larger components out of smaller ones.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-is-complexity-in-software-development" class="heading-anchor"&gt;What is complexity in software development?&lt;a href="#what-is-complexity-in-software-development" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;When looking at the complexity problem, it might be useful to identify categories of complexity when looking at components. I&amp;rsquo;m veering away from the academic classifications here to make this discussion more practical.&lt;/p&gt;
&lt;p&gt;For any working component in a system, that is, a subsection of a software application that is useful, we might look at&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Internal complexity&lt;/em&gt; : complexity contained by the component, either caused by the implementation of the component itself or inherited by its integration with subcomponents.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;External complexity&lt;/em&gt; : complexity leaked outside the component&amp;rsquo;s interface. Other components will inherit this complexity when interfacing with or containing this component.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When looking at a system (a component in itself), we can also identify&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Local complexity&lt;/em&gt; : the complexity in understanding a specific component/piece of functionality&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Global complexity&lt;/em&gt; : the complexity in understanding the system in its entirety - all the interactions between the different components within.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="techniques-for-managing-complexity" class="heading-anchor"&gt;Techniques for managing complexity&lt;a href="#techniques-for-managing-complexity" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Since software development has a lot to do with managing complexity, various techniques have sprung up over the years to help manage it. Too many techniques exist to list here as we could argue that even the move to higher-level languages had complexity as its primary motivation.&lt;/p&gt;
&lt;p&gt;A helper in managing complexity in recent years has been &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Object Orientation (OO)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, with the concept of &lt;a href="http://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;encapsulation&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; stopping the spread of complexity outside a component. Internally and externally, OO has taught us to reduce &lt;a href="http://en.wikipedia.org/wiki/Coupling_%28computer_programming%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;coupling&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and maximize &lt;a href="http://en.wikipedia.org/wiki/Cohesion" target="_blank" rel="noopener noreferrer" class="external-link"&gt;cohesion&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. These two principles are the underpinning of most (all?) complexity management techniques in this paradigm.&lt;/p&gt;
&lt;p&gt;Related to encapsulation is the idea of service boundaries and a &lt;a href="http://domaindrivendesign.org/node/91" target="_blank" rel="noopener noreferrer" class="external-link"&gt;bounded context&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Service boundaries cut off complexity at a specific point, and provide a simple, well-thought out contract to interact with a module, thereby reducing the surface area of interactions with it and hiding the complexity within a module. A bounded context helps identify models to keep separate to avoid complexity.&lt;/p&gt;
&lt;p&gt;A more technical technique to reduce complexity in a codebase is to apply the &lt;a href="http://martinfowler.com/articles/injection.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Inversion of Control&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; / &lt;a href="http://hanekom.pro/dependency-injection-the-what-and-the-how" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Dependency Injection&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; pattern/technique. It promotes simplicity in classes, and reduces coupling between components. The former pushes down local complexity - we can zoom in and understand a single component, change it, or replace it - but the latter causes an increase in global complexity since the system is more difficult to understand in it&amp;rsquo;s entirety, and it becomes more difficult to identify all the execution paths in a system.&lt;/p&gt;
&lt;p&gt;If this technique pushes up one category of complexity, why use it? My theory is that global complexity favours the &lt;em&gt;maintenance&lt;/em&gt; phase over the &lt;em&gt;development&lt;/em&gt; phase. In the development phase the focus is on the creation of code - major components are designed and created, and we are expected to have a clear vision of the system in its whole (we have to deliver this thing, don&amp;rsquo;t we?). In the maintenance phase, we generally make smaller changes, and the focus is on &amp;ldquo;zooming in&amp;rdquo; to an appropriate level to fix, refurbish, or replace components to serve a new purpose. DI makes sense since the maintenance phase accounts for most of the effort put into a software product.&lt;/p&gt;
&lt;h2 id="other-techniques-for-managing-complexity" class="heading-anchor"&gt;Other techniques for managing complexity&lt;a href="#other-techniques-for-managing-complexity" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;In &lt;a href="http://madbean.com/2003/mb2003-43" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Matt&amp;rsquo;s post&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; he points out an underused strategy - if the problem is complex, it might be possible to redefine the problem and sidestep that complexity entirely.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.extremeprogramming.org/rules/simple.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Do the simplest thing possible&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Your customers will love you for it.&lt;/p&gt;
&lt;h2 id="further-reading" class="heading-anchor"&gt;Further reading&lt;a href="#further-reading" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://sunnyday.mit.edu/16.355/kearney.pdf" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Software Complexity Measurement (pdf)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; makes the concept of complexity more tangible and discusses the selection process and application of complexity measurements.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.acis.pamplin.vt.edu/faculty/tegarden/wrk-pap/DSS.PDF" target="_blank" rel="noopener noreferrer" class="external-link"&gt;A Software Complexity Model of Object-Oriented Systems (pdf)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; provides a good overview on the different measurements for techniques in OO.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/l5Tzv1alcps?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Alex wong&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/building?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Greener pastures</title><link>https://riaan.hanekom.io/2012/01/13/greener-pastures/</link><pubDate>Fri, 13 Jan 2012 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2012/01/13/greener-pastures/</guid><description>&lt;p&gt;This post is more than two months late, but I&amp;rsquo;ve been at &lt;a href="http://www.dstvo.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;DStv Online&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; since November 2011.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.intervate.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Intervate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has been great to me, and is still on my recommended list of employers. I experienced significant growth there, and I thank them for that - but with consideration of some quality of life issues I&amp;rsquo;ve been having, and a need to stretch my skill set, I&amp;rsquo;ve decided to move on.&lt;/p&gt;</description><content:encoded>&lt;p&gt;This post is more than two months late, but I&amp;rsquo;ve been at &lt;a href="http://www.dstvo.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;DStv Online&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; since November 2011.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.intervate.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Intervate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has been great to me, and is still on my recommended list of employers. I experienced significant growth there, and I thank them for that - but with consideration of some quality of life issues I&amp;rsquo;ve been having, and a need to stretch my skill set, I&amp;rsquo;ve decided to move on.&lt;/p&gt;
&lt;p&gt;So far, I&amp;rsquo;ve found my new environment stimulating and challenging. I&amp;rsquo;ve spent most of my career in finance (aka banks) - the media industry is new to me so I&amp;rsquo;m learning a lot there. The people are eager to experiment and learn on both technical and process levels, and I can say that I have never felt at home so fast at any of my previous jobs. &lt;a href="http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=5JjhX-NVavU" target="_blank" rel="noopener noreferrer" class="external-link"&gt;This video&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; shows the kind of environment they have.&lt;/p&gt;
&lt;p&gt;Some perks :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exciting, pioneering work. Not (as a friend put it) writing Excel over and over again.&lt;/li&gt;
&lt;li&gt;Public facing sites. You know that &amp;ldquo;What do you do for a living?&amp;rdquo; question? I have an answer for people who are not complete geeks. I can &lt;em&gt;show&lt;/em&gt; them.&lt;/li&gt;
&lt;li&gt;I work close to my house. No highway travelling. Period. No sitting in traffic. I might even downgrade to one of &lt;a href="http://www.bigboyscooters.co.za" target="_blank" rel="noopener noreferrer" class="external-link"&gt;these&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; soon.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nothing like some change.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/1rZcfdsjoR4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Fré Sonneveld&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/road?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Blog moved</title><link>https://riaan.hanekom.io/2011/12/17/blog-moved/</link><pubDate>Sat, 17 Dec 2011 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2011/12/17/blog-moved/</guid><description>&lt;p&gt;In preparation for my recurring new years resolution of updating this blog, I&amp;rsquo;ve followed the &lt;a href="http://simoncropp.com/why-i-moved-my-blog-to-posterous" target="_blank" rel="noopener noreferrer" class="external-link"&gt;advice of Simon Cropp&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and moved my &lt;a href="http://ienumerable.wordpress.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;old blog&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; to &lt;a href="http://riaanhanekom.posterous.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Posterous&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.  &lt;/p&gt;</description><content:encoded>&lt;p&gt;In preparation for my recurring new years resolution of updating this blog, I&amp;rsquo;ve followed the &lt;a href="http://simoncropp.com/why-i-moved-my-blog-to-posterous" target="_blank" rel="noopener noreferrer" class="external-link"&gt;advice of Simon Cropp&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and moved my &lt;a href="http://ienumerable.wordpress.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;old blog&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; to &lt;a href="http://riaanhanekom.posterous.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Posterous&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;If you subscribe to my &lt;a href="http://feeds.feedburner.com/BinaryThoughts" target="_blank" rel="noopener noreferrer" class="external-link"&gt;FeedBurner feed&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, there should be no changes necessary from your side to receive updates from me.  Please update any other bookmarks to my site.&lt;/p&gt;
&lt;p&gt;Wordpress has served me well, but has become a bit of an antiquity when compared to some of the modern blogging platforms. The features Posterous provides are encouraging.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s to a new year of fresh content!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/r593e2EAyHg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Nathan Anderson&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/road?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Feature request for SQL Server Management Studio</title><link>https://riaan.hanekom.io/2010/09/30/feature-request-for-sql-server-management-studio/</link><pubDate>Thu, 30 Sep 2010 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2010/09/30/feature-request-for-sql-server-management-studio/</guid><description>&lt;p&gt;A &lt;em&gt;&amp;ldquo;You sure you want to do this?&amp;rdquo;&lt;/em&gt; confirmation when you attempt to run a query that contains a destructive update (delete/update) without a where clause.   With &lt;a href="http://stackoverflow.com/questions/281339/confirm-before-delete-update-in-sql-management-studio" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the hoards of database tables getting wiped&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; in the world, why hasn&amp;rsquo;t this been implemented yet?  This feature would remove a lot of fear of pressing F5.&lt;/p&gt;</description><content:encoded>&lt;p&gt;A &lt;em&gt;&amp;ldquo;You sure you want to do this?&amp;rdquo;&lt;/em&gt; confirmation when you attempt to run a query that contains a destructive update (delete/update) without a where clause.   With &lt;a href="http://stackoverflow.com/questions/281339/confirm-before-delete-update-in-sql-management-studio" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the hoards of database tables getting wiped&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; in the world, why hasn&amp;rsquo;t this been implemented yet?  This feature would remove a lot of fear of pressing F5.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Those who are not afraid running a delete query on a production database haven&amp;rsquo;t lived long enough yet.  On a similar note, those who trust their code still need to experience taking down a couple of servers with it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/fPkvU7RDmCo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Caspar Rubin&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/sql?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Just Finished Reading (Lean Edition)</title><link>https://riaan.hanekom.io/2010/07/11/just-finished-reading-lean-edition/</link><pubDate>Sun, 11 Jul 2010 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2010/07/11/just-finished-reading-lean-edition/</guid><description>&lt;p&gt;&lt;a href="http://www.amazon.com/Lean-Software-Development-Agile-Toolkit/dp/0321150783" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;strong&gt;Lean Software Development : An Agile Toolkit&lt;/strong&gt;, Mary Poppendieck and Tom Poppendieck&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.   A great resource on how the lean principles from product manufacturing can be applied unto software development.  You can find a good overview in their 2002 paper &lt;a href="http://www.poppendieck.com/papers/LeanThinking.pdf" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here (pdf)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and the &lt;a href="http://en.wikipedia.org/wiki/Lean_software_development" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Wikipedia article on Lean&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;a href="http://www.amazon.com/Lean-Software-Development-Agile-Toolkit/dp/0321150783" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;strong&gt;Lean Software Development : An Agile Toolkit&lt;/strong&gt;, Mary Poppendieck and Tom Poppendieck&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.   A great resource on how the lean principles from product manufacturing can be applied unto software development.  You can find a good overview in their 2002 paper &lt;a href="http://www.poppendieck.com/papers/LeanThinking.pdf" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here (pdf)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and the &lt;a href="http://en.wikipedia.org/wiki/Lean_software_development" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Wikipedia article on Lean&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2 id="overview" class="heading-anchor"&gt;Overview&lt;a href="#overview" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Each chapter in the book describes &lt;a href="http://www.poppendieck.com/ld.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&amp;ldquo;thinking tools&amp;rdquo; for the 7 Lean Principles&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Eliminate waste&lt;/strong&gt; describes how to identity and remove waste to maximize the flow of the value stream.
&lt;ul&gt;
&lt;li&gt;Seeing Waste&lt;/li&gt;
&lt;li&gt;Value Stream Mapping&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amplify learning&lt;/strong&gt; emphasizes how short feedback cycles can improve the resulting product and development process.
&lt;ul&gt;
&lt;li&gt;Feedback&lt;/li&gt;
&lt;li&gt;Iterations&lt;/li&gt;
&lt;li&gt;Synchronization&lt;/li&gt;
&lt;li&gt;Set-based development&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decide as late as possible&lt;/strong&gt; to deal with uncertainty, and make better decisions.
&lt;ul&gt;
&lt;li&gt;Options thinking&lt;/li&gt;
&lt;li&gt;The last responsible moment&lt;/li&gt;
&lt;li&gt;Decision making&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deliver as fast as possible&lt;/strong&gt; to enable late decision making, and produce value as fast as we can.
&lt;ul&gt;
&lt;li&gt;Pull systems&lt;/li&gt;
&lt;li&gt;Queuing theory&lt;/li&gt;
&lt;li&gt;Cost of delay&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Empower the team&lt;/strong&gt; to make use of the expertise that lies with the people that do the work.
&lt;ul&gt;
&lt;li&gt;Self-determination&lt;/li&gt;
&lt;li&gt;Motivation&lt;/li&gt;
&lt;li&gt;Leadership&lt;/li&gt;
&lt;li&gt;Expertise&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build integrity in&lt;/strong&gt; to accommodate change and increase the period of usefulness of a product.
&lt;ul&gt;
&lt;li&gt;Perceived integrity&lt;/li&gt;
&lt;li&gt;Conceptual integrity&lt;/li&gt;
&lt;li&gt;Refactoring&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;See the whole&lt;/strong&gt; warns against sub-optimization, and provides tools for keeping the bigger picture in mind.
&lt;ul&gt;
&lt;li&gt;Measurements&lt;/li&gt;
&lt;li&gt;Contracts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Books on process take me longer to get through than those dealing with technical topics – with the density of information in some of the chapters, this one was no exception.  It’s a real eye-opener though and comes highly recommended for those wishing to improve their software development process, even for those in non-agile environments.&lt;/p&gt;
&lt;h2 id="what-to-read-if-you-are-in-a-hurry" class="heading-anchor"&gt;What to read if you are in a hurry&lt;a href="#what-to-read-if-you-are-in-a-hurry" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The part on &lt;a href="http://en.wikipedia.org/wiki/Queuing_theory" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Queuing Theory&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is informative and captures the substance of the book well.  More on this later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/yzVxz_OYVxU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Aliis Sinisalu&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/kindle?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Dependency injection - the what and the how</title><link>https://riaan.hanekom.io/2010/07/04/dependency-injection-the-what-and-the-how/</link><pubDate>Sun, 04 Jul 2010 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2010/07/04/dependency-injection-the-what-and-the-how/</guid><description>&lt;p&gt;&lt;em&gt;Background:  We’ve started a weekly patterns &amp;amp; practices meeting at work with some of our senior developers where our discussions and actions will hopefully bring some  improvement to the current development environment.  Once a week one of us has an opportunity to showcase a new topic – much akin to knowledge transfer session but more fine-grained and at a higher level than the technology.  &lt;a href="http://blogs.netdev.co.za/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Gareth Stephenson&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; suggested we blog about the content for the benefit of others, which I think is a good idea.  Furthermore, I’ve never been able to find a good, down-to-earth resource that explains the benefits of DI and how to get started with it.  This post is a recording of a short presentation I performed on DI and the patterns that emerge in its usage – I hope it proves useful.&lt;/em&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;em&gt;Background:  We’ve started a weekly patterns &amp;amp; practices meeting at work with some of our senior developers where our discussions and actions will hopefully bring some  improvement to the current development environment.  Once a week one of us has an opportunity to showcase a new topic – much akin to knowledge transfer session but more fine-grained and at a higher level than the technology.  &lt;a href="http://blogs.netdev.co.za/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Gareth Stephenson&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; suggested we blog about the content for the benefit of others, which I think is a good idea.  Furthermore, I’ve never been able to find a good, down-to-earth resource that explains the benefits of DI and how to get started with it.  This post is a recording of a short presentation I performed on DI and the patterns that emerge in its usage – I hope it proves useful.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="net-developers-dont-do-patterns" class="heading-anchor"&gt;.NET Developers don’t do patterns&lt;a href="#net-developers-dont-do-patterns" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A surprising number of .NET developers are not familiar with &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Dependency Injection (DI)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and patterns in general.  In the Java world, File –&amp;gt; New Project would give you a template with &lt;a href="http://www.springsource.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Spring&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; baked in – when working with .NET  that kind of guidance is missing from the toolset.  Perhaps some exposure to &lt;a href="http://mef.codeplex.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;MEF&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; with .NET 4.0 will entice .NET developers to look further than the Microsoft toolset, in the same way that &lt;a href="http://msdn.microsoft.com/en-us/library/aa697427%28VS.80%29.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Entity Framework&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; exposed most developers to &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ORM&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&amp;rsquo;s with &lt;a href="http://sourceforge.net/projects/nhibernate/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NHibernate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; getting some adoption as a result. DI and &lt;a href="http://martinfowler.com/articles/injection.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Inversion of Control&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; go hand-in-hand, but be careful not to confuse the two – DI is a tool, whereas Inversion of Control is a pattern.&lt;/p&gt;
&lt;h2 id="a-world-filled-with-legacy-code" class="heading-anchor"&gt;A World filled with legacy code&lt;a href="#a-world-filled-with-legacy-code" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We’ll get to why we would use a container soon, but consider the following code in the meanwhile:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OrderPlacementService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Process(Order order) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// For a big order, notify somebody important&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (order.Amount &amp;gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; SmsSender.SendSms(&lt;span style="color:#e6db74"&gt;&amp;#34;0113334444&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Pretty big order received.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Actually process the order&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Order processed.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SmsSender&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; SendSms(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; number, &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Sent sms \&amp;#34;{0}\&amp;#34; to number \&amp;#34;{1}\&amp;#34;.&amp;#34;&lt;/span&gt;, text, number);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;!-- more --&gt;
&lt;p&gt;The important parts that denote processing represent themselves as writes to standard output.  This code is typical of legacy systems, and even some systems currently under development.  It suffers from the following problems related to coupling and cohesion :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://corfield.org/entry/Static_is_Evil" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Static classes and calls to static members increase the coupling between classes and makes the code harder to change, and reduces testability&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Violation of the &lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Open/Closed Principle&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (&lt;a href="http://www.objectmentor.com/resources/articles/ocp.pdf" target="_blank" rel="noopener noreferrer" class="external-link"&gt;pdf&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) forces us to change the service when we want to change the notification functionality.&lt;/li&gt;
&lt;li&gt;Violation of the &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Single Responsibility Principle&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (&lt;a href="http://www.objectmentor.com/resources/articles/srp.pdf" target="_blank" rel="noopener noreferrer" class="external-link"&gt;pdf&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) by handling order processing, business rules and notifications makes the service more fragile by introducing reasons for change.&lt;/li&gt;
&lt;li&gt;Calls to concrete classes and violation of the &lt;a href="http://en.wikipedia.org/wiki/Dependency_inversion_principle" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Dependency Inversion principle&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (&lt;a href="http://www.objectmentor.com/resources/articles/dip.pdf" target="_blank" rel="noopener noreferrer" class="external-link"&gt;pdf&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) maximizes coupling between completely unrelated pieces of code.&lt;/li&gt;
&lt;li&gt;Resembles &lt;a href="http://en.wikipedia.org/wiki/Procedural_programming" target="_blank" rel="noopener noreferrer" class="external-link"&gt;procedural programming&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; making it difficult to plug code in and out without affecting anything else.&lt;/li&gt;
&lt;li&gt;The above makes the code inherently &lt;a href="http://en.wikipedia.org/wiki/Software_testability" target="_blank" rel="noopener noreferrer" class="external-link"&gt;untestable&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; – we cannot test the code without sending an SMS.  Keeping in mind that we would wish to run our tests as frequently as possible, a test that costs money is not the best idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using a DI framework changes the way you code by solving the problem of constructing objects and the provision of dependencies – it makes it possible to decouple your implementations from one another, thereby improving your code by making it more amendable to testing and more amendable to change.  Before we introduce a DI framework to the sample code above, we need to make some improvements to it.&lt;/p&gt;
&lt;h2 id="improving-the-existing-code" class="heading-anchor"&gt;Improving the existing code&lt;a href="#improving-the-existing-code" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We start off by removing any static calls by making SendSms an instance member. This will allow us to replace SmsSender with a test object (&lt;a href="http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;test double, mock, or a stub&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) to test it.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ISmsSender&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; SendSms(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; number, &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; text);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SmsSender&lt;/span&gt; : ISmsSender
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; SendSms(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; number, &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; text)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Sent sms \&amp;#34;{0}\&amp;#34; to number \&amp;#34;{1}\&amp;#34;.&amp;#34;&lt;/span&gt;, text, number);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We can then write the OrderService class in a cleaner way to reduce the dependency on a concrete implementation of an SMS sender:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OrderPlacementService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; ISmsSender smsSender;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; OrderPlacementService(ISmsSender smsSender)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.smsSender = smsSender;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Process(Order order) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// For a big order, notify somebody important&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (order.Amount &amp;gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; smsSender.SendSms(&lt;span style="color:#e6db74"&gt;&amp;#34;0113334444&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Pretty big order received.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Actually process the order&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Order processed.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Notice the effects this simple change has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We&amp;rsquo;re using inversion of control to &amp;ldquo;push&amp;rdquo; the dependency to the caller, thus relieving ourselves of responsibility of it.&lt;/li&gt;
&lt;li&gt;Our &lt;em&gt;OrderPlacementService&lt;/em&gt; now explicitly states the dependencies that it needs to function properly by requiring an &lt;em&gt;ISmsSender&lt;/em&gt; as a constructor parameter.&lt;/li&gt;
&lt;li&gt;Since we’re not interested in the concrete implementation of an SmsSender,  we’ve replaced the concrete dependency with an interface.  We care about the What (contract), not the Who (concrete type) or the How (actual implementation details).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="a-sample-implementation" class="heading-anchor"&gt;A Sample implementation&lt;a href="#a-sample-implementation" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The calling code must now provide the dependency to the &lt;em&gt;OrderService&lt;/em&gt;.  For example :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Main(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; orderPlacementService = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; OrderPlacementService(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; SmsSender());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Placing small order...&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; orderPlacementService.Process(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Order { Amount = &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Placing big order...&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; orderPlacementService.Process(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Order { Amount = &lt;span style="color:#ae81ff"&gt;700&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Done.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.ReadLine();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Running the code above provides the following output:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="image.jpg" alt="Console output" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 id="providing-extension-points" class="heading-anchor"&gt;Providing extension points&lt;a href="#providing-extension-points" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We can improve the code even more by abstracting at a slightly higher level, and removing the knowledge of the order amount condition (greater than 500) and the resulting action (sending an SMS) from the service by introducing an extension point and moving the logic to a custom extension :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IInterceptor&lt;/span&gt;&amp;lt;T&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Intercept(T item);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IOrderInterceptor&lt;/span&gt; : IInterceptor&amp;lt;Order&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;LargeOrderInterceptor&lt;/span&gt; : IOrderInterceptor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; ISmsSender smsSender;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; LargeOrderInterceptor()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; : &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; SmsSender())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; LargeOrderInterceptor(ISmsSender smsSender)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.smsSender = smsSender;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Intercept(Order order)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (order.Amount &amp;gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; smsSender.SendSms(&lt;span style="color:#e6db74"&gt;&amp;#34;0113334444&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Pretty big order received.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With the interceptor interface in place, our code for our &lt;em&gt;OrderService&lt;/em&gt; is greatly simplified :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;OrderPlacementService&lt;/span&gt; : IOrderPlacementService {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; IOrderInterceptor orderInterceptor;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; OrderPlacementService(IOrderInterceptor orderInterceptor)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.orderInterceptor = orderInterceptor;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Process(Order order)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; orderInterceptor.Intercept(order);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Actually process the order&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Order processed.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="enough-dependencies-to-go-around" class="heading-anchor"&gt;Enough dependencies to go around&lt;a href="#enough-dependencies-to-go-around" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Our calling program needs to provide the appropriate dependencies :  &lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; orderPlacementService = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; OrderPlacementService(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; LargeOrderInterceptor(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; SmsSender()));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and now another problem emerges.  Firstly, it’s a real pain to have to provide the dependencies for &lt;em&gt;OrderPlacementService&lt;/em&gt; (and it’s dependencies) by hand.  The bigger problem here is that we’ll be violating &lt;a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank" rel="noopener noreferrer" class="external-link"&gt;DRY&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; if the service gets used in more than one place, which it’s bound to be.  Coupling increases since every object that has a dependency on &lt;em&gt;OrderPlacementService&lt;/em&gt; would have a direct dependency on the &lt;em&gt;LargeOrderInterceptor&lt;/em&gt; and &lt;em&gt;SmsSender&lt;/em&gt; classes, which denotes a violation of the Single Responsibility Principle.   The classic solution for this problem is to make use of the Factory pattern in order for this knowledge to be in one place (and thus changed with ease if the need arises):&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IServiceFactory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IOrderPlacementService GetOrderPlacementService();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServiceFactory&lt;/span&gt; : IServiceFactory
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; IOrderPlacementService GetOrderPlacementService()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; OrderPlacementService(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; LargeOrderInterceptor(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; SmsSender()));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;##Factories Are Not The Solution&lt;/p&gt;
&lt;p&gt;Using the Factory pattern in this case has it’s own sets of problems :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dependency Replacement :&lt;/strong&gt; While we got rid of the dependency on &lt;em&gt;LargeOrderInterceptor&lt;/em&gt; and &lt;em&gt;SmsSender&lt;/em&gt;, we’ve replaced it with a dependency on &lt;em&gt;ServiceFactory&lt;/em&gt;.  &lt;em&gt;ServiceFactory&lt;/em&gt; then becomes difficult to maintain as any changes to it affects a big chunk of the codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proliferation of helper classes :&lt;/strong&gt; Splitting the &lt;em&gt;ServiceFactory&lt;/em&gt; into smaller factories, each responsible for constructing a different object removes the hotspot, but brings to life a multitude of redundant helper classes (classes that have no real identity or well-defined purpose).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another technique called &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/07/03/how-not-to-do-dependency-injection-in-nerddinner.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Poor Man’s Dependency Injection&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; can reduce the spread of dependency knowledge by one level by creating a default constructor that injects the dependencies into a more specialized constructor.  Applying this technique to the &lt;em&gt;LargeOrderInterceptor&lt;/em&gt; would yield the following constructors :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; ISmsSender smsSender;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; LargeOrderInterceptor() : &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; SmsSender())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; LargeOrderInterceptor(ISmsSender smsSender)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.smsSender = smsSender;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Poor Man’s Dependency Injection also isn’t helpful in this regard, but it may be useful in constrained environments to increase the testability of code.&lt;/p&gt;
&lt;h2 id="dependency-injection-to-the-rescue" class="heading-anchor"&gt;Dependency injection to the rescue&lt;a href="#dependency-injection-to-the-rescue" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This is the situation where DI is helpful – it takes on the knowledge of construction and stores it in a central place, removing duplication and making it easy to change.  It provides the glue that holds an application together and allows us to create small classes isolated from each other, but working together to achieve a common goal.  You can think of a container as a simple hash table of types with interfaces mapping to concrete types.   If we ask the container for a type implementing &lt;em&gt;IFoo&lt;/em&gt;, it can construct and return a &lt;em&gt;Foo&lt;/em&gt; concrete instance.  If &lt;em&gt;Foo&lt;/em&gt; needs any dependencies, the container will construct and inject those as well.  It will construct an entire object graph without your code having any knowledge on the concrete types or the dependencies they take.  &lt;/p&gt;
&lt;p&gt;We’ll use &lt;a href="http://structuremap.sourceforge.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;StructureMap&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (one of many containers available for .NET) to illustrate. First, we need to add some code to initialize the container.  Typically, this bootstrapping code gets run whenever your application starts up in some executable bootstrapper.  Initialization of the container should add set up the container for construction of any objects that we might need during the execution of our program.  StructureMap’s fluent API makes this an easy task :  &lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;StructureMap.ObjectFactory.Initialize( x =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x.For&amp;lt;ISmsSender&amp;gt;().Use&amp;lt;SmsSender&amp;gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x.For&amp;lt;IOrderInterceptor&amp;gt;().Use&amp;lt;LargeOrderInterceptor&amp;gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x.For&amp;lt;IOrderPlacementService&amp;gt;().Use&amp;lt;OrderPlacementService&amp;gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The code above is &lt;em&gt;registering&lt;/em&gt; a type with the container.   Now, whenever we need an &lt;em&gt;OrderPlacementService&lt;/em&gt;, we ask the container to construct it for us using the &lt;a href="http://martinfowler.com/articles/injection.html#UsingAServiceLocator" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Service Locator&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; pattern :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;StructureMap.ObjectFactory.GetInstance&amp;lt;IOrderPlacementService&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And magic!  We have an usable &lt;em&gt;IOrderPlacementService:&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="image1.jpg" alt="Debug screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;In the background StructureMap matched the requested interface to a concrete type, found the greediest constructor (the one that has the most parameters), and injected the &lt;em&gt;IOrderInterceptor&lt;/em&gt; dependency into it.  The same happened to the &lt;em&gt;ISmsSender&lt;/em&gt; dependency for the interceptor.  Our code just ran without any compile time knowledge on concrete implementations for its dependencies.  We achieved both coding to interface (ignorance on concrete implementations) that reduces coupling, and solved the problem of object construction without being &lt;a href="http://books.google.co.za/books?id=sArznQV2GcIC&amp;amp;amp;amp;pg=PA362&amp;amp;amp;amp;lpg=PA362&amp;amp;amp;amp;dq=inappropriately&amp;#43;intimate&amp;amp;amp;amp;source=bl&amp;amp;amp;amp;ots=Vu4IM4YVXU&amp;amp;amp;amp;sig=Xhd4-L6ae_jwrtEiJgDNdHMTh0w&amp;amp;amp;amp;hl=en&amp;amp;amp;amp;ei=MKAvTJTxEtO7jAeepcSWBg&amp;amp;amp;amp;sa=X&amp;amp;amp;amp;oi=book_result&amp;amp;amp;amp;ct=result&amp;amp;amp;amp;resnum=3&amp;amp;amp;amp;ved=0CB0Q6AEwAg#v=onepage&amp;amp;amp;amp;q=inappropriately%20intimate&amp;amp;amp;amp;f=false" target="_blank" rel="noopener noreferrer" class="external-link"&gt;inappropriately intimate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; with them.&lt;/p&gt;
&lt;h2 id="configuring-all-your-dependencies-can-cause-blindness" class="heading-anchor"&gt;Configuring all your dependencies can cause blindness&lt;a href="#configuring-all-your-dependencies-can-cause-blindness" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Coding using all the practices discussed earlier can result in a lot of types (and registrations) in big projects -  having to update the container configuration every time you add a class can be a real pain.  To counter this, most container implementations provide a way of &lt;em&gt;Auto-Registration&lt;/em&gt; - scanning types in assemblies and registering the m automatically using certain conventions.&lt;/p&gt;
&lt;p&gt;With StructureMap, we can instruct the container to scan on initialization :  &lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ObjectFactory.Initialize( x =&amp;gt; x.Scan(scanner =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scanner.AssembliesFromPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scanner.WithDefaultConventions();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scanner.LookForRegistries();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This little snippet above has the following effects :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Let StructureMap scan all the assemblies in the application’s home directory.&lt;/li&gt;
&lt;li&gt;Register types that match the default conventions – that is, if StructureMap finds an interface &lt;em&gt;IFoo&lt;/em&gt; and a concrete implementation called &lt;em&gt;Foo,&lt;/em&gt; it will automatically register the types.  Note that we can be customize these conventions.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;LookForRegistries&lt;/em&gt; finds and adds the information contained in &lt;a href="http://structuremap.github.com/structuremap/RegistryDSL.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;registries&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.  Registries allow us to split the registration configuration in scope (for example on a namespace or assembly level).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that scanning, in our case, removed the need for us to explicitly register &lt;em&gt;ISmsSender&lt;/em&gt; and &lt;em&gt;IOrderService&lt;/em&gt; since the naming of these classes match the default conventions.  Our interceptor is not so lucky, and has to be manually registered using a registry :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DomainRegistry&lt;/span&gt; : Registry
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; DomainRegistry()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; For&amp;lt;IOrderInterceptor&amp;gt;().Use&amp;lt;LargeOrderInterceptor&amp;gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;## Containers Accommodate Change&lt;/p&gt;
&lt;p&gt;We might realise that we have the need for more interceptors to run whenever an order comes in.  We can solve this problem by using the &lt;a href="http://en.wikipedia.org/wiki/Composite_pattern" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Composite pattern&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, which allows us to treat a collection of items as a single item in the following way :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ICompositeOrderInterceptor&lt;/span&gt; : IInterceptor&amp;lt;order&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IList&amp;lt;IOrderInterceptor&amp;gt; Items { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CompositeOrderInterceptor&lt;/span&gt; : ICompositeOrderInterceptor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; CompositeOrderInterceptor(&lt;span style="color:#66d9ef"&gt;params&lt;/span&gt; IOrderInterceptor[] items)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Items = items;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Intercept(Order order)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;foreach&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; interceptor &lt;span style="color:#66d9ef"&gt;in&lt;/span&gt; Items)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; interceptor.Intercept(order);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; IList&amp;lt;IOrderInterceptor&amp;gt; Items { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With this in place, we can construct our container to add all instances of &lt;em&gt;IOrderInterceptor&lt;/em&gt; and inject the composite wherever it’s used.  Their are two distinct ways of registering types in an container. Which one to use depends on the usage and number of items of the individual types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can request the &lt;strong&gt;default implementation&lt;/strong&gt; for an interface using the Service Locator pattern.  Asking for an &lt;em&gt;IFoo&lt;/em&gt; implementation will always result in a &lt;em&gt;Foo&lt;/em&gt; instance with no further information.&lt;/li&gt;
&lt;li&gt;We can request a &lt;strong&gt;list of implementations&lt;/strong&gt; when multiple concrete implementations back an interface.  A request for &lt;em&gt;IFoo&lt;/em&gt; implementations will result in a list of instances of every type that implements &lt;em&gt;IFoo&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scanner.AddAllTypesOf&amp;lt;IOrderInterceptor&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;to our scanning and removing the default registration of &lt;em&gt;LargeOrderInterceptor&lt;/em&gt; will register all instances implementing &lt;em&gt;IOrderInterceptor.&lt;/em&gt; As a result we’ll be able to ask the container for all instances &lt;em&gt;IOrderInterceptor&lt;/em&gt; and get back a list of instances of all the concrete implementations found.    If we replace the dependency of &lt;em&gt;IOrderInterceptor&lt;/em&gt; with &lt;em&gt;ICompositeOrderInterceptor&lt;/em&gt; in our order service, we can effectively add functionality to our order service without changing a line of code in it or touching the container configuration again.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; ICompositeOrderInterceptor orderInterceptor;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; OrderPlacementService(ICompositeOrderInterceptor orderInterceptor)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.orderInterceptor = orderInterceptor;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Our &lt;em&gt;OrderPlacementService&lt;/em&gt; will not receive a composite interceptor with the known interceptors injected into it :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="image2.jpg" alt="Debugging screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;We’re taking advantage of a specific feature of StructureMap here : if you require a list or an array of items in your constructor, the container will provide all instances registered in it.   If we add another interceptor to trigger on small orders,&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SmallOrderInterceptor&lt;/span&gt; : IOrderInterceptor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Intercept(Order order)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (order.Amount &amp;gt; &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Small order!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;the container will automatically inject an instance of the new interceptor :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="image3.jpg" alt="Debugging screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Which allows us to change the behaviour of our application by &lt;strong&gt;adding&lt;/strong&gt; code and &lt;strong&gt;not modifying&lt;/strong&gt; anything.  See &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/12/17/advanced-structuremap-connecting-implementations-to-open-generic-types.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Jimmy Bogard’s post on connecting implementations to open generics types&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for a more advanced example on how containers can accommodate change in an application.&lt;/p&gt;
&lt;h2 id="different-types-of-injection" class="heading-anchor"&gt;Different types of injection&lt;a href="#different-types-of-injection" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Two distinct styles of injection are &lt;a href="http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Constructor Injection and Setter Injection&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constructor injection&lt;/strong&gt; takes dependencies using the constructor like the code above – it involves setting global variables (if necessary) to the constructor parameters to make these dependencies available for the entirety of the class.   The constructor advertises dependencies as required – you can not instantiate an object without providing it’s dependencies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setter Injection&lt;/strong&gt; provides properties for setting dependencies.  No explicit advertising of dependencies is necessary and you can instantiate a class without the required dependencies – so a set of reasonable defaults should be assumed.  This does make a class easier to instantiate, but adds the onus on the class to manage it’s default dependencies.&lt;/p&gt;
&lt;p&gt;Constructor injection is &lt;a href="http://martinfowler.com/articles/injection.html#ConstructorVersusSetterInjection" target="_blank" rel="noopener noreferrer" class="external-link"&gt;clearly&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; &lt;a href="http://structuremap.github.com/structuremap/ConstructorAndSetterInjection.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;preferred&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; over Setter Injection in most cases.  Where you can’t control the instantiation of objects (as in Web Forms), you can &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/01/16/quot-buildup-quot-existing-objects-with-structuremap.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;apply Setter Injection to the already existing object&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="you-can-do-di-wrong" class="heading-anchor"&gt;You can do DI wrong&lt;a href="#you-can-do-di-wrong" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are several anti-patterns you can get yourself into : &lt;strong&gt;Relying on the Service Locator&lt;/strong&gt; pattern effectively &lt;a href="http://initializecomponent.blogspot.com/2008/06/container-dependency-anti-pattern.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;replaces any dependencies with a dependency on the container&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, defeating the purpose somewhat.  Not only could the choice of container percolate throughout our codebase, but now any tests need to mock out the container.  Even worse is a direct dependency on a static container like &lt;em&gt;ObjectFactory&lt;/em&gt; since we can’t run tests without some shared state between them.    In some cases this querying the container direct is a necessary evil, particularly when using the container as a plugin framework. This is the most common anti-pattern I see with people getting started in DI.&lt;/p&gt;
&lt;p&gt;Containers are best called &lt;a href="http://devlicio.us/blogs/krzysztof_kozmic/archive/2010/06/20/how-i-use-inversion-of-control-containers.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;only on application initialization and resolving root components&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; with the rest of the codebase not having any explicit dependency on it. &lt;strong&gt;Too many dependencies tied to a class&lt;/strong&gt; &lt;a href="http://jeffreypalermo.com/constructor-over-injection-smell-ndash-follow-up/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;can cripple a code base, making it fragile and prone to change&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.  While the problem is not tied directly to DI, DI can help hide the pain of having too many dependencies (not a good thing). Using &lt;strong&gt;Setter injection&lt;/strong&gt; enables objects to be instantiated in an invalid state.  It also manages to tie classes directly to their dependencies through the need for reasonable defaults.&lt;/p&gt;
&lt;h2 id="but-wait-theres-more" class="heading-anchor"&gt;But wait!  There’s more&lt;a href="#but-wait-theres-more" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Dependency Injection containers have grown into much more than simple type resolvers.  Once you’re comfortable with the basics you can start investigating:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Containers typically provide some kind of &lt;strong&gt;lifecycle management&lt;/strong&gt; for constructed objects.  For example, it’s dead easy to &lt;a href="http://structuremap.github.com/structuremap/Scoping.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;configure a dependency as a singleton, or to tie it to the HttpContext&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/01/18/conditional-object-construction-in-structuremap-i-e-fun-with-lambdas.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Conditional object construction&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/01/07/advanced-structuremap-custom-registration-conventions-for-partially-closed-types.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Custom conventions for dependency registration&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://elegantcode.com/2009/12/18/advanced-unity-connecting-implementations-to-open-generic-types/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Connecting implementations to open generic types&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2010/02/10/nested-containers-in-structuremap-2-6-1.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Nested containers&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/01/21/interception-capabilities-of-structuremap-2-5.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Interception and substitution&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="a-container-implementation-for-everyone" class="heading-anchor"&gt;A container implementation for everyone&lt;a href="#a-container-implementation-for-everyone" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are several open source/freely available containers for use on .NET.  These are the most popular ones :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://structuremap.sourceforge.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;StructureMap&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;: the oldest one, and still my favourite.  Combines power with speed and an elegant Fluent API.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.castleproject.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Castle Project&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;: container is part of a suite of tools.  Powerful, but I’ve found the syntax rather hard to get started with.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.springframework.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Spring.NET&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;: not just a container, but an application framework.  Very heavy on XML configuration, but the documentation is good and enterprise support is always welcome.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ninject.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ninject&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;: lightweight container that embraces lambdas to it’s fullest.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/autofac/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;AutoFac&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://www.kenegozi.com/Blog/2008/01/17/its-my-turn-to-build-an-ioc-container-in-15-minutes-and-33-lines.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Some people&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; even &lt;a href="http://ayende.com/Blog/archive/2007/10/20/Building-an-IoC-container-in-15-lines-of-code.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;write their own&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion" class="heading-anchor"&gt;Conclusion&lt;a href="#conclusion" class="anchor-link" aria-label="Link to this section"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Probably the most challenging aspect of explaining DI is the overwhelming amount of information that comes along with it. In the last couple of years I’ve come to the conclusion that this is &lt;strong&gt;the&lt;/strong&gt; way of building applications using statically typed languages – of course, most of the principles apply to dynamic languages, but &lt;a href="http://fabiokung.com/2010/05/06/ruby-and-dependency-injection-in-a-dynamic-world/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;IOC just isn’t that big in, for example, Ruby&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/OqtafYT5kTw?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ilya Pavlov&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code-php?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Just finished reading...</title><link>https://riaan.hanekom.io/2010/06/25/just-finished-reading.../</link><pubDate>Fri, 25 Jun 2010 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2010/06/25/just-finished-reading.../</guid><description>&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.pragprog.com/titles/cfcar2/the-passionate-programmer" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Passionate Programmer: Creating a Remarkable Career in Software Development&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt; (Chad Fowler) and &lt;strong&gt;&lt;a href="http://pragprog.com/the-pragmatic-programmer" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Pragmatic Programmer&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt; (Andrew Hunt and David Thomas).&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.pragprog.com/titles/cfcar2/the-passionate-programmer" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Passionate Programmer: Creating a Remarkable Career in Software Development&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt; (Chad Fowler) and &lt;strong&gt;&lt;a href="http://pragprog.com/the-pragmatic-programmer" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Pragmatic Programmer&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt; (Andrew Hunt and David Thomas).&lt;/p&gt;
&lt;p&gt;I wish I had read &lt;em&gt;The Pragmatic Programmer&lt;/em&gt; earlier in my career as it provides a thorough overview of good practices in software development. Reading this a couple of years ago would have shortened some learning cycles.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Passionate Programmer&lt;/em&gt; is a truly inspiring book, and comes highly recommended if you&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;feel that your career is in a lull, or&lt;/li&gt;
&lt;li&gt;need guidance in evolving your career as a software developer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/67rnodKzsRQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Roman Trifonov&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/reading-?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics - new team member</title><link>https://riaan.hanekom.io/2009/10/21/ngenerics-new-team-member/</link><pubDate>Wed, 21 Oct 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/10/21/ngenerics-new-team-member/</guid><description>&lt;p&gt;A hearty welcome to David Schmitt who joined the &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; Team. David&amp;rsquo;s bio : &lt;em&gt;David is a Debian Admin and .Net Developer living and working in Vienna, Austria. He&amp;rsquo;s partner in a small tech company startup at &lt;a href="http://dasz.at/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;http://dasz.at/&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. His current interests with NGenerics is the implementation of the Immutable namespace.&lt;/em&gt; As stated in his bio, David will be working on implementing a selection of &lt;a href="http://en.wikipedia.org/wiki/Immutable_object" target="_blank" rel="noopener noreferrer" class="external-link"&gt;immutable&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; data structures.&lt;/p&gt;</description><content:encoded>&lt;p&gt;A hearty welcome to David Schmitt who joined the &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; Team. David&amp;rsquo;s bio : &lt;em&gt;David is a Debian Admin and .Net Developer living and working in Vienna, Austria. He&amp;rsquo;s partner in a small tech company startup at &lt;a href="http://dasz.at/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;http://dasz.at/&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. His current interests with NGenerics is the implementation of the Immutable namespace.&lt;/em&gt; As stated in his bio, David will be working on implementing a selection of &lt;a href="http://en.wikipedia.org/wiki/Immutable_object" target="_blank" rel="noopener noreferrer" class="external-link"&gt;immutable&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; data structures.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Lh_bn9SgRSY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/meeting?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics 1.4.1 Beta released</title><link>https://riaan.hanekom.io/2009/08/25/ngenerics-1.4.1-beta-released/</link><pubDate>Tue, 25 Aug 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/08/25/ngenerics-1.4.1-beta-released/</guid><description>&lt;p&gt;You can find it on our &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;new project site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;.&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; This build includes the following (straight from the release notes) :&lt;/p&gt;</description><content:encoded>&lt;p&gt;You can find it on our &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;new project site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;.&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; This build includes the following (straight from the release notes) :&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;New Platforms&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NGenerics now has a Silverlight version in this release targeting Silverlight 3.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New data structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Single-Valued (i.e) not KeyValuePair version of the RedBlackTree.&lt;/li&gt;
&lt;li&gt;A generic version of the priority queue that can have a key implementing IComparable, or any object with an IComparer instance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New Patterns&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added the Converter pattern under NGenerics.Patterns.Conversion.&lt;/li&gt;
&lt;li&gt;Added the Specification pattern under NGenerics.Patterns.Specification.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;New Extension Methods&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ConvertTo, Serialize, Deserialize, and DeepCopy extension on Object&lt;/li&gt;
&lt;li&gt;ForEach extension on IEnumerable&lt;T&gt;&lt;/li&gt;
&lt;li&gt;IsSimiliar extensions on double&lt;/li&gt;
&lt;li&gt;Missing list extensions in Silverlight&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Changes to existing data structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added construction mechanism to Singleton - the Singleton value can now be lazy-instantiated.&lt;/li&gt;
&lt;li&gt;Removed the IVisitable interface and added extension methods for applying a visitor over any instance of IEnumerable&lt;T&gt;. &lt;strong&gt;(*breaking change*)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Moved visitor-related classes to NGenerics.Patterns.Visitor &lt;strong&gt;(*breaking change*)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Added FindNode method to GeneralTree.&lt;/li&gt;
&lt;li&gt;The previous version of the priority queue that accepts integers as keys is now named ClassicPriorityQueue. &lt;strong&gt;(* breaking change *)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Bug Fixes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Collection Add raised in ObservableHashList instead of Remove on RemoveItem&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Misc&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lots of internal housekeeping and refactoring to up the quality of the code base.&lt;/li&gt;
&lt;li&gt;More documentation.&lt;/li&gt;
&lt;li&gt;Upgrade to Sandcastle Help File Builder 1.8.0.2 Beta.&lt;/li&gt;
&lt;li&gt;Code Coverage is now at 96%.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please log any issues on the &lt;a href="http://code.google.com/p/ngenerics/issues/list" target="_blank" rel="noopener noreferrer" class="external-link"&gt;issues list&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and feature requests on &lt;a href="http://ngenerics.uservoice.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;UserVoice&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.  For discussions, please use the &lt;a href="http://groups.google.com/group/ngenerics-users" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ngenerics-users google group&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; NGenerics is now hosted on &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;GitHub&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Skf7HxARcoc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markus Spiske&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics has moved</title><link>https://riaan.hanekom.io/2009/08/09/ngenerics-has-moved/</link><pubDate>Sun, 09 Aug 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/08/09/ngenerics-has-moved/</guid><description>&lt;p&gt;The home of NGenerics has moved to &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Google Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; from it&amp;rsquo;s &lt;a href="http://www.codeplex.com/NGenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;original project site on CodePlex&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. We&amp;rsquo;re still in the process of migrating some of the content like the downloads, but we&amp;rsquo;re mostly up and running. If you have any issues or feature suggestions, please submit them to the &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Google Code project site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;The home of NGenerics has moved to &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Google Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; from it&amp;rsquo;s &lt;a href="http://www.codeplex.com/NGenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;original project site on CodePlex&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. We&amp;rsquo;re still in the process of migrating some of the content like the downloads, but we&amp;rsquo;re mostly up and running. If you have any issues or feature suggestions, please submit them to the &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Google Code project site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;NGenerics is now hosted on GitHub &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/45FJgZMXCK8?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Joey Kyber&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/commute?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics project move update</title><link>https://riaan.hanekom.io/2009/08/09/ngenerics-project-move-update/</link><pubDate>Sun, 09 Aug 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/08/09/ngenerics-project-move-update/</guid><description>&lt;p&gt;Content migration for &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; went well - but please note the following changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All downloads for releases moved to the &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;new project site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Due to &lt;a href="http://code.google.com/p/support/issues/detail?id=2042" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Google not being willing to add the MS-PL license to Google Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, we&amp;rsquo;ve had to re-license NGenerics under the &lt;a href="http://www.gnu.org/licenses/lgpl.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;LGPL&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. LGPL is practically the same license but more wordy.&lt;/li&gt;
&lt;li&gt;A &lt;a href="http://ngenerics.uservoice.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;User Voice site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is available for feature requests - please log (and vote for) any features you would like to see in NGenerics. We&amp;rsquo;ll get to these in order of the number of votes attached to them.&lt;/li&gt;
&lt;li&gt;Discussions are now hosted on the &lt;a href="http://groups.google.com/group/ngenerics-users" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ngenerics-users Google group&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you experience any problems caused by the move, let us know by sending a message to the &lt;a href="http://groups.google.com/group/ngenerics-users" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ngenerics-users group&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; or leaving a comment to this post.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Content migration for &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; went well - but please note the following changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All downloads for releases moved to the &lt;a href="http://code.google.com/p/ngenerics/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;new project site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Due to &lt;a href="http://code.google.com/p/support/issues/detail?id=2042" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Google not being willing to add the MS-PL license to Google Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, we&amp;rsquo;ve had to re-license NGenerics under the &lt;a href="http://www.gnu.org/licenses/lgpl.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;LGPL&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. LGPL is practically the same license but more wordy.&lt;/li&gt;
&lt;li&gt;A &lt;a href="http://ngenerics.uservoice.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;User Voice site&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is available for feature requests - please log (and vote for) any features you would like to see in NGenerics. We&amp;rsquo;ll get to these in order of the number of votes attached to them.&lt;/li&gt;
&lt;li&gt;Discussions are now hosted on the &lt;a href="http://groups.google.com/group/ngenerics-users" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ngenerics-users Google group&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you experience any problems caused by the move, let us know by sending a message to the &lt;a href="http://groups.google.com/group/ngenerics-users" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ngenerics-users group&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; or leaving a comment to this post.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; NGenerics is now hosted on &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;GitHub&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/FvfK16cHRrE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Denys Argyriou&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/commute?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics overview - the Priority Queue</title><link>https://riaan.hanekom.io/2009/08/04/ngenerics-overview-the-priority-queue/</link><pubDate>Tue, 04 Aug 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/08/04/ngenerics-overview-the-priority-queue/</guid><description>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/07/09/ngenerics-overview-the-objectmatrix/"&gt;ObjectMatrix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Trees&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;GeneralTree and the Visitor Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/30/ngenerics-overview-binary-trees-and-binary-search-trees/"&gt;Binary Trees and Binary Search Trees&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href="http://en.wikipedia.org/wiki/Priority_queue" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Priority Queue data structure&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has the same basic behaviour and operations as &lt;a href="http://en.wikipedia.org/wiki/Queue_%28data_structure%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the classic queue&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/7977ey2c.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;found in .NET&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.   A queue applies a first-in, first-out (&lt;a href="http://en.wikipedia.org/wiki/FIFO_%28computing%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;FIFO&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) approach to a list of objects. This data structure is typically used in message processing to process messages in order of arrival. Queue implementations tend to have the following operations available :&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/07/09/ngenerics-overview-the-objectmatrix/"&gt;ObjectMatrix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Trees&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;GeneralTree and the Visitor Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/30/ngenerics-overview-binary-trees-and-binary-search-trees/"&gt;Binary Trees and Binary Search Trees&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href="http://en.wikipedia.org/wiki/Priority_queue" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Priority Queue data structure&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has the same basic behaviour and operations as &lt;a href="http://en.wikipedia.org/wiki/Queue_%28data_structure%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;the classic queue&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/7977ey2c.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;found in .NET&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.   A queue applies a first-in, first-out (&lt;a href="http://en.wikipedia.org/wiki/FIFO_%28computing%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;FIFO&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;) approach to a list of objects. This data structure is typically used in message processing to process messages in order of arrival. Queue implementations tend to have the following operations available :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Enqueue&lt;/em&gt; - Adds the object at the back of the queue.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Dequeue&lt;/em&gt; - Fetches and removes the object at the front of the queue.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Peek -&lt;/em&gt; Fetches the object at the front of the queue for inspection without removing it.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;IsEmpty&lt;/em&gt; - Provides information on whether the queue contains any items.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Count&lt;/em&gt; - The number of items in the queue.&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="priority_queue_1.jpg" alt="Priority queue" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;A &lt;a href="http://en.wikipedia.org/wiki/Priority_queue" target="_blank" rel="noopener noreferrer" class="external-link"&gt;priority queue&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; still retains queue semantics, but orders items with relation to their priority - that is, in a &lt;strong&gt;Min Priority Queue&lt;/strong&gt;, the item with the &lt;strong&gt;lowest priority&lt;/strong&gt; will always be at the &lt;strong&gt;head&lt;/strong&gt; of the queue, while items in a &lt;strong&gt;Max Priority Queue&lt;/strong&gt; will sort items in such a way that the item with the &lt;strong&gt;highest priority&lt;/strong&gt; will be at the &lt;strong&gt;head&lt;/strong&gt;.   To illustrate, take the &lt;a href="http://en.wikipedia.org/wiki/Triage" target="_blank" rel="noopener noreferrer" class="external-link"&gt;medical Triage system&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for applying priority to the treatment of patients  (copied directly &lt;a href="http://en.wikipedia.org/wiki/Triage" target="_blank" rel="noopener noreferrer" class="external-link"&gt;from Wikipedia&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;)  :&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Immediate&lt;/strong&gt;: The casualty requires immediate medical attention and will not survive if not seen soon. Any compromise to the casualty&amp;rsquo;s respiration, haemorrhage control, or shock control could be fatal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delayed&lt;/strong&gt;: The casualty requires medical attention within 6 hours. Injuries are potentially life-threatening, but can wait until the Immediate casualties are stabilized and evacuated.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minimal&lt;/strong&gt;: &amp;ldquo;Walking wounded,&amp;rdquo; the casualty requires medical attention when all higher priority patients have been evacuated, and may not require stabilization or monitoring.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expectant&lt;/strong&gt;: The casualty is expected not to reach higher medical support alive without compromising the treatment of higher priority patients. Care should not be abandoned, spare any remaining time and resources after Immediate and Delayed patients have been treated.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can define these classes of priority as a Java style enumeration :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Triage&lt;/span&gt; : IComparable&amp;lt;Triage&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// &amp;#34;Constant&amp;#34; values&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; Triage Green = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Triage(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; Triage Yellow = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Triage(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;readonly&lt;/span&gt; Triage Red = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Triage(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Triage Implementation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; Triage(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Value = &lt;span style="color:#66d9ef"&gt;value&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; Value { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// IComparable Members&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; CompareTo(Triage other) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (other == &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span style="color:#e6db74"&gt;&amp;#34;other&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; Value.CompareTo(other.Value);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Using a priority queue we can trivially ordering of patients using the Triage value:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; queue = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; PriorityQueue(PriorityQueueType.Maximum);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;queue.Enqueue(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Patient(&lt;span style="color:#e6db74"&gt;&amp;#34;P1&amp;#34;&lt;/span&gt;), Triage.Red);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;queue.Enqueue(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Patient(&lt;span style="color:#e6db74"&gt;&amp;#34;P2&amp;#34;&lt;/span&gt;), Triage.Green);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;queue.Enqueue(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Patient(&lt;span style="color:#e6db74"&gt;&amp;#34;P3&amp;#34;&lt;/span&gt;), Triage.Green);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;queue.Enqueue(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Patient(&lt;span style="color:#e6db74"&gt;&amp;#34;P4&amp;#34;&lt;/span&gt;), Triage.Yellow);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Running the code above will result in a priority queue that looks like this :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="priority_queue_2.jpg" alt="Output priority queue" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The priority queue will insert any new patients in their appropriate spot, much like the behaviour of  a &lt;a href="http://msdn.microsoft.com/en-us/library/system.collections.sortedlist.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Sorted List&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.  Inserting another critical patient (Red), will result in the following state :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="priority_queue_3.jpg" alt="Critical patient in priority queue" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Note that items follow chronological order when their priorities are equal.  Retrieving the next patient is as simple as calling the &lt;em&gt;Dequeue&lt;/em&gt; method on the queue.  The &lt;em&gt;Dequeue&lt;/em&gt; operation removes the item at the &lt;strong&gt;head&lt;/strong&gt; of the queue:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Triage priority;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Patient criticalPatient = queue.Dequeue(&lt;span style="color:#66d9ef"&gt;out&lt;/span&gt; priority);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Console.WriteLine(criticalPatient.Name); &lt;span style="color:#75715e"&gt;// P1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Console.WriteLine(priority.Value); &lt;span style="color:#75715e"&gt;// 3 (Red)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="priority_queue_4.jpg" alt="Priority queue with item removed" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Typically,  priority queues are typically implemented using a &lt;a href="http://en.wikipedia.org/wiki/Heap_%28data_structure%29" target="_blank" rel="noopener noreferrer" class="external-link"&gt;heap&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; or a &lt;a href="http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;self-balancing tree&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. The &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/Queues/PriorityQueue.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;implementation in NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; uses a &lt;a href="http://en.wikipedia.org/wiki/Red-black_tree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Red-black tree&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; which makes the operations perform at &lt;em&gt;O(log n)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/pjAH2Ax4uWk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Charles Deluvio 🇵🇭🇨🇦&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Playing with types - non-unique property and field names</title><link>https://riaan.hanekom.io/2009/07/30/playing-with-types-non-unique-property-and-field-names/</link><pubDate>Thu, 30 Jul 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/07/30/playing-with-types-non-unique-property-and-field-names/</guid><description>&lt;p&gt;Cool, I didn&amp;rsquo;t know you could do that:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="playing_wiith_types_1.jpg" alt="Reflector screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Of course, this doesn&amp;rsquo;t play all that well with C#:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="playing_wiith_types_2.jpg" alt="Usage screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I should complete my reading of that &lt;a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;CLI specification&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Z3ownETsdNQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Avi Richards&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;Cool, I didn&amp;rsquo;t know you could do that:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="playing_wiith_types_1.jpg" alt="Reflector screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Of course, this doesn&amp;rsquo;t play all that well with C#:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="playing_wiith_types_2.jpg" alt="Usage screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;I should complete my reading of that &lt;a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;CLI specification&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Z3ownETsdNQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Avi Richards&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Emitting a Type that inherits from a base type referencing the built Type</title><link>https://riaan.hanekom.io/2009/07/26/emitting-a-type-that-inherits-from-a-base-type-referencing-the-built-type/</link><pubDate>Sun, 26 Jul 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/07/26/emitting-a-type-that-inherits-from-a-base-type-referencing-the-built-type/</guid><description>&lt;p&gt;Simple in hindsight, yet it took me a while to craft the correct search terms to come up with this solution.  I can&amp;rsquo;t even find that forum post now, so hopefully this entry will save someone else some time.&lt;/p&gt;
&lt;p&gt;In a lot of solutions there exists a base class that would take the inheritor as a type reference to be able to do some work on it - you&amp;rsquo;ll typically see this pattern  in fluent interfaces and classes that use reflection.  In our current solution we generate NHibernate entities on the fly, which all need to inherit from a base class that look something like this :&lt;/p&gt;</description><content:encoded>&lt;p&gt;Simple in hindsight, yet it took me a while to craft the correct search terms to come up with this solution.  I can&amp;rsquo;t even find that forum post now, so hopefully this entry will save someone else some time.&lt;/p&gt;
&lt;p&gt;In a lot of solutions there exists a base class that would take the inheritor as a type reference to be able to do some work on it - you&amp;rsquo;ll typically see this pattern  in fluent interfaces and classes that use reflection.  In our current solution we generate NHibernate entities on the fly, which all need to inherit from a base class that look something like this :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;abstract&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;DynamicEntity&lt;/span&gt; : IDynamicEntity &lt;span style="color:#66d9ef"&gt;where&lt;/span&gt; T:DynamicEntity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;virtual&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;long&lt;/span&gt; Id { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;!-- more --&gt;
&lt;p&gt;Utilizing &lt;a href="http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;TypeBuilder&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, we can build new classes as follows :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Type baseType = &lt;span style="color:#66d9ef"&gt;typeof&lt;/span&gt;(DynamicEntity);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;typeBuilder.SetParent(baseType.MakeGenericType(?)); &lt;span style="color:#75715e"&gt;// Add methods, properties, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Type newType = typeBuilder.CreateType();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note the question mark  (&lt;strong&gt;?&lt;/strong&gt;) in the call to &lt;em&gt;MakeGenericType.&lt;/em&gt; What do we set the base type to if the base type has to include the unconstructed type?  Turns out that the solution is simple (and I&amp;rsquo;m embarrassed I didn&amp;rsquo;t see it sooner) :  TypeBuilder inherits from &lt;a href="http://msdn.microsoft.com/en-us/library/system.type.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;System.Type&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, so we can reference it as a type placeholder:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;typeBuilder.SetParent(baseType.MakeGenericType(typeBuilder));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Skf7HxARcoc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markus Spiske&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics Overview - The ObjectMatrix</title><link>https://riaan.hanekom.io/2009/07/09/ngenerics-overview-the-objectmatrix/</link><pubDate>Thu, 09 Jul 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/07/09/ngenerics-overview-the-objectmatrix/</guid><description>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Trees&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;GeneralTree and the Visitor Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/30/ngenerics-overview-binary-trees-and-binary-search-trees/"&gt;Binary Trees and Binary Search Trees&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Looking at tree structures will make your eyes bleed, so we&amp;rsquo;ll take a break to discuss one of the simpler data structures &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; offers - the &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/General/ObjectMatrix.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ObjectMatrix&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. The ObjectMatrix is a representation of a 2-dimensional array of objects, like, for example, a game board :&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Trees&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;GeneralTree and the Visitor Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/30/ngenerics-overview-binary-trees-and-binary-search-trees/"&gt;Binary Trees and Binary Search Trees&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Looking at tree structures will make your eyes bleed, so we&amp;rsquo;ll take a break to discuss one of the simpler data structures &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; offers - the &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/General/ObjectMatrix.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ObjectMatrix&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. The ObjectMatrix is a representation of a 2-dimensional array of objects, like, for example, a game board :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="tictactoe.jpg" alt="Tic tac toe" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;Why not use a two-dimensional array in the first place?  The ObjectMatrix offers the following useful operations at the time of writing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rows&lt;/strong&gt; and &lt;strong&gt;Columns&lt;/strong&gt; - formal definition of rows and columns - much better than having &lt;code&gt;.Length&lt;/code&gt; scattered all over your code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetSubMatrix&lt;/strong&gt; -  enables the retrieval of a subset of the matrix.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;InterchangeRows&lt;/strong&gt; and &lt;strong&gt;InterchangeColumns&lt;/strong&gt; - swap individual rows and columns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetRow&lt;/strong&gt; and &lt;strong&gt;GetColumn&lt;/strong&gt; - provides an easy way of retrieving individual rows and columns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AddRow&lt;/strong&gt; and &lt;strong&gt;AddColumn&lt;/strong&gt; - add new rows and columns when you need more space.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DeleteRow&lt;/strong&gt; and &lt;strong&gt;DeleteColumn&lt;/strong&gt; - delete individual rows and columns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resize&lt;/strong&gt; - resize the matrix to have any arbitrary column/row count.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use it like you would use any two dimensional array :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; matrix = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ObjectMatrix(&lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Cross();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Nought();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Nought();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Nought();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Cross();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;matrix[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Cross();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; enumerator = matrix.GetEnumerator();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (enumerator.MoveNext())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(enumerator.Current);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The ObjectMatrix is also the base class for one of the biggest classes in NGenerics - the &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/Mathematical/Matrix.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;mathematical Matrix&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, which we&amp;rsquo;ll get to in a later post.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/FXFz-sW0uwo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markus Spiske&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/matrix?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Tarjan's Algorithm</title><link>https://riaan.hanekom.io/2009/07/06/tarjans-algorithm/</link><pubDate>Mon, 06 Jul 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/07/06/tarjans-algorithm/</guid><description>&lt;p&gt;Thanks to a &lt;a href="http://ngenerics.codeplex.com/SourceControl/PatchList.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;contribution&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; from Andre van der Merwe (&lt;a href="http://andrevdm.blogspot.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;blog&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://twitter.com/andrevdm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;twitter&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;), &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; now features &lt;a href="http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Tarjan&amp;rsquo;s strongly connected components algorithm&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on it&amp;rsquo;s Graph implementation. By using Tarjan&amp;rsquo;s algorithm, we&amp;rsquo;re able to find the &lt;a href="http://en.wikipedia.org/wiki/Strongly_connected_component" target="_blank" rel="noopener noreferrer" class="external-link"&gt;strongly connected components&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (read : cycles) in a directed graph. You can invoke it via the FindCycles method on the &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/General/Graph.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Graph&amp;lt;T&amp;gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; class, available from build &lt;a href="http://teamcity.codebetter.com/viewLog.html?buildTypeId=bt33&amp;amp;amp;amp;buildId=3737" target="_blank" rel="noopener noreferrer" class="external-link"&gt;#1.0.0.55764 (30 Jun 09 13:40)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Thanks to a &lt;a href="http://ngenerics.codeplex.com/SourceControl/PatchList.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;contribution&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; from Andre van der Merwe (&lt;a href="http://andrevdm.blogspot.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;blog&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://twitter.com/andrevdm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;twitter&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;), &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; now features &lt;a href="http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Tarjan&amp;rsquo;s strongly connected components algorithm&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on it&amp;rsquo;s Graph implementation. By using Tarjan&amp;rsquo;s algorithm, we&amp;rsquo;re able to find the &lt;a href="http://en.wikipedia.org/wiki/Strongly_connected_component" target="_blank" rel="noopener noreferrer" class="external-link"&gt;strongly connected components&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (read : cycles) in a directed graph. You can invoke it via the FindCycles method on the &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/General/Graph.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Graph&amp;lt;T&amp;gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; class, available from build &lt;a href="http://teamcity.codebetter.com/viewLog.html?buildTypeId=bt33&amp;amp;amp;amp;buildId=3737" target="_blank" rel="noopener noreferrer" class="external-link"&gt;#1.0.0.55764 (30 Jun 09 13:40)&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/k_T9Zj3SE8k?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Simon Abrams&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics Overview - Binary Trees and Binary Search Trees</title><link>https://riaan.hanekom.io/2009/06/30/ngenerics-overview-binary-trees-and-binary-search-trees/</link><pubDate>Tue, 30 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/30/ngenerics-overview-binary-trees-and-binary-search-trees/</guid><description>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Trees&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;GeneralTree and the Visitor Pattern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;If you haven&amp;rsquo;t read my &lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;previous post on General Trees&lt;/a&gt;, it might be a good idea to do so before reading further.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A &lt;a href="http://en.wikipedia.org/wiki/Binary_tree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Binary Tree&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is a refined version of the General Tree that limits the &lt;strong&gt;number of children&lt;/strong&gt; each node can have - two to be exact.   Child nodes are thus referred to as the &lt;strong&gt;Left&lt;/strong&gt; and &lt;strong&gt;Right&lt;/strong&gt; child nodes.  The &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/Trees/BinaryTree.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;BinaryTree&amp;lt;T&amp;gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; class in &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; provides an implementation of a Binary Tree, which, when simplified, looks something like this :&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Trees&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;GeneralTree and the Visitor Pattern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;If you haven&amp;rsquo;t read my &lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;previous post on General Trees&lt;/a&gt;, it might be a good idea to do so before reading further.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A &lt;a href="http://en.wikipedia.org/wiki/Binary_tree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Binary Tree&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is a refined version of the General Tree that limits the &lt;strong&gt;number of children&lt;/strong&gt; each node can have - two to be exact.   Child nodes are thus referred to as the &lt;strong&gt;Left&lt;/strong&gt; and &lt;strong&gt;Right&lt;/strong&gt; child nodes.  The &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/Trees/BinaryTree.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;BinaryTree&amp;lt;T&amp;gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; class in &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; provides an implementation of a Binary Tree, which, when simplified, looks something like this :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BinaryTree&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BinaryTree Left { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BinaryTree Right { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; T Data { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;!-- more --&gt;
&lt;p&gt;We can represent a simple binary tree visually like this:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="binarytree3.jpg" alt="Binary tree" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Binary Trees support pre-order and post-order traversal as &lt;a href="https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/"&gt;discussed in my previous post,&lt;/a&gt; and also support in-order traversal.  An in-order traversal visits the left node, the root node and lastly the node on the right.  When supplied with an &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/Patterns/Visitor/InOrderVisitor.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;InOrderVisitor&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; instance, the visitor will visit tree nodes in the order (7, 4, 8, 2, 5, 1, 3, 9, 6, 10) :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="binarytree_2.jpg" alt="In order traversal" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;As with General Trees, the BinaryTree&amp;lt;T&amp;gt; class supports &lt;a href="http://en.wikipedia.org/wiki/Breadth-first_search" target="_blank" rel="noopener noreferrer" class="external-link"&gt;breadth first traversal&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and has &lt;a href="http://msdn.microsoft.com/en-us/library/92t2ye13.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ICollection&amp;lt;T&amp;gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; semantics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Binary Search Trees&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Search trees attempt to address the problem of reducing the number of comparisons in finding items.  While not as efficient as &lt;a href="http://www.google.co.za/url?q=http://msdn.microsoft.com/en-us/library/xfhwa508.aspx&amp;amp;amp;amp;amp;ei=bRlJSsaaA5jNjAfSmcxh&amp;amp;amp;amp;amp;sa=X&amp;amp;amp;amp;amp;oi=revisions_result&amp;amp;amp;amp;amp;resnum=4&amp;amp;amp;amp;amp;ct=result&amp;amp;amp;amp;amp;cad=revid%3D946890717&amp;amp;amp;amp;amp;usg=AFQjCNEmtnVWvSzOfAhzWOnkGeLO90Esqw" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Hash tables&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; with their O(1) performance, they do cut down search times over larger data sets.   Search trees are able to do this by adding constraints to tree data structures.  A &lt;a href="http://en.wikipedia.org/wiki/Binary_search_tree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Binary Search Tree&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is the simplest of search trees with the following rules in place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each value in the tree is distinct from any other (unique).&lt;/li&gt;
&lt;li&gt;Each left child node has a value smaller than the value of its parent.&lt;/li&gt;
&lt;li&gt;Each right child node has a value larger than the value of its parent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/Trees/BinarySearchTree.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;BinarySearchTree&amp;lt;TKey, TValue&amp;gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; class in NGenerics implements the &lt;a href="http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;IDictionary&amp;lt;TKey, TValue&amp;gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; interface for simple lookups based on keys, and supports the usual traversal algorithms.  Reusing our example tree and changing it to comply to the rules could result in the following tree:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="binarysearchtree4.jpg" alt="Binary tree" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easy to see how a Binary Tree can cut down search times - when using a sequential data structure (array, list), or when manually searching an unordered tree like the plain BinaryTree, we potentially need to search through every item in the collection before we find it with a worst-case performance of O(n).  With Binary Search Trees we can cut down that time by comparing node values with the search value and deciding on which branch to continue searching on - enough to make searching a Binary Trees on average an O(log n) operation.  To illustrate, searching for the value &amp;ldquo;3&amp;rdquo; in our sample tree will result in 4 comparisons :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="binarytree_4.jpg" alt="Binary search tree" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Although Binary Trees are not nearly as efficient as hash tables with regards to searching (assuming that you&amp;rsquo;ve implemented a proper hash function), Binary Search Trees (and most other search trees) provide an enormous benefit over hash tables in that we can traverse items in sorted order without any preprocessing.  We can use an in-order traversal to yield items in sorted order:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="binarysearchtreeinordertraversal2.jpg" alt="In order traversal" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Binary Trees do suffer from  a couple of worst-case performance scenarios where there performance could degrade to &lt;em&gt;O(n)&lt;/em&gt; in searches.  Adding items to the tree in ascending order will result in the following worst-case scenario:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="binarysearchtreeworstcase3.jpg" alt="Binary search tree worst case" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Adding items in descending order will result in a tree that grows in the opposite direction, with the same devastating effect.  &lt;a href="http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Self-balancing trees&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; address this problem but that&amp;rsquo;s a topic for a future post.  If the data you&amp;rsquo;re pumping into the tree is random you&amp;rsquo;ll probably never hit this situation - but if you have data with some order in it a self-balancing tree might be a better fit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="../https://unsplash.com/photos/oMVCUyAIWpE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Andrew Haimerl&lt;/a&gt; on &lt;a href="../https://unsplash.com/search/photos/tree?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Developer Podcasts</title><link>https://riaan.hanekom.io/2009/06/29/developer-podcasts/</link><pubDate>Mon, 29 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/29/developer-podcasts/</guid><description>&lt;p&gt;I&amp;rsquo;ve found podcasts a good way to spend your time when you&amp;rsquo;re stuck in traffic - here&amp;rsquo;s a list of my favourite developer podcasts in alphabetical order :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.dotnetrocks.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;.NET Rocks&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - still one of the best podcasts out there.  The banter is fun to listen too, and they have a wide variety of guests and topics on .NET.  Also presents a large (but fun) challenge in catching up on previous episodes with more than 400 episodes recorded.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.43folders.com/podcast" target="_blank" rel="noopener noreferrer" class="external-link"&gt;43 Folders&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - a productivity podcast, recommended.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.altnetpodcast.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Alt.NET Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - infrequent releases, but some interesting topics.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://deepfriedbytes.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Deep Fried Bytes&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - good topics and friendly banter in a Southern flavour.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://elegantcode.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Elegant Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - good topics, nice variety of guests.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hanselminutes.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Hanselminutes&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - possibly my top podcast.  Scott Hanselman provides a technical (and sometime hilarious) view on a variety of developer topics.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://get-scripting.blogspot.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Get Scripting&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - useful if you&amp;rsquo;re into PowerShell scripting.  The audio quality is not that great though.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://herdingcode.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Herding Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; -  falls into the same class as Deep Fried Bytes and Elegant Code.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://linuxoutlaws.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Linux Outlaws&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - News cast for everything Linux.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.informit.com/podcasts/index_rss.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;On Open Source&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - variety of topics on different platforms/languages, infrequent releases in audio format.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://polymorphicpodcast.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Polymorphic Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - infrequent releases, but some good content in most of the episodes.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pragprog.com/podcasts/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Pragmatic Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - I love the format of the Pragmatic Podcast - it plays like a news reel.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rookiedesigner.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Rookie Designer&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - originally downloaded it for my wife, but now I&amp;rsquo;m listening to it.  All about the life of a designer (web / graphics).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://podcast.rubyonrails.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ruby On Rails Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - ruby on rails.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.se-radio.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Software Engineering Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - more formal discussions on computer science topics.   The accent takes some getting used to, but the content is worthwhile.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sparklingclient.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Sparkling Client&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - short and sweet Silverlight podcasts.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://aspnetpodcast.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The ASP.NET Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - short podcasts on ASP.NET and web development in general - sound quality gets in the way sometimes.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.javaposse.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Java Posse&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - newscast on everything Java.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://startuppodcast.wordpress.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Startup Success Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - podcast on what it takes to build an IT startup - highly recommended.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thirstydeveloper.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Thirsty Developer&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - wide variety of topics, good content.&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;strong&gt;And the winners are&amp;hellip;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve found podcasts a good way to spend your time when you&amp;rsquo;re stuck in traffic - here&amp;rsquo;s a list of my favourite developer podcasts in alphabetical order :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.dotnetrocks.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;.NET Rocks&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - still one of the best podcasts out there.  The banter is fun to listen too, and they have a wide variety of guests and topics on .NET.  Also presents a large (but fun) challenge in catching up on previous episodes with more than 400 episodes recorded.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.43folders.com/podcast" target="_blank" rel="noopener noreferrer" class="external-link"&gt;43 Folders&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - a productivity podcast, recommended.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.altnetpodcast.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Alt.NET Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - infrequent releases, but some interesting topics.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://deepfriedbytes.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Deep Fried Bytes&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - good topics and friendly banter in a Southern flavour.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://elegantcode.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Elegant Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - good topics, nice variety of guests.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hanselminutes.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Hanselminutes&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - possibly my top podcast.  Scott Hanselman provides a technical (and sometime hilarious) view on a variety of developer topics.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://get-scripting.blogspot.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Get Scripting&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - useful if you&amp;rsquo;re into PowerShell scripting.  The audio quality is not that great though.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://herdingcode.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Herding Code&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; -  falls into the same class as Deep Fried Bytes and Elegant Code.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://linuxoutlaws.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Linux Outlaws&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - News cast for everything Linux.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.informit.com/podcasts/index_rss.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;On Open Source&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - variety of topics on different platforms/languages, infrequent releases in audio format.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://polymorphicpodcast.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Polymorphic Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - infrequent releases, but some good content in most of the episodes.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://pragprog.com/podcasts/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Pragmatic Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - I love the format of the Pragmatic Podcast - it plays like a news reel.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rookiedesigner.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Rookie Designer&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - originally downloaded it for my wife, but now I&amp;rsquo;m listening to it.  All about the life of a designer (web / graphics).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://podcast.rubyonrails.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ruby On Rails Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - ruby on rails.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.se-radio.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Software Engineering Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - more formal discussions on computer science topics.   The accent takes some getting used to, but the content is worthwhile.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sparklingclient.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Sparkling Client&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - short and sweet Silverlight podcasts.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://aspnetpodcast.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The ASP.NET Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - short podcasts on ASP.NET and web development in general - sound quality gets in the way sometimes.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.javaposse.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Java Posse&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - newscast on everything Java.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://startuppodcast.wordpress.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Startup Success Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - podcast on what it takes to build an IT startup - highly recommended.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://thirstydeveloper.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;The Thirsty Developer&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - wide variety of topics, good content.&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;strong&gt;And the winners are&amp;hellip;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are a .NET developer starting out with podcasts try these first:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(6) &lt;a href="http://www.hanselminutes.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Hanselminutes&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(1) .&lt;a href="http://www.dotnetrocks.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NET Rocks&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;(12) &lt;a href="http://pragprog.com/podcasts/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Pragmatic Podcast&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also see this &lt;a href="http://stackoverflow.com/questions/531570/developer-podcasts" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Stack Overflow question&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="http://www.hanselman.com/HanselmanListOfPodcastsForNETProgrammers.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Scott Hanselman&amp;rsquo;s post&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for other lists of podcasts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/bE3_aFt85Y8?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NeONBRAND&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/headphones?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics overview - GeneralTree and the Visitor pattern</title><link>https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/</link><pubDate>Sun, 21 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/21/ngenerics-overview-generaltree-and-the-visitor-pattern/</guid><description>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;[ Note : This post feels like Computer Science 101 - but I felt it necessary to discuss the basic tree concepts before we move on to some of the more specialized trees like search trees.  ]&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/Trees/GeneralTree.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;em&gt;GeneralTree&amp;lt;T&amp;gt;&lt;/em&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; class in &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; provides a way of defining tree structures in a simple, recursive way. It has a simple, recursive definition :&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;strong&gt;Previous instalments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;General Data Structures&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/"&gt;HashList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;[ Note : This post feels like Computer Science 101 - but I felt it necessary to discuss the basic tree concepts before we move on to some of the more specialized trees like search trees.  ]&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/DataStructures/Trees/GeneralTree.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;em&gt;GeneralTree&amp;lt;T&amp;gt;&lt;/em&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; class in &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; provides a way of defining tree structures in a simple, recursive way. It has a simple, recursive definition :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;GeneralTree&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; T nodeData;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; List childNodes;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;!-- more --&gt;
&lt;p&gt;Visually, we can represent it, well, as a tree :&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="simpletree3.jpg" alt="Simple tree" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;In contrast to some of the more specialized tree structures (like binary trees and search trees), the GeneralTree enforces no constraints on the structure of the tree. Each tree node have no constraints on the number of children or order of those child nodes. General trees are useful for expressing some relationship between objects without having these relationships encoded in the object itself.  Once we have these relationships set up, we can start traversing the tree in all kinds of interesting ways.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Visitor_pattern" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;strong&gt;The Visitor Pattern&lt;/strong&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The visitor pattern provides a way of separating the acting logic from the traversal logic of the structure.  Almost all data structures in NGenerics can accept a visitor instance for traversing the structure, either via the Accept extension method on &lt;a href="http://msdn.microsoft.com/en-us/library/9eekhta0.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;em&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/em&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, or through specialized traversal methods on the data structures themselves.  A visitor needs to adhere to the &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/Patterns/Visitor/IVisitor.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;em&gt;IVisitor&amp;lt;T&amp;gt;&lt;/em&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; interface :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IVisitor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; HasCompleted { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Visit(T obj);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;When traversing a data structure the Visit member gets called on the visitor with each visited instance.  A contrived example of a visitor is a SummingVisitor:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SumVisitor&lt;/span&gt; : IVisitor
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Visit(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; obj)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Sum += obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; HasCompleted
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt; { &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; Sum
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;em&gt;HasCompleted&lt;/em&gt; property provides a way for the visitor to stop traversing the structure.  This might be useful in visitors that search for specific items, and would like to quit after they&amp;rsquo;ve found what they&amp;rsquo;re looking for. &lt;a href="http://en.wikipedia.org/wiki/Tree_traversal" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;strong&gt;Tree Traversals&lt;/strong&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; There are two ways of traversing trees - &lt;strong&gt;breadth-first traversal&lt;/strong&gt;, and &lt;strong&gt;depth-first traversal&lt;/strong&gt;.   Both these implementations in NGenerics make use of the visitor pattern.  &lt;strong&gt;Breadth-first traversal&lt;/strong&gt; visits each node on a level before moving on to the next level.  In our example tree above, breadth first traversal would result in the following order of visitations:  &lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="simpletree-breadth-first-traversal1.jpg" alt="Breadth first traversal 1" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Depth-first traversal&lt;/strong&gt;, will result in visiting nodes from top to bottom in the tree.   There are three types of depth-first traversal routines that visit the nodes in different orders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pre-order traversals:&lt;/strong&gt; root -&amp;gt; left child -&amp;gt; right child&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In-order traversals:&lt;/strong&gt; used in binary trees - left child -&amp;gt; root node -&amp;gt; right child.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Post-order traversals:&lt;/strong&gt; left child -&amp;gt; right child -&amp;gt; root&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these traversal types, NGenerics defines the &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/Patterns/Visitor/InOrderVisitor.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;InOrderVisitor&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/Patterns/Visitor/PostOrderVisitor.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;PostOrderVisitor&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and &lt;a href="https://github.com/ngenerics/ngenerics/blob/master/src/NGenerics/Patterns/Visitor/PreOrderVisitor.cs" target="_blank" rel="noopener noreferrer" class="external-link"&gt;PreOrderVisitor&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; classes that custom visitors can inherit from.  Traversing our sample tree in &lt;strong&gt;pre-order&lt;/strong&gt; fashion will result in the following order of visitation:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="simpletree-preorder-traversal2.jpg" alt="Pre order traversal" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;An ubiquitous use for pre-order traversals is in the evaluation of &lt;a href="http://en.wikipedia.org/wiki/Expression_tree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;expression trees&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;post-order visitor&lt;/strong&gt; will visit the tree in the following order:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="simpletree-postorder-traversal.jpg" alt="Post order traversal" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;More &lt;em&gt;GeneralTree&amp;lt;T&amp;gt;&lt;/em&gt; Goodness&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Apart from having &lt;a href="http://msdn.microsoft.com/en-us/library/92t2ye13.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;em&gt;ICollection&amp;lt;T&amp;gt;&lt;/em&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; semantics and enabling traversals of the tree structure, the GeneralTree class offers other useful methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ancestors : Retrieve all ancestors of the current node as a path through the tree.&lt;/li&gt;
&lt;li&gt;Descendants : Retrieve all descendants of the current node as a path through the tree.&lt;/li&gt;
&lt;li&gt;Each node keeps track of both the parent and the child nodes and enables easy detaching and re-attaching of nodes to any parent node.&lt;/li&gt;
&lt;li&gt;We can sort TreeNodes on a child level (i.e. all children of a specific node) or recursively through the tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/w0p6j2-OYww?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Bart Zimny&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/tree?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Avoid the home page in Internet Explorer</title><link>https://riaan.hanekom.io/2009/06/17/avoid-the-home-page-in-internet-explorer/</link><pubDate>Wed, 17 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/17/avoid-the-home-page-in-internet-explorer/</guid><description>&lt;p&gt;More for my own records than anything else&amp;hellip; I&amp;rsquo;m a big fan of the about:blank home page, but sometimes corporate policies dictate (and enforce) the company intranet site as IE&amp;rsquo;s home page. To start IE without going to the set home page, add the &lt;strong&gt;nohome&lt;/strong&gt; command line parameter as such :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;C:\Program Files\Internet Explorer\iexplore.exe&amp;#34;&lt;/span&gt; -nohome&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/tUPPJicAfxY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Colin Rex&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/run?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;More for my own records than anything else&amp;hellip; I&amp;rsquo;m a big fan of the about:blank home page, but sometimes corporate policies dictate (and enforce) the company intranet site as IE&amp;rsquo;s home page. To start IE without going to the set home page, add the &lt;strong&gt;nohome&lt;/strong&gt; command line parameter as such :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;Bash&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;C:\Program Files\Internet Explorer\iexplore.exe&amp;#34;&lt;/span&gt; -nohome&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/tUPPJicAfxY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Colin Rex&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/run?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics for Silverlight</title><link>https://riaan.hanekom.io/2009/06/17/ngenerics-for-silverlight/</link><pubDate>Wed, 17 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/17/ngenerics-for-silverlight/</guid><description>&lt;p&gt;The &lt;a href="http://www.codebetter.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Code Better TeamCity guys&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; were &lt;a href="https://riaan.hanekom.io/2009/03/30/public-ci-for-ngenerics/"&gt;kind enough to install the Silverlight runtime&lt;/a&gt; on the &lt;a href="http://teamcity.codebetter.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;build server&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; a while ago, which means that &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; now has an automated Silverlight build.&lt;/p&gt;</description><content:encoded>&lt;p&gt;The &lt;a href="http://www.codebetter.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Code Better TeamCity guys&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; were &lt;a href="https://riaan.hanekom.io/2009/03/30/public-ci-for-ngenerics/"&gt;kind enough to install the Silverlight runtime&lt;/a&gt; on the &lt;a href="http://teamcity.codebetter.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;build server&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; a while ago, which means that &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; now has an automated Silverlight build.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in trying out NGenerics on the Silverlight platform, you can find the assemblies under NGenerics Trunk/Artifacts.  Be sure to let us know if you find any bugs/pain points/features that can need improvement on this particular platform.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/AaEQmoufHLk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markus Spiske&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics on Ohloh</title><link>https://riaan.hanekom.io/2009/06/17/ngenerics-on-ohloh/</link><pubDate>Wed, 17 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/17/ngenerics-on-ohloh/</guid><description>&lt;p&gt;I share the same sentiment as &lt;a href="http://ayende.com/Blog/archive/2009/05/22/nhibernate-ndash-help-us-see-who-is-using-it.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ayende on the visibility of open source project usage&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - page views and downloads are not useful in determining usage. If you do use NGenerics in your projects (whether it be public or private), you can let us know on the &lt;a href="https://www.ohloh.net/p/NGenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ohloh project page&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. If you&amp;rsquo;re using it in an public/open source project, drop us a line so that we can add a link to you in our &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Hall Of Fame&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I share the same sentiment as &lt;a href="http://ayende.com/Blog/archive/2009/05/22/nhibernate-ndash-help-us-see-who-is-using-it.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ayende on the visibility of open source project usage&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - page views and downloads are not useful in determining usage. If you do use NGenerics in your projects (whether it be public or private), you can let us know on the &lt;a href="https://www.ohloh.net/p/NGenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ohloh project page&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. If you&amp;rsquo;re using it in an public/open source project, drop us a line so that we can add a link to you in our &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Hall Of Fame&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/w7ZyuGYNpRQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Kevin&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>100% Code Coverage</title><link>https://riaan.hanekom.io/2009/06/15/100-code-coverage/</link><pubDate>Mon, 15 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/15/100-code-coverage/</guid><description>&lt;p&gt;I&amp;rsquo;ll say it once more - it&amp;rsquo;s not worth it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/06/07/high-test-coverage-ratio-is-a-good-thing-anyway.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Let it go.&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Your aim should be at about &lt;strong&gt;70% code coverage&lt;/strong&gt; - as long as you know in your hearts heart that &lt;strong&gt;you have tested that you should have&lt;/strong&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ll say it once more - it&amp;rsquo;s not worth it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/06/07/high-test-coverage-ratio-is-a-good-thing-anyway.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Let it go.&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Your aim should be at about &lt;strong&gt;70% code coverage&lt;/strong&gt; - as long as you know in your hearts heart that &lt;strong&gt;you have tested that you should have&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s vitally important (and which is the whole reason why I run coverage tools in the first place), is not the warm, fuzzy feeling I get in my tummy when I see a high number - it&amp;rsquo;s the &lt;strong&gt;easy identification of untested code and pathways&lt;/strong&gt; that yield value in this regard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/LJQEDQAmAnI?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ben White&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/holy-bible?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics overview - the HashList</title><link>https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/</link><pubDate>Mon, 15 Jun 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/06/15/ngenerics-overview-the-hashlist/</guid><description>&lt;p&gt;Something that I find a use for in almost every project I work on, is the &lt;a href="https://github.com/ngenerics/ngenerics/wiki/HashList" target="_blank" rel="noopener noreferrer" class="external-link"&gt;HashList&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (also known as a MultiMap in the Java world) in &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; 1.2. A HashList is a multi-valued dictionary that uses a &lt;em&gt;Dictionary&amp;lt;TKey, IList&lt;TValue&gt;&amp;gt;&lt;/em&gt; under the covers. It still retains dictionary semantics but handles the creation and destruction of the key/list pairs itself.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Something that I find a use for in almost every project I work on, is the &lt;a href="https://github.com/ngenerics/ngenerics/wiki/HashList" target="_blank" rel="noopener noreferrer" class="external-link"&gt;HashList&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; (also known as a MultiMap in the Java world) in &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; 1.2. A HashList is a multi-valued dictionary that uses a &lt;em&gt;Dictionary&amp;lt;TKey, IList&lt;TValue&gt;&amp;gt;&lt;/em&gt; under the covers. It still retains dictionary semantics but handles the creation and destruction of the key/list pairs itself.&lt;/p&gt;
&lt;p&gt;For example, adding a couple of items to the HashList will have the following result:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; legsHashList = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; HashList();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;legsHashList.Add(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Cow&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;legsHashList.Add(&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Horse&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;legsHashList.Add(&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Chimpanzee&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;legsHashList.Add(&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Spider&amp;#34;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Key&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Values&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Cow&lt;/td&gt;
&lt;td&gt;Horse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Chimpanzee&lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Spider&lt;/td&gt;
&lt;td&gt; &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Removing the cow and the horse will result in removing the list (and the key) from the dictionary, affecting both the key count and the value count.  The HashList implements &lt;em&gt;IEnumerable&amp;lt;KeyValuePair&amp;lt;TKey, IList&amp;lt;TValue&amp;raquo;&amp;gt;&lt;/em&gt; so you can traverse items in grouped order. Sure beats the heck out of having all that list management code sitting in your code base.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/u2Ru4QBXA5Q?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Pankaj Patel&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Public CI for NGenerics</title><link>https://riaan.hanekom.io/2009/03/30/public-ci-for-ngenerics/</link><pubDate>Mon, 30 Mar 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/03/30/public-ci-for-ngenerics/</guid><description>&lt;p&gt;Thanks to the &lt;a href="http://codebetter.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Code Better guys&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;,  &lt;a href="http://www.jetbrains.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;JetBrains&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://ideavine.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ideavine&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and &lt;a href="http://devlicio.us" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Devlicio.us&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;,  &lt;a href="https://www.github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is now hosted on a &lt;a href="http://teamcity.codebetter.com/project.html?projectId=project21" target="_blank" rel="noopener noreferrer" class="external-link"&gt;public CI server&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Thanks to the &lt;a href="http://codebetter.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Code Better guys&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;,  &lt;a href="http://www.jetbrains.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;JetBrains&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://ideavine.net/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ideavine&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and &lt;a href="http://devlicio.us" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Devlicio.us&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;,  &lt;a href="https://www.github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is now hosted on a &lt;a href="http://teamcity.codebetter.com/project.html?projectId=project21" target="_blank" rel="noopener noreferrer" class="external-link"&gt;public CI server&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="ngenericsci_1.jpg" alt="CI screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The build script packages the main NGenerics assemblies in a zip file, so you always have access to the latest build from source.  You can find those under &amp;ldquo;Artifacts&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="ngenericsci_2.jpg" alt="CI screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re still waiting for a response from the Code Better team on supporting Silverlight on the server - if we get that, the latest Silverlight version of NGenerics will be available as well. If you own an open source project and want CI for your project, find James Kovacs&amp;rsquo; post &lt;a href="http://codebetter.com/blogs/james.kovacs/archive/2009/02/24/announcing-teamcity-codebetter-com.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/JL82X5WO_Tg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Igor Ovsyannykov&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/technology?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Visual SVN - Subversion at its best</title><link>https://riaan.hanekom.io/2009/03/10/visual-svn-subversion-at-its-best/</link><pubDate>Tue, 10 Mar 2009 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2009/03/10/visual-svn-subversion-at-its-best/</guid><description>&lt;p&gt;About a year ago, the VisualSVN guys gave the &lt;a href="https://www.github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; team a complimentary license for their product.  After a year with it, I would not using Subversion as a VCS without it!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.visualsvn.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Get it here, and have a look at their VisualSVN Server product&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; while you&amp;rsquo;re there - also a great product.&lt;/p&gt;</description><content:encoded>&lt;p&gt;About a year ago, the VisualSVN guys gave the &lt;a href="https://www.github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; team a complimentary license for their product.  After a year with it, I would not using Subversion as a VCS without it!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.visualsvn.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Get it here, and have a look at their VisualSVN Server product&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; while you&amp;rsquo;re there - also a great product.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="visualsvn.jpg" alt="VisualSVN screenshot" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/HzWERZc5yP4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Tyler Nix&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/coffee-gloves?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Specification pattern</title><link>https://riaan.hanekom.io/2008/10/05/specification-pattern/</link><pubDate>Sun, 05 Oct 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/10/05/specification-pattern/</guid><description>&lt;p&gt;The Specification pattern has been added to &lt;a href="https://www.github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. In &lt;a href="https://riaan.hanekom.io/2008/09/10/extension-method-patterns/"&gt;my previous post on the Specification Pattern&lt;/a&gt;, we explored creating specification functionality using extension methods. It&amp;rsquo;s been implemented with the operator methods (And, Or, Xor) on the actual interface, with an abstract class forming the base of all specifications. The deal-breaker for this approach was the need to add operators |, &amp;amp; and ^ to trim down the syntax some. With the Specification Pattern in NGenerics, you can now do this:&lt;/p&gt;</description><content:encoded>&lt;p&gt;The Specification pattern has been added to &lt;a href="https://www.github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. In &lt;a href="https://riaan.hanekom.io/2008/09/10/extension-method-patterns/"&gt;my previous post on the Specification Pattern&lt;/a&gt;, we explored creating specification functionality using extension methods. It&amp;rsquo;s been implemented with the operator methods (And, Or, Xor) on the actual interface, with an abstract class forming the base of all specifications. The deal-breaker for this approach was the need to add operators |, &amp;amp; and ^ to trim down the syntax some. With the Specification Pattern in NGenerics, you can now do this:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;16
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;17
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;18
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;19
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;20
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;21
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;22
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;23
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;24
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;25
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;26
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;27
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;28
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;29
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;30
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;31
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;32
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;33
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;34
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;35
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Customer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; Name { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; Surname { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; CustomerStatus Status { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; BalanceStatus BalanceStatus { &lt;span style="color:#66d9ef"&gt;get&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;set&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;enum&lt;/span&gt; BalanceStatus
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Settled,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Owing
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;enum&lt;/span&gt; CustomerStatus
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Bronze,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Silver,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Gold
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; ValidateGoldCustomer()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; specification = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; PredicateSpecification(x =&amp;gt; x.Status == CustomerStatus.Gold)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .And(x =&amp;gt; x.Name == &lt;span style="color:#e6db74"&gt;&amp;#34;CustomerName&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .And(x =&amp;gt; x.BalanceStatus == BalanceStatus.Settled).Not();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; testCustomer = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Customer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Name = &lt;span style="color:#e6db74"&gt;&amp;#34;CustomerName&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Surname = &lt;span style="color:#e6db74"&gt;&amp;#34;CustomerSurname&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Status = CustomerStatus-.Gold
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; specification.IsSatisfiedBy(testCustomer);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Or you can use the operators defined in &lt;em&gt;AbstractSpecification&amp;lt;T&amp;gt;&lt;/em&gt;:&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 3
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 4
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 5
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 6
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 7
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 8
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt; 9
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;10
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;11
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;12
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;13
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;14
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; ValidateGoldCustomerWithOperators()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; specification = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; PredicateSpecification(x =&amp;gt; x.Status == CustomerStatus.Gold) &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Predicate(x =&amp;gt; x.Name == &lt;span style="color:#e6db74"&gt;&amp;#34;CustomerName&amp;#34;&lt;/span&gt;) &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; !&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; PredicateSpecification(x =&amp;gt; x.BalanceStatus == BalanceStatus.Settled);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; testCustomer = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Customer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Name = &lt;span style="color:#e6db74"&gt;&amp;#34;CustomerName&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Surname = &lt;span style="color:#e6db74"&gt;&amp;#34;CustomerSurname&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Status = CustomerStatus.Gold
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; specification.IsSatisfiedBy(testCustomer);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The part I&amp;rsquo;m looking into now is &lt;strong&gt;subsumption&lt;/strong&gt; and &lt;strong&gt;partially satisfied specifications&lt;/strong&gt;. From &lt;a href="http://martinfowler.com/apsupp/spec.pdf" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Martin Fowler and Eric Evans&amp;rsquo; paper&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Subsumption&lt;/strong&gt; allows you to compare specifications to see if satisfying one implies satisfaction of the other. It is also sometimes possible to use subsumption to implement satisfaction. If a candidate object can produce a specification that characterizes it, the testing with a specification then becomes a comparison of similar specifications — removing the coupling of specification mechanism entirely from the domain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/fqkrXYMosT4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;William Felker&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/box?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>MEF now MS-PL</title><link>https://riaan.hanekom.io/2008/10/04/mef-now-ms-pl/</link><pubDate>Sat, 04 Oct 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/10/04/mef-now-ms-pl/</guid><description>&lt;p&gt;&lt;a href="https://riaan.hanekom.io/2008/09/10/ms-lpl/"&gt;I take back every word I said&lt;/a&gt;. &lt;a href="http://feeds.feedburner.com/~r/CodeBetter/~3/409030171/mef-going-ms-pl-the-little-engine-that-could.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Now it feels worth looking into&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/DqWEAOHsAvc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Olu Eletu&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/contract?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;a href="https://riaan.hanekom.io/2008/09/10/ms-lpl/"&gt;I take back every word I said&lt;/a&gt;. &lt;a href="http://feeds.feedburner.com/~r/CodeBetter/~3/409030171/mef-going-ms-pl-the-little-engine-that-could.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Now it feels worth looking into&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/DqWEAOHsAvc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Olu Eletu&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/contract?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics 1.3 Release</title><link>https://riaan.hanekom.io/2008/09/25/ngenerics-1.3-release/</link><pubDate>Thu, 25 Sep 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/09/25/ngenerics-1.3-release/</guid><description>&lt;p&gt;NGenerics 1.3 has finally reached production status - you can download it &lt;a href="http://www.codeplex.com/NGenerics/Release/ProjectReleases.aspx?ReleaseId=10959" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With it released, we can start working on some exciting new features for 1.4. Watch this space!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/f5pTwLHCsAg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Lewis Ngugi&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;NGenerics 1.3 has finally reached production status - you can download it &lt;a href="http://www.codeplex.com/NGenerics/Release/ProjectReleases.aspx?ReleaseId=10959" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With it released, we can start working on some exciting new features for 1.4. Watch this space!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/f5pTwLHCsAg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Lewis Ngugi&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>LiveWriter Plugins</title><link>https://riaan.hanekom.io/2008/09/13/livewriter-plugins/</link><pubDate>Sat, 13 Sep 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/09/13/livewriter-plugins/</guid><description>&lt;p&gt;Installed a bunch of them - ahh, it&amp;rsquo;s good to have them back.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="cayla_teeth.jpg" alt="Cayla&amp;rsquo;s Teeth" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;13 September 2008 - Update : We&amp;rsquo;ve found the little girl in the picture&amp;rsquo;s first tooth!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/V4EOZj7g1gw?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Neven Krcmarek&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/write?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;Installed a bunch of them - ahh, it&amp;rsquo;s good to have them back.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="cayla_teeth.jpg" alt="Cayla&amp;rsquo;s Teeth" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;13 September 2008 - Update : We&amp;rsquo;ve found the little girl in the picture&amp;rsquo;s first tooth!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/V4EOZj7g1gw?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Neven Krcmarek&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/write?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Extension Method Patterns</title><link>https://riaan.hanekom.io/2008/09/10/extension-method-patterns/</link><pubDate>Wed, 10 Sep 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/09/10/extension-method-patterns/</guid><description>&lt;p&gt;One of the walls I hit the most in C# when designing classes is the lack of support for multiple inheritance, which makes that one spot for inheriting from a very valuable spot indeed. For the purposes of this discussion, we&amp;rsquo;ll start with a simple implementation of the &lt;a href="http://en.wikipedia.org/wiki/Specification_pattern" target="_blank" rel="noopener noreferrer" class="external-link"&gt;specification pattern&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; :&lt;/p&gt;</description><content:encoded>&lt;p&gt;One of the walls I hit the most in C# when designing classes is the lack of support for multiple inheritance, which makes that one spot for inheriting from a very valuable spot indeed. For the purposes of this discussion, we&amp;rsquo;ll start with a simple implementation of the &lt;a href="http://en.wikipedia.org/wiki/Specification_pattern" target="_blank" rel="noopener noreferrer" class="external-link"&gt;specification pattern&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; :&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ISpecification&lt;/span&gt;&amp;lt;T&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt; IsSatisfiedBy(T item);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The evaluation is all set, but now we feel the need to add the boolean operators And, Or, and Not. Most developers follow the route of changing the interface to add And, Or and Not, create a base (abstract) class (let call it &lt;em&gt;SpecificationBase&lt;/em&gt;) implementing the operators and leaving the &lt;em&gt;IsSatisfiedBy&lt;/em&gt; method abstract. The downside of this approach is that concrete implementations of specifications are forced to give up their one empty slot for inheritance. An alternative is to leave the interface as is, and add extension methods that operate on the interface - no inheritance needed.&lt;/p&gt;
&lt;div class="code-block-wrapper"&gt;
&lt;div class="code-block-header"&gt;
&lt;span class="code-block-lang"&gt;C#&lt;/span&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;
&lt;table style="border-spacing:0;padding:0;margin:0;border:0;"&gt;&lt;tr&gt;&lt;td style="vertical-align:top;padding:0;margin:0;border:0;"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;2
&lt;/span&gt;&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%"&gt;
&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; ISpecification&amp;lt;T&amp;gt; And&amp;lt;T&amp;gt; (&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt; ISpecification&amp;lt;T&amp;gt; left, ISpecification&amp;lt;T&amp;gt; right) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; AndSpecification&amp;lt;T&amp;gt;(left, right);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The downside with this implementation is that you need to import the namespace in order use the methods. Although most people will probably do this automatically anyway, it might not be clear what operations the class has to offer.&lt;/p&gt;
&lt;p&gt;My question is this : In the context of a reusable class library like &lt;a href="http://www.github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, is using extension methods in this way evil?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/-f8ssjFhD1k?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Kyle Glenn&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/extension?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>MS-LPL</title><link>https://riaan.hanekom.io/2008/09/10/ms-lpl/</link><pubDate>Wed, 10 Sep 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/09/10/ms-lpl/</guid><description>&lt;p&gt;&lt;a href="http://tirania.org/archive/2008/Sep-07.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;As Miguel pointed out&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://www.codeplex.com/MEF/license" target="_blank" rel="noopener noreferrer" class="external-link"&gt;this&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; just seems &amp;hellip; well, evil.&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;a href="http://tirania.org/archive/2008/Sep-07.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;As Miguel pointed out&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, &lt;a href="http://www.codeplex.com/MEF/license" target="_blank" rel="noopener noreferrer" class="external-link"&gt;this&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; just seems &amp;hellip; well, evil.&lt;/p&gt;
&lt;p&gt;Notice the last clause in Section 2 :&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(F) Platform Limitation- The licenses granted in sections 2(A) &amp;amp; 2(B) extend only to the software or derivative works that you create that run on a Microsoft Windows operating system product.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Wow. Can&amp;rsquo;t believe that you can still get away with open-sourcing code and then choosing a license like that.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a great need for .NET application developers and consumers for them to be able to be cross-platform compatible - limiting yourself to a Windows environment limits your audience and adoption.&lt;/p&gt;
&lt;p&gt;Hats off to Miguel and the Mono team for keeping &lt;a href="http://www.mono-project.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Mono&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; alive and well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/L17H6upTC-8?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/contract?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Vimperator</title><link>https://riaan.hanekom.io/2008/09/09/vimperator/</link><pubDate>Tue, 09 Sep 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/09/09/vimperator/</guid><description>&lt;p&gt;The &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/4891" target="_blank" rel="noopener noreferrer" class="external-link"&gt;best Firefox add-on&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; ever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/MzdoJwjayOs?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Dan Gold&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/shortcut?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;The &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/4891" target="_blank" rel="noopener noreferrer" class="external-link"&gt;best Firefox add-on&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; ever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/MzdoJwjayOs?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Dan Gold&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/shortcut?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics 1.3 Beta Release</title><link>https://riaan.hanekom.io/2008/07/07/ngenerics-1.3-beta-release/</link><pubDate>Mon, 07 Jul 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/07/07/ngenerics-1.3-beta-release/</guid><description>&lt;p&gt;We&amp;rsquo;ve just released NGenerics 1.3 Beta - &lt;a href="http://www.codeplex.com/NGenerics/Release/ProjectReleases.aspx?ReleaseId=5557" target="_blank" rel="noopener noreferrer" class="external-link"&gt;grab it while it&amp;rsquo;s hot!&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; Also, don&amp;rsquo;t forget to &lt;a href="http://www.codeplex.com/NGenerics/Thread/List.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;give feedback&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on new features / anything that really bugs you.&lt;/p&gt;</description><content:encoded>&lt;p&gt;We&amp;rsquo;ve just released NGenerics 1.3 Beta - &lt;a href="http://www.codeplex.com/NGenerics/Release/ProjectReleases.aspx?ReleaseId=5557" target="_blank" rel="noopener noreferrer" class="external-link"&gt;grab it while it&amp;rsquo;s hot!&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; Also, don&amp;rsquo;t forget to &lt;a href="http://www.codeplex.com/NGenerics/Thread/List.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;give feedback&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on new features / anything that really bugs you.&lt;/p&gt;
&lt;p&gt;Quite a bit of time passed between this release and the Alpha release. We&amp;rsquo;re currently working on achieving a quicker release schedule, about one release every month or so (alpha, beta, release version).&lt;/p&gt;
&lt;p&gt;In doing this, we hope to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get features out there quicker.&lt;/li&gt;
&lt;li&gt;Decrease the time to get feedback on what we&amp;rsquo;ve done.&lt;/li&gt;
&lt;li&gt;Keep the momentum.&lt;/li&gt;
&lt;li&gt;Generate less bugs per release as the scope of releases are reduced.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;NGenerics 1.3 is more or less fixed in scope now. All the release version will add is some more unit tests, bug fixes, and updates to documentation. As always, you can request new features for version 1.4 &lt;a href="http://www.codeplex.com/NGenerics/WorkItem/List.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/466ENaLuhLY?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markus Spiske&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Cayla Rose</title><link>https://riaan.hanekom.io/2008/06/26/cayla-rose/</link><pubDate>Thu, 26 Jun 2008 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2008/06/26/cayla-rose/</guid><description>&lt;p&gt;I&amp;rsquo;m a little bit late with this announcement - a month or so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Welcome to the world, little one!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="cayla137.jpg" alt="Cayla Rose Hanekom" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Cayla Rose Hanekom was born on the 4th of June 2008 in Johannesburg, South Africa, weighing a whopping 4.1 kg.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/CAMwIxYk5Xg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Jörg Angeli&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/sunrise?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;m a little bit late with this announcement - a month or so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Welcome to the world, little one!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="cayla137.jpg" alt="Cayla Rose Hanekom" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Cayla Rose Hanekom was born on the 4th of June 2008 in Johannesburg, South Africa, weighing a whopping 4.1 kg.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/CAMwIxYk5Xg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Jörg Angeli&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/sunrise?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Team Foundation Server</title><link>https://riaan.hanekom.io/2007/07/05/team-foundation-server/</link><pubDate>Thu, 05 Jul 2007 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2007/07/05/team-foundation-server/</guid><description>&lt;p&gt;You would think that the integration between Visual Studio (using the TFS client) and TFS would be better than the Visual SourceSafe integration. Nope, the same annoying bugs that were present in the Visual SourceSafe integration has rocked up in TFS, so I&amp;rsquo;m assuming someone extended the old codebase.&lt;/p&gt;
&lt;p&gt;After some unsuccessful check-ins (read, breaking the build) when I&amp;rsquo;ve worked disconnected on NGenerics, I&amp;rsquo;ve given up on TFS. Well, not quite, but as soon as the &lt;a href="https://archive.codeplex.com/?p=svnbridge" target="_blank" rel="noopener noreferrer" class="external-link"&gt;SVN bridge&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; brings out a stable version, I&amp;rsquo;m switching.&lt;/p&gt;</description><content:encoded>&lt;p&gt;You would think that the integration between Visual Studio (using the TFS client) and TFS would be better than the Visual SourceSafe integration. Nope, the same annoying bugs that were present in the Visual SourceSafe integration has rocked up in TFS, so I&amp;rsquo;m assuming someone extended the old codebase.&lt;/p&gt;
&lt;p&gt;After some unsuccessful check-ins (read, breaking the build) when I&amp;rsquo;ve worked disconnected on NGenerics, I&amp;rsquo;ve given up on TFS. Well, not quite, but as soon as the &lt;a href="https://archive.codeplex.com/?p=svnbridge" target="_blank" rel="noopener noreferrer" class="external-link"&gt;SVN bridge&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; brings out a stable version, I&amp;rsquo;m switching.&lt;/p&gt;
&lt;p&gt;Congratulations to the CodePlex team for trying to fill the gap - although it took Subsonic abandoning TFS to get to this point.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/luPOnViYl7I?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Tanguy Sauvin&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/bug?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Unit testing and mocks</title><link>https://riaan.hanekom.io/2007/05/12/unit-testing-and-mocks/</link><pubDate>Sat, 12 May 2007 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2007/05/12/unit-testing-and-mocks/</guid><description>&lt;p&gt;I&amp;rsquo;m one of the converted when it comes to test-driven development. One of the main &amp;ldquo;aha&amp;rdquo; moments for me is not to write unit tests - it&amp;rsquo;s writing testable code. Any code that&amp;rsquo;s testable is sure to be of a higher quality and easier to maintain than typical spaghetti code.&lt;/p&gt;
&lt;p&gt;That brings me to the second part of the title - mocks. The art of mocking objects have taken off over the last couple of years. I feel that there is a danger of abusing them to test code, when the code is not written in a testable way. I&amp;rsquo;ve seen examples where developers use mocking so much that what you&amp;rsquo;re testing is the mock object&amp;rsquo;s functionality - and not your code. In cases like these you&amp;rsquo;d be much better off refactoring than mocking dependencies.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;m one of the converted when it comes to test-driven development. One of the main &amp;ldquo;aha&amp;rdquo; moments for me is not to write unit tests - it&amp;rsquo;s writing testable code. Any code that&amp;rsquo;s testable is sure to be of a higher quality and easier to maintain than typical spaghetti code.&lt;/p&gt;
&lt;p&gt;That brings me to the second part of the title - mocks. The art of mocking objects have taken off over the last couple of years. I feel that there is a danger of abusing them to test code, when the code is not written in a testable way. I&amp;rsquo;ve seen examples where developers use mocking so much that what you&amp;rsquo;re testing is the mock object&amp;rsquo;s functionality - and not your code. In cases like these you&amp;rsquo;d be much better off refactoring than mocking dependencies.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s my recommendation: focus on writing testable code, and try to reduce the use of mocks. Use it when you have no other method available to test your code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/flEStjHTY14?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Leio McLaren&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/tightrope?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>New Company, new job, NGenerics</title><link>https://riaan.hanekom.io/2007/05/04/new-company-new-job-ngenerics/</link><pubDate>Fri, 04 May 2007 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2007/05/04/new-company-new-job-ngenerics/</guid><description>&lt;p&gt;I&amp;rsquo;ve left Avision to join &lt;a href="http://www.intervate.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Intervate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Although I miss Avision and its people tremendously, I felt that I&amp;rsquo;ve reached my growth ceiling and that I needed some new challenges.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been an employee at &lt;a href="http://www.intervate.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Intervate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for two months now - and it&amp;rsquo;s a great company : Microsoft Gold Partner, intelligent and competent people, exciting projects and learning opportunities.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve left Avision to join &lt;a href="http://www.intervate.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Intervate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;. Although I miss Avision and its people tremendously, I felt that I&amp;rsquo;ve reached my growth ceiling and that I needed some new challenges.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been an employee at &lt;a href="http://www.intervate.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Intervate&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; for two months now - and it&amp;rsquo;s a great company : Microsoft Gold Partner, intelligent and competent people, exciting projects and learning opportunities.&lt;/p&gt;
&lt;p&gt;At the moment I&amp;rsquo;m somewhat of a contractor - but that should pass pretty soon.&lt;/p&gt;
&lt;p&gt;Other than that, I&amp;rsquo;m working hard to get the 1.3 release of &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; out of the door. We are focusing on the quality of the library - thus we&amp;rsquo;ve introduced a couple of breaking changes (like the changing of namespaces). After this release, &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; will remain stable (and backwards compatible). As we go along and change it, we&amp;rsquo;ll start marking methods as deprecated whenever we break compatibility with previous releases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Agx5_TLsIf4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Fatos Bytyqi&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/desk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Sealed classes</title><link>https://riaan.hanekom.io/2007/05/04/sealed-classes/</link><pubDate>Fri, 04 May 2007 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2007/05/04/sealed-classes/</guid><description>&lt;p&gt;As part of version 1.3 of &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, I&amp;rsquo;ve removed most of the sealed keywords from the classes (where it made sense). It took me a while, but I&amp;rsquo;ve accepted the following rule (and Microsoft is of the same opinion, it seems) :&lt;/p&gt;</description><content:encoded>&lt;p&gt;As part of version 1.3 of &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, I&amp;rsquo;ve removed most of the sealed keywords from the classes (where it made sense). It took me a while, but I&amp;rsquo;ve accepted the following rule (and Microsoft is of the same opinion, it seems) :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Never seal a class unless there&amp;rsquo;s a very good reason to do so (like it being internal, security reasons, etc). Programmers using your library will use it many creative ways you can&amp;rsquo;t even imagine, and sealing a class limits that creativity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also see the post &lt;a href="http://weblogs.asp.net/cazzu/archive/2005/08/29/IHateSealed.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/6ZZh8kOyW-4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Adam Wilson&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/sealed?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics 1.2 released</title><link>https://riaan.hanekom.io/2007/03/28/ngenerics-1.2-released/</link><pubDate>Wed, 28 Mar 2007 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2007/03/28/ngenerics-1.2-released/</guid><description>&lt;p&gt;Yeah, &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics 1.2&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has been released!&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t checked it out yet, &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;do so now&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - no decent programmer should go without a toolbox of data structures and algorithms.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Yeah, &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics 1.2&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has been released!&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t checked it out yet, &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;do so now&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - no decent programmer should go without a toolbox of data structures and algorithms.&lt;/p&gt;
&lt;p&gt;Some new features in &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NGenerics 1.2&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; includes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ngenerics/ngenerics/wiki/RedBlackTree" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Red Black Tree&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ngenerics/ngenerics/wiki/HashList" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Hash List&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ngenerics/ngenerics/wiki/ObjectMatrix" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Object Matrix&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;ReadOnlyPropertyList&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ngenerics/ngenerics/wiki/Prim" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Prim&amp;rsquo;s Minimal Spanning Tree Algorithm&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And if you try it, be sure to give some &lt;a href="https://github.com/ngenerics/ngenerics/issues" target="_blank" rel="noopener noreferrer" class="external-link"&gt;feedback&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - we&amp;rsquo;re always looking for &lt;a href="https://github.com/ngenerics/ngenerics/issues" target="_blank" rel="noopener noreferrer" class="external-link"&gt;new ideas / improvements&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/ieic5Tq8YMk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Chris Ried&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/@rhanekom/likes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>NGenerics Born</title><link>https://riaan.hanekom.io/2006/12/28/ngenerics-born/</link><pubDate>Thu, 28 Dec 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/12/28/ngenerics-born/</guid><description>&lt;p&gt;My &lt;a href="https://www.codeproject.com/Articles/16337/Back-to-Basics-Generic-Data-Structures-and-Algorit" target="_blank" rel="noopener noreferrer" class="external-link"&gt;data structures article on CodeProject&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has grown up and became a project on &lt;a href="http://www.codeplex.com/NGenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;del&gt;CodePlex&lt;/del&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;GitHub&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;</description><content:encoded>&lt;p&gt;My &lt;a href="https://www.codeproject.com/Articles/16337/Back-to-Basics-Generic-Data-Structures-and-Algorit" target="_blank" rel="noopener noreferrer" class="external-link"&gt;data structures article on CodeProject&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; has grown up and became a project on &lt;a href="http://www.codeplex.com/NGenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;&lt;del&gt;CodePlex&lt;/del&gt;&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; &lt;a href="https://github.com/ngenerics/ngenerics" target="_blank" rel="noopener noreferrer" class="external-link"&gt;GitHub&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To do this, I had to make a couple of major changes - like changing all the namespaces to NGenerics.*.&lt;/p&gt;
&lt;p&gt;The new version includes a Binary Search Tree, Euclid&amp;rsquo;s Algorithm, and a couple of changes to the BinaryTree, GeneralTree, and Matrix classes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/vrbZVyX2k4I?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Markus Spiske&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Generic Data Structures and Algorithms in .NET 2.0</title><link>https://riaan.hanekom.io/2006/12/12/generic-data-structures-and-algorithms-in-.net-2.0/</link><pubDate>Tue, 12 Dec 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/12/12/generic-data-structures-and-algorithms-in-.net-2.0/</guid><description>&lt;p&gt;I&amp;rsquo;ve posted an article on generic data structures on CodeProject.&lt;/p&gt;
&lt;p&gt;At the moment, it provides the following data structures :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deque&lt;/li&gt;
&lt;li&gt;GeneralTree&lt;/li&gt;
&lt;li&gt;BinaryTree&lt;/li&gt;
&lt;li&gt;SorterList&lt;/li&gt;
&lt;li&gt;Heap&lt;/li&gt;
&lt;li&gt;Bag&lt;/li&gt;
&lt;li&gt;Set&lt;/li&gt;
&lt;li&gt;Graph&lt;/li&gt;
&lt;li&gt;Association&lt;/li&gt;
&lt;li&gt;Matrix&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve also implemented a couple of sorting algorithms.&lt;/p&gt;
&lt;p&gt;If you get a change, &lt;a href="https://www.codeproject.com/Articles/16337/Back-to-Basics-Generic-Data-Structures-and-Algorit" target="_blank" rel="noopener noreferrer" class="external-link"&gt;go check it out&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and give me some feedback.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve posted an article on generic data structures on CodeProject.&lt;/p&gt;
&lt;p&gt;At the moment, it provides the following data structures :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deque&lt;/li&gt;
&lt;li&gt;GeneralTree&lt;/li&gt;
&lt;li&gt;BinaryTree&lt;/li&gt;
&lt;li&gt;SorterList&lt;/li&gt;
&lt;li&gt;Heap&lt;/li&gt;
&lt;li&gt;Bag&lt;/li&gt;
&lt;li&gt;Set&lt;/li&gt;
&lt;li&gt;Graph&lt;/li&gt;
&lt;li&gt;Association&lt;/li&gt;
&lt;li&gt;Matrix&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve also implemented a couple of sorting algorithms.&lt;/p&gt;
&lt;p&gt;If you get a change, &lt;a href="https://www.codeproject.com/Articles/16337/Back-to-Basics-Generic-Data-Structures-and-Algorit" target="_blank" rel="noopener noreferrer" class="external-link"&gt;go check it out&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, and give me some feedback.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/BW0vK-FA3eg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Clint Adair&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/data?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>I see the sea shore</title><link>https://riaan.hanekom.io/2006/10/04/i-see-the-sea-shore/</link><pubDate>Wed, 04 Oct 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/10/04/i-see-the-sea-shore/</guid><description>&lt;p&gt;I&amp;rsquo;m back from a holiday of doing nothing on Ballito&amp;rsquo;s beautiful coast line (KwaZulu Natal, South Africa)&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="Shore.jpg" alt="Sea shore" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Back to reality&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/W3nPLWO1ePU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/rest?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;m back from a holiday of doing nothing on Ballito&amp;rsquo;s beautiful coast line (KwaZulu Natal, South Africa)&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src="Shore.jpg" alt="Sea shore" loading="lazy"&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Back to reality&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/W3nPLWO1ePU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/rest?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>XLANGS.BTENGINE.BTXTIMERMESSAGE</title><link>https://riaan.hanekom.io/2006/09/26/xlangs.btengine.btxtimermessage/</link><pubDate>Tue, 26 Sep 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/09/26/xlangs.btengine.btxtimermessage/</guid><description>&lt;p&gt;Wow. BizTalk is always full of surprises.&lt;/p&gt;
&lt;p&gt;Stephen W. Thomas has an explanation &lt;a href="http://geekswithblogs.net/sthomas/archive/2004/11/17/15201.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/vZawEq0Eexo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Marcelo Leal&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/timer?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;Wow. BizTalk is always full of surprises.&lt;/p&gt;
&lt;p&gt;Stephen W. Thomas has an explanation &lt;a href="http://geekswithblogs.net/sthomas/archive/2004/11/17/15201.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/vZawEq0Eexo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Marcelo Leal&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/timer?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>A very interesting hobby</title><link>https://riaan.hanekom.io/2006/09/08/a-very-interesting-hobby/</link><pubDate>Fri, 08 Sep 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/09/08/a-very-interesting-hobby/</guid><description>&lt;p&gt;I&amp;rsquo;ve grown interested in Chess programming this year, and started building my own chess engine that will understand the WinBoard protocol. Chess programming is fascinating. Initial development is difficult but I&amp;rsquo;m starting off with the basics :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A simple bitboard representation.&lt;/li&gt;
&lt;li&gt;A simple implementation of the Alpha-Beta algorithm.&lt;/li&gt;
&lt;li&gt;Implementation of the WinBoard protocol.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When that&amp;rsquo;s done there&amp;rsquo;s going to be ample room for improvement (twenty or so algorithms left to try out and then you can still play around with different representations of the board).&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve grown interested in Chess programming this year, and started building my own chess engine that will understand the WinBoard protocol. Chess programming is fascinating. Initial development is difficult but I&amp;rsquo;m starting off with the basics :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A simple bitboard representation.&lt;/li&gt;
&lt;li&gt;A simple implementation of the Alpha-Beta algorithm.&lt;/li&gt;
&lt;li&gt;Implementation of the WinBoard protocol.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When that&amp;rsquo;s done there&amp;rsquo;s going to be ample room for improvement (twenty or so algorithms left to try out and then you can still play around with different representations of the board).&lt;/p&gt;
&lt;p&gt;Chess engines can compete against each other on sites like &lt;a href="http://loirechecs.chez-alice.fr/chesswar/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;these&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; - I&amp;rsquo;d love to do this soon.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/eilPz30MSUo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/chess?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Time is of the essence (or so it seems)</title><link>https://riaan.hanekom.io/2006/09/08/time-is-of-the-essence-or-so-it-seems/</link><pubDate>Fri, 08 Sep 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/09/08/time-is-of-the-essence-or-so-it-seems/</guid><description>&lt;p&gt;There&amp;rsquo;s been some long gaps between blog entries due to the amount of time I can afford to write.&lt;/p&gt;
&lt;p&gt;What am I up to these days?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Still working my full time day job as a systems developer (I actually think it qualifies as a day-night job).&lt;/li&gt;
&lt;li&gt;Writing (and fixing) articles for CodeProject.&lt;/li&gt;
&lt;li&gt;Doing lots and lots of R&amp;amp;D (new frameworks, applications, technologies are emerging at an incredible rate these days). I blame this one on Microsoft with their pre-release software.&lt;/li&gt;
&lt;li&gt;Spending lots of time on my studies (B.Sc. Hon in Information Systems). Didn&amp;rsquo;t think it would take up this much time when I started it, but I&amp;rsquo;m almost there&amp;hellip;&lt;/li&gt;
&lt;li&gt;Working on the next big thing, which will hopefully provide an extra revenue stream.&lt;/li&gt;
&lt;li&gt;Spending time with the family ;)&lt;/li&gt;
&lt;li&gt;Trying to get some actual sleep.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m taking a break soon to spent all my time on a beach for a couple of days. Live Writer is coming with, I&amp;rsquo;ll post a pic of South Africa&amp;rsquo;s beautiful coastline.&lt;/p&gt;</description><content:encoded>&lt;p&gt;There&amp;rsquo;s been some long gaps between blog entries due to the amount of time I can afford to write.&lt;/p&gt;
&lt;p&gt;What am I up to these days?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Still working my full time day job as a systems developer (I actually think it qualifies as a day-night job).&lt;/li&gt;
&lt;li&gt;Writing (and fixing) articles for CodeProject.&lt;/li&gt;
&lt;li&gt;Doing lots and lots of R&amp;amp;D (new frameworks, applications, technologies are emerging at an incredible rate these days). I blame this one on Microsoft with their pre-release software.&lt;/li&gt;
&lt;li&gt;Spending lots of time on my studies (B.Sc. Hon in Information Systems). Didn&amp;rsquo;t think it would take up this much time when I started it, but I&amp;rsquo;m almost there&amp;hellip;&lt;/li&gt;
&lt;li&gt;Working on the next big thing, which will hopefully provide an extra revenue stream.&lt;/li&gt;
&lt;li&gt;Spending time with the family ;)&lt;/li&gt;
&lt;li&gt;Trying to get some actual sleep.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m taking a break soon to spent all my time on a beach for a couple of days. Live Writer is coming with, I&amp;rsquo;ll post a pic of South Africa&amp;rsquo;s beautiful coastline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Hk89vWuWXfE?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/time?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Test - Please Ignore</title><link>https://riaan.hanekom.io/2006/08/21/test-please-ignore/</link><pubDate>Mon, 21 Aug 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/08/21/test-please-ignore/</guid><description>&lt;p&gt;Wow, this actually &lt;strong&gt;works&lt;/strong&gt;! (Testing with Live Writer).&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/photos/AvV5rJl1vcU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ShareGrid&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/test?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;Wow, this actually &lt;strong&gt;works&lt;/strong&gt;! (Testing with Live Writer).&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/photos/AvV5rJl1vcU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;ShareGrid&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/test?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>First CodeProject Article</title><link>https://riaan.hanekom.io/2006/08/17/first-codeproject-article/</link><pubDate>Thu, 17 Aug 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/08/17/first-codeproject-article/</guid><description>&lt;p&gt;Got my first &lt;a href="https://www.codeproject.com/Articles/15201/Smoothy-Event-Log-Viewer" target="_blank" rel="noopener noreferrer" class="external-link"&gt;CodeProject article&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; submitted!&lt;/p&gt;
&lt;p&gt;Yes I know, it&amp;rsquo;s small and still a work in progress but it&amp;rsquo;s a start!&lt;/p&gt;
&lt;p&gt;The URL&amp;rsquo;s going to change soon, I&amp;rsquo;ll update this post with the new link.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/IhsaTDKzdwg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NeONBRAND&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/write?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;Got my first &lt;a href="https://www.codeproject.com/Articles/15201/Smoothy-Event-Log-Viewer" target="_blank" rel="noopener noreferrer" class="external-link"&gt;CodeProject article&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; submitted!&lt;/p&gt;
&lt;p&gt;Yes I know, it&amp;rsquo;s small and still a work in progress but it&amp;rsquo;s a start!&lt;/p&gt;
&lt;p&gt;The URL&amp;rsquo;s going to change soon, I&amp;rsquo;ll update this post with the new link.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/IhsaTDKzdwg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NeONBRAND&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/write?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Creating or Input Multiple Messages from or to Biztalk Maps</title><link>https://riaan.hanekom.io/2006/07/19/creating-or-input-multiple-messages-from-or-to-biztalk-maps/</link><pubDate>Wed, 19 Jul 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/07/19/creating-or-input-multiple-messages-from-or-to-biztalk-maps/</guid><description>&lt;p&gt;Sure, we all know how to do that by know, right?&lt;/p&gt;
&lt;p&gt;Funny thing is, all the blog entries I&amp;rsquo;ve seen like the ones &lt;a href="http://www.topxml.com/BizTalk-2004/re-3136_Mapping-Many-Messages-to-One-Inside-the-Mapper-in-BizTalk-2004.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/markhsch/archive/2004/11/30/272573.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, end up creating a new map, usually situated in the root of your assembly (or event worse, create temporary orchestrations to do that). In order to move it to another folder in your project you&amp;rsquo;ll have to edit the XML contained inside the map since it contains relative paths to the schemas mapped (and watch out for those namespaces).&lt;/p&gt;</description><content:encoded>&lt;p&gt;Sure, we all know how to do that by know, right?&lt;/p&gt;
&lt;p&gt;Funny thing is, all the blog entries I&amp;rsquo;ve seen like the ones &lt;a href="http://www.topxml.com/BizTalk-2004/re-3136_Mapping-Many-Messages-to-One-Inside-the-Mapper-in-BizTalk-2004.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/markhsch/archive/2004/11/30/272573.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, end up creating a new map, usually situated in the root of your assembly (or event worse, create temporary orchestrations to do that). In order to move it to another folder in your project you&amp;rsquo;ll have to edit the XML contained inside the map since it contains relative paths to the schemas mapped (and watch out for those namespaces).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an easier way to do it :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create your empty map exactly where you want it.&lt;/li&gt;
&lt;li&gt;Add a transforms shape and open up the properties.&lt;/li&gt;
&lt;li&gt;Instead of choosing new map, choose existing map.&lt;/li&gt;
&lt;li&gt;Select your newly created (empty) map.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The BizTalk Editor will modify the map to take the new message types - multiple if you selected them.&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/photos/o0l-M8W_7wA?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Chris Lawton&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/map?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Sharepoint Object Model - Good Practices</title><link>https://riaan.hanekom.io/2006/07/18/sharepoint-object-model-good-practices/</link><pubDate>Tue, 18 Jul 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/07/18/sharepoint-object-model-good-practices/</guid><description>&lt;p&gt;&lt;strong&gt;Dispose those objects!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using the SharePoint object model anywhere, make sure that you dispose any objects that you create (not those that the SharePoint object model creates for you, like calling GetContextWeb()).&lt;/p&gt;
&lt;p&gt;These objects have a small memory footprint visible to the Garbage Collector, but a large amount of unmanaged resources (effectively not visible to the Garbage Collector).&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t dispose of them, the GC will not be in any rush to free up the memory used by these objects since it can&amp;rsquo;t (or won&amp;rsquo;t) see the bigger picture. The result? OutofMemoryExceptions when doing any operation that creates a lot of these objects and not disposing them.&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;strong&gt;Dispose those objects!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using the SharePoint object model anywhere, make sure that you dispose any objects that you create (not those that the SharePoint object model creates for you, like calling GetContextWeb()).&lt;/p&gt;
&lt;p&gt;These objects have a small memory footprint visible to the Garbage Collector, but a large amount of unmanaged resources (effectively not visible to the Garbage Collector).&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t dispose of them, the GC will not be in any rush to free up the memory used by these objects since it can&amp;rsquo;t (or won&amp;rsquo;t) see the bigger picture. The result? OutofMemoryExceptions when doing any operation that creates a lot of these objects and not disposing them.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Side track : this is &lt;a href="http://riaanhanekom.com/2006/07/15/net-cf-part-1" target="_blank" rel="noopener noreferrer" class="external-link"&gt;what happens to the SqlCeCommand objects&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;See the full details on &amp;ldquo;Best Coding Practices&amp;rdquo; for SharePoint in this &lt;a href="http://msdn2.microsoft.com/en-us/library/ms778813.aspx" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Microsoft article&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One thing&amp;rsquo;s for certain - we can&amp;rsquo;t ignore the unmanaged world yet&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/c7Ev87qEkRc?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Giu Vicente&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>.NET CF - Part 1</title><link>https://riaan.hanekom.io/2006/07/15/.net-cf-part-1/</link><pubDate>Sat, 15 Jul 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/07/15/.net-cf-part-1/</guid><description>&lt;p&gt;I&amp;rsquo;ve been porting an application of ours to .NET CF 2.0, Mobile 5.0 and SQL Mobile the past couple of weeks.&lt;/p&gt;
&lt;p&gt;.NET CF 2.0 is impressive. The .NET Compact Framework 1 was a bit lacking in functionality - it felt like Microsoft shipped an unfinished product. .NET CF 2 provides a lot of new functionality : Pocket Outlook Access, Phone and messaging capabilities, new controls, etc. Basically everything the guys at &lt;a href="http://www.opennetcf.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;OpenNet CF&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; had in their previous version, is now in the new version of the framework. They&amp;rsquo;ve released a new version of their library that adds even more functionality - download it and use it if you work with the Compact Framework.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve been porting an application of ours to .NET CF 2.0, Mobile 5.0 and SQL Mobile the past couple of weeks.&lt;/p&gt;
&lt;p&gt;.NET CF 2.0 is impressive. The .NET Compact Framework 1 was a bit lacking in functionality - it felt like Microsoft shipped an unfinished product. .NET CF 2 provides a lot of new functionality : Pocket Outlook Access, Phone and messaging capabilities, new controls, etc. Basically everything the guys at &lt;a href="http://www.opennetcf.org/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;OpenNet CF&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; had in their previous version, is now in the new version of the framework. They&amp;rsquo;ve released a new version of their library that adds even more functionality - download it and use it if you work with the Compact Framework.&lt;/p&gt;
&lt;p&gt;Working with generics is an absolute godsend - can&amp;rsquo;t tell you how much the incessant casting of objects chewed on my nerves&amp;hellip;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m a bit disappointed in the SQL Mobile zone - all the old features (read &amp;ldquo;bugs) are still there like the failure of cleaning up SqlCeCommand objects. That said, being able to make more than one connection to the database and remove my Singleton connection manager class is great! &lt;em&gt;Side track : Note, Making the connection to the database is a real bottleneck. For batch operations such as inserts (Microsoft, when can we get batch transactions on Mobile?), it&amp;rsquo;s best to keep a connection open and reuse the same command - you&amp;rsquo;ll notice the speed difference when you don&amp;rsquo;t.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Microsoft has added support in the Visual Studio IDE for designing SQL Mobile databases (avoiding the pain of typing in SQL queries using a stencil on the device). Works great, gets deployed onto your device and you can even query it! What I&amp;rsquo;m missing there (and it&amp;rsquo;s driving me nuts) is support for ordering columns (I&amp;rsquo;m adding a new column and I want it to be next to the primary key), renaming tables (the way I&amp;rsquo;ve found to do this is to recreate the entire table), and stored procedures.&lt;/p&gt;
&lt;p&gt;OK, the stored procedures is going a bit too far, but it would be nice, wouldn&amp;rsquo;t it?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/ejPPVWDPeGU?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;John-Paul Joseph Henry&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/phone?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>SSIS Woes</title><link>https://riaan.hanekom.io/2006/06/02/ssis-woes/</link><pubDate>Fri, 02 Jun 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/06/02/ssis-woes/</guid><description>&lt;p&gt;I&amp;rsquo;ve been dabbling with SQL 2005 a lot these days and two features impress me: SSIS and Reporting Services.&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;might&lt;/em&gt; find it difficult to actually deploy a SSIS package.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m missing something with calling a web service in SSIS&amp;hellip; Even when you change the connection manager setting for the HTTP Connection manager to a new value (say we deploy to a live environment), it still reads the WSDL file you provided and calls the wrong web service (&lt;a href="http://www.ethereal.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ethereal&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is the coolest network tracing tool ever btw.).&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;ve been dabbling with SQL 2005 a lot these days and two features impress me: SSIS and Reporting Services.&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;might&lt;/em&gt; find it difficult to actually deploy a SSIS package.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m missing something with calling a web service in SSIS&amp;hellip; Even when you change the connection manager setting for the HTTP Connection manager to a new value (say we deploy to a live environment), it still reads the WSDL file you provided and calls the wrong web service (&lt;a href="http://www.ethereal.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ethereal&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; is the coolest network tracing tool ever btw.).&lt;/p&gt;
&lt;p&gt;And deployment!&lt;/p&gt;
&lt;p&gt;There doesn&amp;rsquo;t seem to be a way (enlighten me if you know a way to do this) to specify a username and a password to your HTTP connection manager at any time but design time - i.e. it&amp;rsquo;s saved with your SSIS package.&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;strong&gt;Now comes the problem&lt;/strong&gt; : by default SSIS encrypts sensitive data like usernames and passwords in the XML file. The encryption type defaults to &lt;em&gt;&amp;ldquo;Encrypt With User Key&amp;rdquo;&lt;/em&gt; which means that SSIS encrypts the file with your username token - no other user can run your package.&lt;/p&gt;
&lt;p&gt;Set this to &lt;em&gt;&amp;ldquo;Encrypt Sensitive With Password&amp;rdquo;&lt;/em&gt;, deploy and run it - it works! Now try to schedule the SSIS package with a SQL Agent Job - it fails. Try to run it manually with dtsexec: it fails, stating that it can&amp;rsquo;t decrypt the data even though you&amp;rsquo;ve specified the password for the package &lt;em&gt;(Side track : no useful information comes out of running a SSIS package manually. If you want to know what actually went wrong, use dtsexec)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;One final try : &lt;em&gt;&amp;ldquo;SQL Storage&amp;rdquo;&lt;/em&gt; for the package, which leaves in unencrypted and depends on the database security to secure sensitive information. You cannot at present deploy a package to SQL Storage (unencrypted) from Visual Studio (again, enlighten me if you know how). Instead, open SQL Server Management Studio and find the &amp;ldquo;Save a copy&amp;rdquo; option under the file menu - there you can select a SQL server to deploy to.&lt;/p&gt;
&lt;p&gt;Otherwise than the deployment issues, &lt;em&gt;&lt;strong&gt;great&lt;/strong&gt;&lt;/em&gt; work done by Microsoft on SSIS and Reporting Services!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/Sot0f3hQQ4Y?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Dominik Scythe&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/database?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Windows Mobile 5.0</title><link>https://riaan.hanekom.io/2006/05/20/windows-mobile-5.0/</link><pubDate>Sat, 20 May 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/05/20/windows-mobile-5.0/</guid><description>&lt;p&gt;Yeah! Got my new toy - an IMATE JAMIN with (important!) Windows Mobile 5.0. I&amp;rsquo;ll be playing around with the new SQL Mobile and .NET Compact Framework 2.0 on this device - expect a storm of new posts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/CpHNKNRwXps?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NASA&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/windows?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;Yeah! Got my new toy - an IMATE JAMIN with (important!) Windows Mobile 5.0. I&amp;rsquo;ll be playing around with the new SQL Mobile and .NET Compact Framework 2.0 on this device - expect a storm of new posts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/CpHNKNRwXps?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;NASA&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/windows?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Biztalk Listen Shape</title><link>https://riaan.hanekom.io/2006/05/19/biztalk-listen-shape/</link><pubDate>Fri, 19 May 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/05/19/biztalk-listen-shape/</guid><description>&lt;p&gt;I&amp;rsquo;m no Scott Woodgate, but I think I know a fair amount about BizTalk. However, it seems that I never recognized what the Listen shape actually does (you don&amp;rsquo;t see this mentioned very often btw.). Turns out that this little shape can solve many of the problems we&amp;rsquo;re currently having, mainly correlation issues, like situations where the message you are waiting for might never arrive, keeping your orchestration in a dehydrated state, waiting forever.&lt;/p&gt;</description><content:encoded>&lt;p&gt;I&amp;rsquo;m no Scott Woodgate, but I think I know a fair amount about BizTalk. However, it seems that I never recognized what the Listen shape actually does (you don&amp;rsquo;t see this mentioned very often btw.). Turns out that this little shape can solve many of the problems we&amp;rsquo;re currently having, mainly correlation issues, like situations where the message you are waiting for might never arrive, keeping your orchestration in a dehydrated state, waiting forever.&lt;/p&gt;
&lt;p&gt;This shape works like a parallel branch, but with one major difference : Only one leg of the shape needs to complete for the orchestration to continue, while in a parallel branch all branches need to complete. Add it to your orchestration, add a receive shape, add a delay shape with a terminate on the other branch. If the orchestration does not receive a message in one day or whatever your delay is configured for, it will terminate. However, if it receives a message, the orchestration will continue as normal and the termination won&amp;rsquo;t occur.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/IJ9EYLIJDLA?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;rawpixel.com&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/listen?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>Now this is jewel in my Biztalk Toolbox</title><link>https://riaan.hanekom.io/2006/05/19/now-this-is-jewel-in-my-biztalk-toolbox/</link><pubDate>Fri, 19 May 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/05/19/now-this-is-jewel-in-my-biztalk-toolbox/</guid><description>&lt;p&gt;If your BizTalk orchestration is published as a web service and something goes awry in your orchestration a specific exception might not be thrown to your web service, but rather it will throw ApplicationTimeOutException.&lt;/p&gt;
&lt;p&gt;I was prepared to live with it, until I found the following jewel &lt;a href="http://thearchhacker.blogspot.com/2004_08_01_thearchhacker_archive.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here.&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;If your BizTalk orchestration is published as a web service and something goes awry in your orchestration a specific exception might not be thrown to your web service, but rather it will throw ApplicationTimeOutException.&lt;/p&gt;
&lt;p&gt;I was prepared to live with it, until I found the following jewel &lt;a href="http://thearchhacker.blogspot.com/2004_08_01_thearchhacker_archive.html" target="_blank" rel="noopener noreferrer" class="external-link"&gt;here.&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Turns out you can have custom SOAP faults returned in your orchestration. Who would&amp;rsquo;ve known?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/IdjxBF_StBk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;jesse orrico&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/soap?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>The question about life, the universe, and everything.</title><link>https://riaan.hanekom.io/2006/05/19/the-question-about-life-the-universe-and-everything./</link><pubDate>Fri, 19 May 2006 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2006/05/19/the-question-about-life-the-universe-and-everything./</guid><description>&lt;p&gt;Amazing how little time you get as a developer for doing the things you really want to do (and here I am sitting in front of a computer again ;)). This blog has been a bit stale, and I&amp;rsquo;ve made a quarter-year resolution to put new energy into it.&lt;/p&gt;
&lt;p&gt;Projects have been keeping me extremely busy these last couple of weeks - specifically an integration project (using BizTalk of course). That&amp;rsquo;s one of those projects where everything goes wrong and all unforeseen circumstances come to the party. Hell, by this time I&amp;rsquo;m an expert at crisis management. Luckily, none of these problems are unsolvable (but that&amp;rsquo;s where the time issue come in).&lt;/p&gt;</description><content:encoded>&lt;p&gt;Amazing how little time you get as a developer for doing the things you really want to do (and here I am sitting in front of a computer again ;)). This blog has been a bit stale, and I&amp;rsquo;ve made a quarter-year resolution to put new energy into it.&lt;/p&gt;
&lt;p&gt;Projects have been keeping me extremely busy these last couple of weeks - specifically an integration project (using BizTalk of course). That&amp;rsquo;s one of those projects where everything goes wrong and all unforeseen circumstances come to the party. Hell, by this time I&amp;rsquo;m an expert at crisis management. Luckily, none of these problems are unsolvable (but that&amp;rsquo;s where the time issue come in).&lt;/p&gt;
&lt;p&gt;How does a systems developer end up making money, moving forward in life? Not that money is my main goal in life, but hey, it would be nice to retire at 35 wouldn&amp;rsquo;t it? Probably wouldn&amp;rsquo;t stop doing what I do though&amp;hellip;&lt;/p&gt;
&lt;p&gt;Anyway, enough with the ramblings, let&amp;rsquo;s get some real content on this blog!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/f2tUvySJYr4?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Yong Chuan&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/universe?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>First Post</title><link>https://riaan.hanekom.io/2005/08/11/first-post/</link><pubDate>Thu, 11 Aug 2005 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/2005/08/11/first-post/</guid><description>&lt;p&gt;Here we go - my first post&amp;hellip;&lt;/p&gt;
&lt;p&gt;I am working as a Systems Developer for a company in Johannesburg, specializing in Microsoft technologies (C#, SharePoint, BizTalk, SQL, the whole stack).&lt;/p&gt;
&lt;p&gt;This blog is a place where I can get my thoughts into the open and get opinions from the whole wide world (www). My intention is for this to be a learning experience for both the reader and myself.&lt;/p&gt;
&lt;p&gt;This blog will cover BizTalk, Mobile development, SharePoint, SQL and general C# .NET topics with a little C++, AI and theoretical computing sprinkled on top.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Here we go - my first post&amp;hellip;&lt;/p&gt;
&lt;p&gt;I am working as a Systems Developer for a company in Johannesburg, specializing in Microsoft technologies (C#, SharePoint, BizTalk, SQL, the whole stack).&lt;/p&gt;
&lt;p&gt;This blog is a place where I can get my thoughts into the open and get opinions from the whole wide world (www). My intention is for this to be a learning experience for both the reader and myself.&lt;/p&gt;
&lt;p&gt;This blog will cover BizTalk, Mobile development, SharePoint, SQL and general C# .NET topics with a little C++, AI and theoretical computing sprinkled on top.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m breaking a bottle of champagne against this blog and naming it &amp;ldquo;Binary Thoughts&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Photo by &lt;a href="https://unsplash.com/photos/4JxV3Gs42Ks?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Kelly Sikkema&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/write?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Unsplash&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</content:encoded></item><item><title>About</title><link>https://riaan.hanekom.io/page/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/page/about/</guid><description>&lt;p&gt;Riaan is a Chief Technology Officer at &lt;a href="https://ozow.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ozow&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, a leading fintech company in South Africa. He is a solution-focused technology leader with deep expertise spanning executive-level strategy and hands-on technical depth.&lt;/p&gt;
&lt;p&gt;With a wide range of experience in software development, project delivery, and technology strategy, Riaan has led teams building some of the most prominent internet applications in Africa. He is a polyglot technologist who prides himself on his ability to learn and adapt to new challenges.&lt;/p&gt;</description><content:encoded>&lt;p&gt;Riaan is a Chief Technology Officer at &lt;a href="https://ozow.com" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Ozow&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, a leading fintech company in South Africa. He is a solution-focused technology leader with deep expertise spanning executive-level strategy and hands-on technical depth.&lt;/p&gt;
&lt;p&gt;With a wide range of experience in software development, project delivery, and technology strategy, Riaan has led teams building some of the most prominent internet applications in Africa. He is a polyglot technologist who prides himself on his ability to learn and adapt to new challenges.&lt;/p&gt;
&lt;p&gt;Beyond technology, Riaan has a keen interest in people, organisational dynamics, and what drives individuals and teams to succeed.&lt;/p&gt;
&lt;p&gt;Riaan also consults through &lt;a href="https://www.pragcraft.com/" target="_blank" rel="noopener noreferrer" class="external-link"&gt;Pragcraft&lt;svg class="external-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"&gt;&lt;path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"&gt;&lt;/path&gt;&lt;polyline points="15 3 21 3 21 9"&gt;&lt;/polyline&gt;&lt;line x1="10" y1="14" x2="21" y2="3"&gt;&lt;/line&gt;&lt;/svg&gt;
&lt;/a&gt;, providing consulting services for software engineering, architecture, and fractional CTO engagements.&lt;/p&gt;
&lt;div class="social-links large"&gt;
&lt;a href="#ZgotmplZ" title="Twitter/X" rel="noopener" target="_blank"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;a href="#ZgotmplZ" title="LinkedIn" rel="noopener" target="_blank"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"&gt;&lt;/path&gt;&lt;rect x="2" y="9" width="4" height="12"&gt;&lt;/rect&gt;&lt;circle cx="4" cy="4" r="2"&gt;&lt;/circle&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;a href="#ZgotmplZ" title="GitHub" rel="noopener" target="_blank"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"&gt;&lt;/path&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;</content:encoded></item><item><title>Archive</title><link>https://riaan.hanekom.io/archive/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/archive/</guid><description/><content:encoded/></item><item><title>Search</title><link>https://riaan.hanekom.io/search/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://riaan.hanekom.io/search/</guid><description/><content:encoded/></item></channel></rss>