<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[keeoon]]></title><description><![CDATA[We write about software development and building teams that perform.]]></description><link>https://keeoon.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!y6IF!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f3f81b8-d509-4f5c-b56b-755c2fd58fef_270x270.png</url><title>keeoon</title><link>https://keeoon.substack.com</link></image><generator>Substack</generator><lastBuildDate>Sun, 23 Aug 2026 07:53:53 GMT</lastBuildDate><atom:link href="https://keeoon.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[keeoon]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[keeoon@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[keeoon@substack.com]]></itunes:email><itunes:name><![CDATA[keeoon]]></itunes:name></itunes:owner><itunes:author><![CDATA[keeoon]]></itunes:author><googleplay:owner><![CDATA[keeoon@substack.com]]></googleplay:owner><googleplay:email><![CDATA[keeoon@substack.com]]></googleplay:email><googleplay:author><![CDATA[keeoon]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Understanding the Economics of Software Delivery]]></title><description><![CDATA[Deployment Overhead]]></description><link>https://keeoon.substack.com/p/understanding-the-economics-of-software</link><guid isPermaLink="false">https://keeoon.substack.com/p/understanding-the-economics-of-software</guid><dc:creator><![CDATA[keeoon]]></dc:creator><pubDate>Mon, 17 Jul 2023 06:00:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!3Zha!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The increasing recognition of the importance of these is part of what originated the DevOps movement, which correctly identified the segregation of &#8220;Development&#8221; (writing the application) and &#8220;Operations&#8221; (running the application) as a source of issues.</p><p>One of the most important practices to arise out of this movement is Continuous Delivery, the automation of the software delivery process; by automating, teams improve the reliability and speed of releases and simultaneously, reduce the overhead involved. This, in turn, enables them to deliver more often, which provides more and better feedback.</p><p>Why and how does Continuous Delivery work, though? To understand this, we need to learn about the economics of Software Delivery; in this post, we&#8217;ll write about Deployment Overhead.</p><h1>Deployment Overhead</h1><p>The process of delivering a piece of software from source code to production (whatever that means) involves a number of activities:</p><ul><li><p>Packaging the application</p></li><li><p>Installing the package in the runtime environment</p></li><li><p>Testing</p></li><li><p>Configuring the application</p></li><li><p>Migrating application data</p></li></ul><p>These operations are not, strictly speaking, adding value to the software: you can repeat them as often as you like but you&#8217;re not going to get new features in the software unless you actually change the source code. Moreover, these still take time, which you won&#8217;t be ablo to use for value added development tasks; for this reason, we call these activities <strong>deployment overhead</strong>.</p><p>Now, imagine that it takes you an hour to do all of these<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>: if you want to release every day and you have 8 hours of work in a day, that leaves you with only 7 hours to work on code, i.e., your productivity is</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{7}{8}=0.875=87.5\\%&quot;,&quot;id&quot;:&quot;KDQZSATNBZ&quot;}" data-component-name="LatexBlockToDOM"></div><p>In other words, only 87.5% of your time was spent adding value to your product. </p><p>However, what happens if, instead of doing this every day, you do it <strong>every 2 days </strong>(16 work hours)? Your productivity is now:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{15}{16}=0.9375=93.65\\%&quot;,&quot;id&quot;:&quot;RXGAKKTKHU&quot;}" data-component-name="LatexBlockToDOM"></div><p>Wow, you just got a 6% gain in productivity! Maybe we&#8217;re on to something: <strong>by releasing less frequently, we can increase our productivity</strong>&#8230;</p><p>Indeed, this is true; plotting deployment overhead as a function of the release cadence (the inverse of frequency) makes it easy to spot the trend:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3Zha!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3Zha!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 424w, https://substackcdn.com/image/fetch/$s_!3Zha!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 848w, https://substackcdn.com/image/fetch/$s_!3Zha!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 1272w, https://substackcdn.com/image/fetch/$s_!3Zha!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3Zha!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png" width="876" height="618" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:618,&quot;width&quot;:876,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:45549,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3Zha!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 424w, https://substackcdn.com/image/fetch/$s_!3Zha!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 848w, https://substackcdn.com/image/fetch/$s_!3Zha!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 1272w, https://substackcdn.com/image/fetch/$s_!3Zha!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d610aa5-e706-46bb-8a46-13ee88539fee_876x618.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>This seems to suggest that batching up more changes for each deployment is more efficient and thus makes the most economic sense.</p><h1>Summary</h1><p>In this article, we have started to describe the economics of software delivery, starting with Deployment Overhead and how, taken in isolation, it suggests that it&#8217;s best to release infrequently, in order to be more efficient.</p><p>However, deployment overhead is not the only variable that influences the economics of software delivery; as we&#8217;ll see in upcoming articles, other concerns will come into play that will push us into shorter deployment cadences.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>If this seems like a lot to you, congratulations! That means that you&#8217;ve probably worked in places where Continuous Delivery is a valued practice; unfortunately, this was a reality not too long ago, and sadly there will still be places where this is true.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Communicating using asynchronous media]]></title><description><![CDATA[A recurring theme when organizing software development teams is how to build the communication structures in and around the team.]]></description><link>https://keeoon.substack.com/p/communicating-using-asynchronous</link><guid isPermaLink="false">https://keeoon.substack.com/p/communicating-using-asynchronous</guid><dc:creator><![CDATA[keeoon]]></dc:creator><pubDate>Tue, 13 Jun 2023 06:01:06 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A recurring theme when organizing software development teams is how to build the communication structures in and around the team.</p><p>Engineering, being knowledge work, requires large chunks of distraction-free time, in order to tackle complex problems; on the other hand, it&#8217;s also a team sport, and thus requires intense collaboration to build any system of non-trivial scale.</p><p>Balancing both of these needs is hard but, in our experience, can be done effectively by resorting to asynchronous communication media.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="1080" height="1440" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1440,&quot;width&quot;:1080,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;shallow focus photography of gray mailbox&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="shallow focus photography of gray mailbox" title="shallow focus photography of gray mailbox" srcset="https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1528329140527-75853b1e1650?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHw0fHxtYWlsfGVufDB8fHx8MTY4NjU5MzYxNHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@mikaela_wiedenhoff">Mikaela Wiedenhoff</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><h1>What is asynchronous communication?</h1><p>When we say &#8220;communication&#8221;, we usually mean &#8220;conversation&#8221;: two (or more) people speaking in turns, exchanging ideas.</p><p>In this traditional means of communication, all parties are actively involved at the same time (i.e. synchronized), effectively blocked from doing anything else besides speaking or listening<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>. Examples of this are talking (whether in-person or on a phone) and chat systems (e.g. Slack).</p><p>For communication to be &#8220;asynchronous&#8221;, i.e., to work in the absence of significant synchronization, it is optional that everyone is available at the same time and there is an understanding that a reply probably won&#8217;t arrive immediately.</p><p>An example of asynchronous communication media that is easy to understand is conventional mail (you don&#8217;t need to be at home to receive your mail), but plain email is asynchronous as well.</p><p>For software development specifically, the issue tracker (Gitlab, GitHub, JIRA) is also an asynchronous communication media, as are most other tools that support messaging/commenting.</p><h1>Why is asynchronous communication better?</h1><p>The first thing to note here is that asynchronous communication is not better in every context: rather, it is <em>usually</em> better in the specific context of software engineering.</p><h2>It produces less interruptions</h2><p>By its nature, asynchronous media separate the production of the message from its consumption: in other words, even if someone sends you a letter every day, you&#8217;re free to only check your mail once a week.</p><p>Since, as mentioned above, effective engineering work requires focus, this allows engineers to focus on their work without interruptions and only stop every hour or so to check on their messages.</p><h2>It allows for deeper discussions</h2><p>Discussions in engineering often require:</p><ul><li><p>compiling information from various sources</p></li><li><p>testing hypotheses</p></li></ul><p>Both of which are awkward to do synchronously because they take time and, meanwhile, the other person would just be standing there &#8220;doing nothing&#8221;.</p><p>With asynchronous messages, the writer can devote themselves to writing something that is well structured and easy to &#8220;digest&#8221;, while the reader can take their time to make sure they understand the points that were made.</p><h1>How can I use asynchronous messaging better?</h1><p>An interesting observation is that, while most people will have experience with email, their usage is strongly influenced by synchronous communication patterns and, to a certain extent, defeat its whole point.</p><p>Here, we make some recommendations for making better use of asynchronous communication.</p><h2>Set expectations for response times and availability</h2><p>This might be the hardest to pull off: in the end, we all know we have little control over other people&#8217;s feelings, and it&#8217;s easy to imagine &#8220;missing&#8221; a message, with severe consequences.</p><p>In practice, such incidents are very rare and can be handled by providing an emergency contact (e.g. phone call), with the understanding that it&#8217;ll only be used for something that requires immediate action.</p><p>In most cases, as long as you still reply in a reasonable time (e.g. a couple of hours), most people won&#8217;t care too much or notice.</p><h2>Disable notifications</h2><p>Even if you&#8217;re not reading the messages right away, if you don&#8217;t disable notifications, you&#8217;ll be distracted by them.</p><p>A good strategy here is not to disable notifications completely but to keep them only for &#8220;urgent&#8221; messages (e.g. explicit mentions).</p><h2>Pull all messages into a single inbox</h2><p>This makes it easier to go through all the messages than having to hop between different systems; in practice, this &#8220;main&#8221; inbox will almost always be email because it&#8217;s what almost every tool supports.</p><p>This might seem overwhelming at first (especially with the amount of email that certain tools send) but can be made tractable with effective use of filters.</p><p>Something else to keep in mind is that not all messages are created equal: some will require a turn-around of only a few hours (e.g. answering a question), while others may not require one for a few days (e.g. a long discussion on a Request For Comments document), and still others might require no answer (e.g. a notification that someone created a Merge Request).</p><h2>Assign an &#8220;on-call&#8221; engineer</h2><p>An option, within a team, is to assign a single engineer to &#8220;on-call&#8221; duty, meaning that person will field all synchronous requests, in order to shield the team from the distractions.</p><p>This assignment can be rotated on a regular basis, so every engineer has the chance to work distraction-free.</p><h1>Summary</h1><p>In this article, we&#8217;ve described what asynchronous communication is and how it can be beneficial for teams developing software.</p><p>Additionally, we&#8217;ve provided some suggestions on how to make asynchronous communication work better.</p><p>Do you feel that your work environment is too distracting? </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.keeoon.dev/company/&quot;,&quot;text&quot;:&quot;Contact Us!&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.keeoon.dev/company/"><span>Contact Us!</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>There is no such thing as multi-tasking: research has firmly established that, with the exception of basic tasks, multi-tasking produces significantly inferior outcomes and, over time, deteriorates an individual&#8217;s ability to focus effectively, even when working on one task at a time.</p></div></div>]]></content:encoded></item><item><title><![CDATA[The test client pattern]]></title><description><![CDATA[Testing is a central activity in software development: due to its &#8220;softness&#8221;, software changes very frequently and, particularly in large systems, this rate of change can cause previously correct behavior to change; this type of bug is commonly called a regression.]]></description><link>https://keeoon.substack.com/p/the-test-client-pattern</link><guid isPermaLink="false">https://keeoon.substack.com/p/the-test-client-pattern</guid><dc:creator><![CDATA[keeoon]]></dc:creator><pubDate>Tue, 06 Jun 2023 06:01:11 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Testing is a central activity in software development: due to its &#8220;softness&#8221;, software changes very frequently and, particularly in large systems, this rate of change can cause previously correct behavior to change; this type of bug is commonly called a regression.</p><p>As code complexity rises quite quickly with the size of the code base, it becomes impossible to check for regressions using manual testing procedures and, in practice, any professional software development effort will employ automated testing; automating tests is of such importance that, in many projects, the ratio of production to test code is almost 1:1.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://keeoon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading keeoon! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="1080" height="810" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:810,&quot;width&quot;:1080,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;robot playing piano&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="robot playing piano" title="robot playing piano" srcset="https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1516110833967-0b5716ca1387?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwyOXx8cm9ib3QlMjBnbG92ZXxlbnwwfHx8fDE2ODU4ODYyNzJ8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This makes the use of patterns for managing test code important, and one such pattern that we&#8217;ve found useful for testing API (Application Programming Interface) based components is implementing a test client.</p><h1>What is a test client?</h1><p>A test client is an entire client for your API that is written for the purpose of implementing tests.</p><p>In this context, an API is an interface that is accessed over a network (using a protocol such as HTTP); one of the goals of the test client is to abstract that protocol&#8217;s details in the same way they would be if you were writing an entire client application.</p><h2>What are the benefits of writing a test client?</h2><h3>Improved DX (Developer Experience)</h3><p>The most common complaint heard by someone consuming an API is that it is difficult to use.</p><p>This usually happens because:</p><ul><li><p>Operations/resources have a plethora of arguments/options;</p></li><li><p>There are many seemingly identical operations;</p></li><li><p>The sequence of operations to perform a higher level action is complex.</p></li></ul><p>By creating a separate code base, you are, in effect, replicating the DX of whoever needs to integrate with your API; this means that any awkwardness in the API design becomes much more obvious/painful to the team designing and implementing the API.</p><h3>More readable test code</h3><p>Unfortunately, while most engineers are motivated to produce Clean Code (meaning readable, intent-revealing code) for production, test code is often exempted from this attention to detail, often resulting in tangled, brittle tests.</p><p>The following is a too common example of implementing a test:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ipa2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ipa2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 424w, https://substackcdn.com/image/fetch/$s_!Ipa2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 848w, https://substackcdn.com/image/fetch/$s_!Ipa2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 1272w, https://substackcdn.com/image/fetch/$s_!Ipa2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ipa2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png" width="1456" height="832" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:832,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:215498,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ipa2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 424w, https://substackcdn.com/image/fetch/$s_!Ipa2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 848w, https://substackcdn.com/image/fetch/$s_!Ipa2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 1272w, https://substackcdn.com/image/fetch/$s_!Ipa2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa3b11474-cbeb-4f07-9386-a47f79560cb2_1460x834.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By implementing a test client, you would instead write something like: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iHdW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iHdW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 424w, https://substackcdn.com/image/fetch/$s_!iHdW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 848w, https://substackcdn.com/image/fetch/$s_!iHdW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 1272w, https://substackcdn.com/image/fetch/$s_!iHdW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iHdW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png" width="968" height="430" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:430,&quot;width&quot;:968,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:85024,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iHdW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 424w, https://substackcdn.com/image/fetch/$s_!iHdW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 848w, https://substackcdn.com/image/fetch/$s_!iHdW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 1272w, https://substackcdn.com/image/fetch/$s_!iHdW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8241dcc6-5f4e-419e-8f59-fdeb251f7cbf_968x430.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This makes the code much easier to understand and maintain.</p><h2>What are the disadvantages of implementing a test client?</h2><h3>Duplicated effort</h3><p>By design, the test client is an abstraction which requires effort to build and maintain; while this effort will usually be small, it needs to be taken into account when planning.</p><p>On the other hand, if the effort required to build the test client is significant, this could indicate a complex API design that should be given more attention.</p><h1>How should I implement my test client?</h1><h3>Avoid code sharing</h3><p>Ideally, a test client implementation will use a different programming language than the one used to implement the API; for example, if the API is implemented using Java, the client could be implemented in JavaScript or Python.</p><p>The benefit of this is that it avoids too much coupling of the API design to the affordances of a particular programming language or stack.</p><p>In particular, it makes it almost impossible to share production code with the test client, forcing API designers to face their design decisions; we&#8217;ve seen extreme cases in which, by sharing <a href="https://en.wikipedia.org/wiki/Data_transfer_object">Data Transfer Objects</a> between the application and test code, developers were oblivious to what the JSON payload really looked at the wire level (and yes, it looked nasty).</p><h3>Use a code generator, if possible</h3><p>While we find the usefulness of tools like OpenAPI debatable when used strictly for specification or documentation purposes, their ability to generate client stubs from the spec can yield significant productivity gains.</p><p>Since the biggest con of implementing a test client is increased development effort, using a code generator greatly alleviates this and makes the pattern much more worthwhile.</p><h3>Publish the client</h3><p>If the API is public (i.e. meant to be consumed by external parties), you can publish the test client as an artifact, to make it easier for others to integrate with your API; some examples of this are the API clients for cloud services like <a href="https://cloud.google.com/apis/docs/cloud-client-libraries">Google Cloud Platform</a> or <a href="https://aws.amazon.com/developer/tools/">Amazon Web Services</a>.</p><p>Even if the API isn&#8217;t public and is only consumed by a single application (usually a Web Frontend), it&#8217;s still possible (and beneficial) to publish the client, so it can be used not only by the tests but also the actual client.</p><h1>Summary</h1><p>In this article, we&#8217;ve described the test client pattern; this pattern makes the friction in DX more evident to API designers, thus incentivizing them to improve the design.</p><p>Is this pattern one that would make sense for you? Let us know in the comments!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://keeoon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading keeoon! Subscribe for free to receive new posts and support our work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Using estimates for planning]]></title><description><![CDATA[Developing software is a marathon, not a sprint, which makes planning a key part of the process; without a plan, you&#8217;ll get dragged away by the events of the day and, eventually, find that you didn&#8217;t quite end up where you wanted to.]]></description><link>https://keeoon.substack.com/p/using-estimates-for-planning</link><guid isPermaLink="false">https://keeoon.substack.com/p/using-estimates-for-planning</guid><dc:creator><![CDATA[keeoon]]></dc:creator><pubDate>Mon, 29 May 2023 23:00:11 GMT</pubDate><enclosure url="https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Developing software is a marathon, not a sprint, which makes planning a key part of the process; without a plan, you&#8217;ll get dragged away by the events of the day and, eventually, find that you didn&#8217;t quite end up where you wanted to.</p><p>One of the crucial activities that support planning is that of estimation; while this is a contentious view, in this article, we explain how estimation, when done <em>well enough</em>, can make the difference in the planning of software development.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://keeoon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading keeoon! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw"><img src="https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080" width="1080" height="720" data-attrs="{&quot;src&quot;:&quot;https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1080,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;five person by table watching turned on white iMac&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="five person by table watching turned on white iMac" title="five person by table watching turned on white iMac" srcset="https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 424w, https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 848w, https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1272w, https://images.unsplash.com/photo-1552581234-26160f608093?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMDAzMzh8MHwxfHNlYXJjaHwxOHx8cGxhbm5pbmd8ZW58MHx8fHwxNjg1MDQ4ODUxfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo by <a href="https://unsplash.com/@jasongoodman_youxventures">Jason Goodman</a> on <a href="https://unsplash.com">Unsplash</a></figcaption></figure></div><h1>What is estimation?</h1><p>In software development, the term &#8220;estimation&#8221; is commonly used to describe the activity of predicting how long a given task, feature or even entire project will take to complete.</p><p>Estimating is then, at its heart, assigning a cost to some action which, in the context of planning, allows that action to be compared with the alternatives<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>.</p><h1>Why are estimates useful?</h1><p>In our experience, estimates are most helpful <strong>when combined with the benefit</strong> the team <strong>expects</strong> to derive from completing a particular piece of work. </p><p>By plotting a unit of work&#8217;s estimated cost against its estimated benefit, we can place it in an Action Priority Matrix<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>:</p><ol><li><p><em>Fill Ins</em>, which can be completed quickly but don&#8217;t add a lot of value;</p></li><li><p><em>Quick Wins</em>, work that has low-cost but high benefit;</p></li><li><p><em>Thankless Tasks</em> that, despite their high cost to complete, don&#8217;t actually achieve much;</p></li><li><p><em>Big Bets</em> involving a lot of effort but also with a large payoff.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-0_T!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-0_T!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 424w, https://substackcdn.com/image/fetch/$s_!-0_T!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 848w, https://substackcdn.com/image/fetch/$s_!-0_T!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 1272w, https://substackcdn.com/image/fetch/$s_!-0_T!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-0_T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png" width="1456" height="1420" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1420,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:106341,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-0_T!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 424w, https://substackcdn.com/image/fetch/$s_!-0_T!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 848w, https://substackcdn.com/image/fetch/$s_!-0_T!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 1272w, https://substackcdn.com/image/fetch/$s_!-0_T!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e25cd97-1f5f-4d5b-8aff-6c9466e35702_1784x1740.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By classifying tasks into these four categories, it becomes evident that a team will want to spend most of its time working on <em>Quick Wins</em> and avoiding <em>Thankless Tasks</em><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>, since these will generate (in theory) the most value in the least amount of time; thus, the use of estimates provides <strong>a basis for prioritizing work</strong>.</p><h1>Summary</h1><p>While the topic of estimation in software development can be a contentious one, we&#8217;ve described one way in which it can be used to support planning activities; by analyzing a task&#8217;s benefit and cost, it becomes easier to recognize in which category of the Action Priority Matrix it belongs and thus prioritize quickly, even with large backlogs. </p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>The benefit or value that would be derived from a given work unit is usually an estimate itself; the reason we haven&#8217;t included in this definition of estimation is that benefits are often tied to business outcomes and thus not generally estimated by engineering.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>We haven&#8217;t been able to find an origin for this, although it seems to often be associated with Eisenhower&#8217;s Matrix, as popularized by Stephen R. Covey, the author of &#8220;The 7 Habits of Highly Effective People&#8221;.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>While <em>Fill Ins</em> and <em>Big Bets</em> have similar cost/benefit ratios, in practice, <em>Fill Ins</em> should be favored because they&#8217;re associated with smaller batches and thus smaller risk.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Building for production]]></title><description><![CDATA[Growing adoption of DevOps has been one of the trends of the last 15 years or so in software engineering; in short, DevOps stresses the collaboration between Development (writing the software) and Operations (running the software).]]></description><link>https://keeoon.substack.com/p/building-for-production</link><guid isPermaLink="false">https://keeoon.substack.com/p/building-for-production</guid><dc:creator><![CDATA[keeoon]]></dc:creator><pubDate>Sat, 06 May 2023 11:38:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!y6IF!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f3f81b8-d509-4f5c-b56b-755c2fd58fef_270x270.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Growing adoption of <a href="https://en.wikipedia.org/wiki/DevOps">DevOps</a> has been one of the trends of the last 15 years or so in software engineering; in short, DevOps stresses the collaboration between Development (writing the software) and Operations (running the software).</p><p>This arose because, historically, these were segregated roles, with those in Development handing over their work to Operations; however, this segregation lead to applications that were built without taking into consideration how they would actually be run in production, leading to all sorts of problems:</p><ul><li><p>applications that needed thousands of configuration settings to run;</p></li><li><p>applications that did not scale, i.e., could not handle increases in volume;</p></li><li><p>applications that fail in mysterious ways.</p></li></ul><h1>Silent machines</h1><p>A recurring theme that we see with teams that deploy software is <strong>how silent it is, in a bad way</strong>: the application could be running for weeks until someone (often a user) reports that something isn&#8217;t quite right.</p><p>Why does this happen?</p><p>The simple reason is these applications don&#8217;t provide operators with even simple things like:</p><ul><li><p>logs, textual output describing what the application is doing;</p></li><li><p>metrics, usually numeric data that measure different aspects of the application&#8217;s operation.</p></li></ul><p>In other cases, this information does exist, but <strong>needs to be proactively looked at</strong>&#8230; which means that:</p><ol><li><p>it usually isn&#8217;t;</p></li><li><p>if the app is expected to run 24/7, you need someone to check in around the clock (this is a good way to burn out your engineers).</p></li></ol><h1>Don&#8217;t call us: we&#8217;ll call you</h1><p>What you want is to have your software make some noise when it&#8217;s sick, so you can heal it. While conceptually simple, this can (and often does) require a lot of effort to build in and coordinate between several pieces.</p><h2>Software architecture</h2><p>At a minimum, any modern toolchain that you build software on needs to perform logging. This is so errors can be identified and operators notified; if this doesn&#8217;t exist, you should look into a different toolchain.</p><p>Then, your application needs to be architected in a way that ensures that, <strong>by default, all errors are handled centrally</strong>; what this means is that, if an error occurs, you guarantee that <em>something specific</em> (usually logging or reporting to an external service like <a href="https://sentry.io/">Sentry</a>) happens. If it becomes possible for an error to be silently ignored, you&#8217;re relying on your customers to (angrily) report them to you.</p><h2>Your platform</h2><p>Even if you&#8217;ve carefully built logging into your application and instrumented it to collect metrics, you need to push this data into a place where you can look at it and setup some rules that&#8217;ll notify you when something seems suspicious. This is where your choice of platform (the place where your software runs) can make things easier or harder:</p><ul><li><p>a good platform can do most of the work for you; all you have to do is deploy your app and everything will appear in its place, as if by magic;</p></li><li><p>a bad platform won&#8217;t give you this (or it might charge you obscenely for it), leaving you with no option but to <strong>run more software</strong> in order to make up for it.</p></li></ul><h1>Conclusion</h1><p>While application development tools have come a long way, they cannot, by themselves, replace proper design and implementation: even when the best tools are available, software requires the employment of certain architectural patterns to ensure that it performs its intended business duties and, most importantly, that we know <em>when</em> it&#8217;s failing and have the data to learn <em>why</em>.</p><p>In this article, we&#8217;ve outlined a few of these techniques, which are part of our assessment of client maturity. Do you feel that this is an area that might need improvement? If so, <a href="https://www.keeoon.dev/company">get in touch</a>.</p>]]></content:encoded></item><item><title><![CDATA[How we want to make a difference]]></title><description><![CDATA[In the last blog post, we explained the reasons for founding keeoon through a couple of scenarios found in the software development world of today.]]></description><link>https://keeoon.substack.com/p/how-we-want-to-make-a-difference</link><guid isPermaLink="false">https://keeoon.substack.com/p/how-we-want-to-make-a-difference</guid><dc:creator><![CDATA[keeoon]]></dc:creator><pubDate>Sat, 15 Apr 2023 11:36:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!y6IF!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f3f81b8-d509-4f5c-b56b-755c2fd58fef_270x270.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In <a href="https://open.substack.com/pub/keeoon/p/hello-world?r=2g1uew&amp;utm_campaign=post&amp;utm_medium=web">the last blog post</a>, we explained the reasons for founding keeoon through a couple of scenarios found in the software development world of today. In this post, we want to describe our approach to solving this problem.</p><h1>The OODA loop</h1><p>Many in business will be familiar with <a href="https://en.wikipedia.org/wiki/OODA_loop">the OODA loop</a>; in summary, it is a model of decision making with 4 steps:</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://keeoon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading keeoon! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><ol><li><p><em>Observe</em>, where one gathers information on their environment;</p></li><li><p><em>Orient</em>, where one uses the information to understand their position in the environment;</p></li><li><p><em>Decide</em>, where one formulates a hypothesis of what action will lead to a favorable outcome;</p></li><li><p><em>Act</em>, where one performs the actions planned in the previous step.</p></li></ol><p>A central idea is that, in any enterprise, decision makers go through the loop multiple times and, with each round, learn something about the environment that informs later hypotheses and actions. Therefore, there is a competitive advantage to gain by looping faster because, on the one hand, one gathers more information faster while, on the other hand, one&#8217;s actions can disrupt a competitor by changing the landscape on which they based their decisions.</p><h1>Orient</h1><p>The work that we do focuses on the <em>Orient</em> stage; the reason is that, in our experience, while many engineering companies are <em>observing</em> the environment, they often fail to take into account their position within it, which leads to plans that ultimately fail to produce their expected outcome.</p><p>As an example, it&#8217;s very common to see small or midsized companies adopting practices from much larger (and publicly visible) companies without understanding that those practices are only needed or worthwhile beyond a certain scale.</p><p>We believe we can change this by providing insight into <strong>where your company is right now</strong>: after all, you can only get to where you want to be if you know where you&#8217;re starting from. And not only do we want to tell you what your strengths and weaknesses are, we also want to give you a boost on your path to improvement by <em>suggesting</em> what you could do; ultimately, we want your team to succeed by itself.</p><h1>Summary</h1><p>At keeoon, we want to turn software into something that is, on the one hand, a reliable foundation for many business models and, on the other hand, a safe and satisfying career option for the people that build it.</p><p>While software engineering is a relatively young and fast moving field, there is already a body of knowledge that makes it possible to assess a software development team or company&#8217;s maturity, and point to resources that will help them improve and succeed.</p><p>Do you feel like we could help you? If so, <a href="https://www.keeoon.dev/company">get in touch</a>.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://keeoon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading keeoon! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Hello World]]></title><description><![CDATA[Why keeoon exists]]></description><link>https://keeoon.substack.com/p/hello-world</link><guid isPermaLink="false">https://keeoon.substack.com/p/hello-world</guid><dc:creator><![CDATA[keeoon]]></dc:creator><pubDate>Sat, 25 Mar 2023 12:32:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!y6IF!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f3f81b8-d509-4f5c-b56b-755c2fd58fef_270x270.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>&#8220;Hello World&#8221; is a common expression used in programming, when trying something out for the first time. It seemed appropriate to use it for this first post, since keeoon is also an experiment, an experiment in changing how software is experienced.</p><p>In this post, we aim to describe why the company came into being; we&#8217;ll start with a couple of stories.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://keeoon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading keeoon! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>A startup founder&#8217;s story</h2><p>Imagine you&#8217;re a startup founder: you have a business idea that you&#8217;re trying to validate.</p><p>Your idea needs some software, though, and you don&#8217;t have the expertise to build it, so you hire a team to build it for you.</p><p>You tell them what you want, work with them for a few months&#8230; and you have nothing to show for it; or maybe you have <em>something</em>, but it&#8217;s definitely not what you had in mind: the interface is hideous and clunky, and trying to do anything is an exercise in frustration because it takes so long&#8230; before failing.</p><p>You&#8217;ve spent most of your money away and, at this point, it&#8217;s very likely that your business is going to fail; there are customers interested in your solution but they don&#8217;t want to pay for something that gives them headaches.</p><h2>A struggling company</h2><p>In another company, in business for over a decade, there is a growing sense of unrest: their once well established position in the market is increasingly under attack from new entrants and, so far, they&#8217;ve been unable to innovate quickly enough to fend off the threat.</p><p>The engineering team is hard at work but, for some reason, the results just don&#8217;t seem to show up; in fact, productivity is going down because some of the most senior engineers have left due to being unhappy with the how the company works.</p><h1>A better way?</h1><p>We&#8217;ve seen the scenarios above play out too often and we want to do something about it. We want a world where businesses of all kinds can rely on software development teams to deliver, while promoting the right environment for engineers to be productive.</p><p>Our journey is just getting started though; if you&#8217;re excited by what you&#8217;ve just read, <a href="https://www.keeoon.dev/company">get in touch</a>.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://keeoon.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading keeoon! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>