<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Denis Kranjcec, Author at ShiftMag</title>
	<atom:link href="https://shiftmag.dev/author/deniskranjcec/feed/" rel="self" type="application/rss+xml" />
	<link>https://shiftmag.dev/author/deniskranjcec/</link>
	<description>Insightful engineering content &#38; community</description>
	<lastBuildDate>Wed, 24 Dec 2025 13:36:50 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shiftmag.dev/wp-content/uploads/2024/08/cropped-ShiftMag-favicon-32x32.png</url>
	<title>Denis Kranjcec, Author at ShiftMag</title>
	<link>https://shiftmag.dev/author/deniskranjcec/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>What It Takes to Fully Benefit from a Deployment Pipeline</title>
		<link>https://shiftmag.dev/what-it-takes-to-fully-benefit-from-a-deployment-pipeline-7463/</link>
		
		<dc:creator><![CDATA[Denis Kranjcec]]></dc:creator>
		<pubDate>Wed, 24 Dec 2025 13:34:53 +0000</pubDate>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Continuous Delivery]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Deployment Pipeline]]></category>
		<category><![CDATA[development]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=7463</guid>

					<description><![CDATA[<p>To get the full power of a Deployment Pipeline, you need more than tools - you need practices that let it shine and reveal both your strengths and your weaknesses.</p>
<p>The post <a href="https://shiftmag.dev/what-it-takes-to-fully-benefit-from-a-deployment-pipeline-7463/">What It Takes to Fully Benefit from a Deployment Pipeline</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img fetchpriority="high" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2025/12/development-pipeline-1.png?x91379" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2025/12/development-pipeline-1.png 1200w, https://shiftmag.dev/wp-content/uploads/2025/12/development-pipeline-1-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2025/12/development-pipeline-1-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2025/12/development-pipeline-1-768x403.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></figure>


<p>The Deployment Pipeline is a critical tool for ensuring software quality &#8211; and <a href="https://shiftmag.dev/the-dilemma-of-quality-versus-speed-is-false-3310/" target="_blank" rel="noreferrer noopener">quality is a prerequisite for speed</a>.</p>



<p>So, what is a <strong>Deployment Pipeline</strong>? How has it helped us improve both quality and speed? And what are, in my experience, the common problems in using and implementing deployment pipelines?</p>



<blockquote class="wp-block-quote is-style-plain is-layout-flow wp-block-quote-is-layout-flow">
<p>A Deployment Pipeline is a machine that helps us move from an idea to valuable software in the hands of users by organizing software development work. It enables us to go from commit to releasable outcome as quickly and efficiently as possible, in a repeatable and reliable way.</p>



<p>— Dave Farley, <em><a href="https://leanpub.com/cd-pipelines/" target="_blank" rel="noreferrer noopener">Continuous Delivery Pipelines: How to Build Better Software Faster</a></em></p>
</blockquote>



<p>Before exploring how Deployment Pipelines have helped us, it is helpful to briefly introduce <strong>Continuous Integration</strong> and <strong>Continuous Delivery</strong>.</p>



<h2 class="wp-block-heading"><span id="continuous-integration">Continuous Integration</span></h2>



<p>Continuous Integration is a software development practice that helps us <strong>create and maintain a high-quality codebase</strong> that is easy to change and to implement new features.</p>



<p>As Martin Fowler points out, <a href="https://martinfowler.com/articles/continuousIntegration.html" target="_blank" rel="noreferrer noopener">the practices of Continuous Integration</a> are:</p>



<ul class="wp-block-list">
<li>Put everything in a version controlled mainline​</li>



<li>Automate the Build​</li>



<li>Make the Build Self-Testing​</li>



<li>Everyone Pushes Commits To the Mainline Every Day​</li>



<li>Every Push to Mainline Should Trigger a Build​</li>



<li>Fix Broken Builds Immediately​</li>



<li>Keep the Build Fast​</li>



<li>Hide Work-in-Progress​</li>



<li>Test in a Clone of the Production Environment​</li>



<li>Everyone can see what&#8217;s happening​</li>



<li>Automate Deployment​</li>
</ul>



<ol start="1" class="wp-block-list"></ol>



<p>Kent Beck developed the practice of Continuous Integration as part of Extreme Programming in the 1990s. The book <em><a href="https://www.informit.com/store/continuous-integration-improving-software-quality-and-9780321336385" target="_blank" rel="noreferrer noopener">Continuous Integration</a></em> by Paul M. Duvall, Steve Matyas, and Andrew Glover was published in 2007. While this is nothing new, <strong>many software engineers and teams still do not practice Continuous Integration</strong> and therefore miss out on the benefits it provides.</p>



<h2 class="wp-block-heading"><span id="continuous-delivery">Continuous Delivery</span></h2>



<p>Continuous Delivery can further help create and maintain high-quality software. The excellent book <em><a href="https://www.amazon.com/Continuous-Delivery-Deployment-Automation-Addison-Wesley/dp/0321601912" target="_blank" rel="noreferrer noopener">Continuous Delivery</a> </em>by Jez Humble and David Farley was published in 2010. and it describes the idea behind continuous delivery in detail, and it introduces &#8220;<em>&#8230;the central paradigm of the book &#8211; a pattern we call the <strong>deployment pipeline</strong></em>&#8220;.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Continuous Delivery is the ability to get changes of all types &#8211; including new features, configuration changes, bug fixes and experiments &#8211; into production, or into the hands of users, safely and quickly in a sustainable way.</p>



<p>&#8211; <a href="https://continuousdelivery.com/">https://continuousdelivery.com/</a></p>
</blockquote>



<p><strong>Continuous Integration is a prerequisite for Continuous Delivery</strong>.</p>



<p>The minimum activities required for Continuous Delivery, as defined by <a href="https://minimumcd.org/" target="_blank" rel="noreferrer noopener">minimumcd.org</a>, are:</p>



<ul class="wp-block-list">
<li>Use Continuous Integration<em>​</em></li>



<li>The application pipeline is the only way to deploy to any environment​</li>



<li>The pipeline decides the releasability of changes, its verdict is definitive​</li>



<li>Artifacts created by the pipeline always meet the organization’s definition of deployable​</li>



<li>Immutable artifact (no human changes after commit)​</li>



<li>All feature work stops when the pipeline is red​</li>



<li>Production-like test environment​</li>



<li>Rollback on-demand​</li>



<li>Application configuration deploys with artifact​</li>
</ul>



<h2 class="wp-block-heading"><span id="deployment-pipeline">Deployment Pipeline</span></h2>



<p>The best description of deployment pipelines, and practical advice on how to implement them, I found in another excellent book <a href="https://leanpub.com/cd-pipelines/" target="_blank" rel="noreferrer noopener"><em>Continuous Delivery Pipelines, How to Build Better Software Faster</em> </a>by Dave Farley. According to him, automation is the key… and is the engine that drives an effective Deployment Pipeline:</p>



<ul class="wp-block-list">
<li>Test Automation​​</li>



<li>Build and Deployment Automation​​</li>



<li>Automate Data Migration​​</li>



<li>Automate Monitoring and Reporting​​</li>



<li>Infrastructure Automation​</li>
</ul>



<figure class="wp-block-image size-full"><img decoding="async" width="624" height="412" src="https://shiftmag.dev/wp-content/uploads/2025/12/denis.jpg?x91379" alt="" class="wp-image-7471" srcset="https://shiftmag.dev/wp-content/uploads/2025/12/denis.jpg 624w, https://shiftmag.dev/wp-content/uploads/2025/12/denis-300x198.jpg 300w" sizes="(max-width: 624px) 100vw, 624px" /></figure>



<p>The simplest deployment pipeline should, after each commit, compile the code (if needed), run all unit tests, create a deployable artifact, execute acceptance tests, and enable deployment to production.</p>



<p>However, a <strong>deployment pipeline can do much more</strong>, such as:</p>



<ul class="wp-block-list">
<li>Static code analysis</li>



<li>Enable manual testing</li>



<li>Performance tests (e.g., latency, throughput, load)</li>



<li>Data and data migration tests</li>



<li>Security tests</li>



<li>Reliability tests etc.</li>
</ul>



<h2 class="wp-block-heading"><span id="ci-practices"><strong>CI practices</strong></span></h2>



<p>I see many teams/companies have a Jenkins job that compiles source code, runs (a few) unit tests, creates an artifact &#8211; often a Docker image &#8211; and have a separate deploy job/button to deploy to the dev and production environments. And they will say they are &#8220;using&#8221; CI/CD. But <strong>most of them are skipping some of the CI practices</strong> and don&#8217;t have code in an always-deployable state, even as a goal, yet still think they are &#8220;using&#8221; CI/CD. </p>



<p><strong>CI practices</strong> are not a menu where you can choose what you like and still have all the benefits CI can help you with.</p>



<h2 class="wp-block-heading"><span id="make-the-build-self-testing"><em>Make the build self-testing</em></span></h2>



<p><strong>Test-Driven Development (TDD)</strong>, or test-first development, is still an exception, and developers usually write tests after the code. Those tests are mostly unit tests (developer-oriented) and much fewer acceptance tests (user-oriented) that cover only parts of the functionalities. The test-after approach usually covers less functionality because the code is harder to test, and tests are complex to write and maintain. Such tests don&#8217;t provide fast and good-enough feedback to automate &#8220;releasability of changes&#8221; or &#8220;enable refactoring for sustained productivity.&#8221; Developers don&#8217;t trust such tests, so manual verification and team coordination are needed to decide when code can be deployed, which is never fully reliable, and more bugs reach production.</p>



<h2 class="wp-block-heading"><span id="everyone-pushes-commits-to-the-mainline-every-day"><em>Everyone pushes commits to the mainline every day</em></span></h2>



<p>Same as TDD, <strong>trunk-based development</strong> is still an exception, and almost everyone is using branches and pull requests with many PR reviews at the end of the sprint, so they are not practicing continuous integration by definition. They are missing the benefits CI brings, like &#8220;less time wasted in integration&#8221; and &#8220;enables refactoring for sustained productivity.&#8221;</p>



<h2 class="wp-block-heading"><span id="test-in-a-clone-of-the-production-environment%e2%80%8b"><em>Test in a clone of the production environment​</em></span></h2>



<p>Some companies have a <strong>&#8220;static&#8221; copy of production</strong>, with test data already prepared in a database, where they deploy their applications and run tests. As a result, developers can’t run tests on their laptops, test preparation is complex and slow, and they regularly break other tests. Feature flags can’t be tested, and it takes a long time from commit to getting test feedback. This demotivates developers from writing tests, and over time, this negative spiral creates &#8216;legacy&#8217; code that is hard to change.</p>



<p>Rarely does any company I know create, on demand, a <strong>&#8220;clone of production&#8221;</strong> &#8211; with the configuration needed for a suite of tests set up exactly as in production, where the tested application is deployed the same way as in production and then tested to determine the releasability of changes.</p>



<p>Usually, a Jenkins job starts the needed <strong>testcontainers</strong> during the integration test phase and tests parts of the application &#8211; or a &#8220;test&#8221; version of the application &#8211; that differ from the production application. These tests don’t cover the application artifact that will actually be deployed, nor do they test deployment, configuration, or dependencies (e.g., microservices) that aren’t properly mocked. Instead, some fake repository or adapter implementations are used that don’t exist in production.</p>



<h2 class="wp-block-heading"><span id="the-application-pipeline-is-the-only-way-to-deploy-to-any-environment-and-the-pipeline-decides-the-releasability-of-changes-its-verdict-is-definitive%e2%80%8b"><em>The application pipeline is the only way to deploy to any environment</em> AND <em>The pipeline decides the releasability of changes; its verdict is definitive​</em></span></h2>



<p>From what I’ve seen or heard, everyone has a workaround that allows deployment of artifacts that didn’t pass the Deployment Pipeline. Sometimes they create artifacts on their laptop and push them to the repository so they can be deployed. Other times, the pipeline itself allows deployment of code that hasn’t passed all required verifications. </p>



<p>This can happen when a &#8220;non-important&#8221; or &#8220;flaky&#8221; test fails, or when a dependency has a critical vulnerability, etc. Usually, the team says these problems will be fixed later, when there’s time, but the new feature is considered urgent and must be deployed ASAP. In practice, <strong>the team never has time to fix these issues</strong>, workarounds become the norm, and the deployment pipeline turns into a theater.</p>



<h2 class="wp-block-heading"><span id="keep-the-build-fast"><em>Keep the build fast</em></span></h2>



<p>With microservices being so popular, build time shouldn’t be a major problem. Yet it’s common to see builds lasting half an hour or more. </p>



<p>In my experience (mostly with Java), if you create tests &#8211; unit tests, acceptance tests, etc. &#8211; that can run in parallel, it’s easy to have a deployment pipeline finish in under 5 minutes, excluding deployment. Just <strong>run everything in parallel</strong>: unit tests, acceptance tests, services with different feature flags enabled or disabled, and static code analysis.</p>



<h2 class="wp-block-heading"><span id="a-deployment-pipeline-must-be-built-not-bought">A Deployment Pipeline must be built, not bought</span></h2>



<p>A deployment pipeline automates your software development process and reveals both its strengths and weaknesses. When your practices are strong, the pipeline amplifies them, providing significant benefits. Conversely, if your practices are weak, the pipeline makes this very apparent &#8211; it can be difficult or even impossible to implement effectively. </p>



<p>This is why Continuous Integration and Continuous Delivery are so valuable: they <strong>encourage good practices and make problems visible early</strong>. A Deployment Pipeline is not a product you can buy or outsource; you must build it yourself, leveraging various tools.</p>



<p>In my experience, the best way to achieve both speed and quality in software development is to <strong>combine pair or mob programming with test-driven, trunk-based development</strong>, supported by a deployment pipeline that automates feedback on key aspects of the process. This approach provides rapid feedback, within minutes, on ideas and experiments through frequent commits and accompanying tests. It allows the codebase to evolve continuously through refactoring and enables the frequent, low-risk release of new features with minimal stress.</p>
<p>The post <a href="https://shiftmag.dev/what-it-takes-to-fully-benefit-from-a-deployment-pipeline-7463/">What It Takes to Fully Benefit from a Deployment Pipeline</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>This is how two simple changes can improve your code’s maintainability</title>
		<link>https://shiftmag.dev/wfa-this-is-how-two-simple-changes-can-improve-your-codes-maintainability-5352/</link>
		
		<dc:creator><![CDATA[Denis Kranjcec]]></dc:creator>
		<pubDate>Tue, 01 Jul 2025 10:02:08 +0000</pubDate>
				<category><![CDATA[Developer Experience]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Code Maintainability]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=5352</guid>

					<description><![CDATA[<p>Ever opened code that feels like ancient hieroglyphics? You’ve likely encountered primitive obsession or premature generalization. But don’t worry - there’s a way out!</p>
<p>The post <a href="https://shiftmag.dev/wfa-this-is-how-two-simple-changes-can-improve-your-codes-maintainability-5352/">This is how two simple changes can improve your code’s maintainability</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2025/06/code-maitenance.png?x91379" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2025/06/code-maitenance.png 1200w, https://shiftmag.dev/wp-content/uploads/2025/06/code-maitenance-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2025/06/code-maitenance-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2025/06/code-maitenance-768x403.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></figure>


<p>I often see code with readability and maintainability issues caused by <strong>primitive obsessions and premature generalizations</strong>. Both problems have been well-known for a long time, well-described, easy to understand, and easy to avoid.</p>



<p>The key is to <strong>use domain-specific types and generalizations thoughtfully</strong>, applying them only when they genuinely simplify the current requirements. Doing so makes your code not just cleaner, but also much easier to read and maintain.</p>



<h2 class="wp-block-heading"><span id="how-do-we-avoid-primitive-obsession">How do we avoid primitive obsession?</span></h2>



<p>Primitive obsession occurs when a software engineer <strong>uses</strong> <strong>built-in primitives and classes instead of custom, domain-specific types</strong>.&nbsp;This problem&nbsp;is described in many presentations, blogs,&nbsp;or&nbsp;books, such as in&nbsp;<a href="https://github.com/97-things/97-things-every-programmer-should-know/blob/master/en/thing_65/README.md" target="_blank" rel="noreferrer noopener"><em>Chapter 65, &#8220;Prefer Domain-Specific Types to Primitive Types</em></a>, by Einar&nbsp;Landrein thebook&nbsp;<em><a href="https://github.com/97-things/97-things-every-programmer-should-know" target="_blank" rel="noreferrer noopener">97 Things Every Programmer Should Know</a></em>.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>The most commonly used types in Java applications, from my experience, are <strong>String,&nbsp;int,&nbsp;and&nbsp;List, where String creates the most problems</strong>.&nbsp;These types, along with other primitives and built-in classes, are certainly needed, but they should primarily be used as implementation details, not as domain-specific types.</p>
</blockquote>



<p>For example, when an int&nbsp;is used to represent a package weight, it&#8217;s not clear which unit of measurement is&nbsp;being used &#8211; grams, kilograms, tons, pounds, or what the accepted values are.&nbsp;</p>



<p>Similarly, <strong>when a String&nbsp;is used for a color, it&#8217;s not clear what values are supported</strong>&nbsp;&#8211;&nbsp;an RGB hex value, CMYK, &#8220;red&#8221;, &#8220;yellow&#8221;, &#8220;black&#8221;, some locale-specific values, etc. Joshua Bloch describes the problems with String overuse in&nbsp;<em><a href="https://learning.oreilly.com/library/view/effective-java-3rd/9780134686097/" target="_blank" rel="noreferrer noopener">Item 62: Avoid strings where other types are more appropriate in the Effective Java, Third Edition</a>.</em></p>



<p><strong>Lists&nbsp;are often used as a simple collection of Objects,</strong> and all related business rules&nbsp;are scattered throughout the application. A common problem is that&nbsp;a <strong>List can be updated anywhere without any business rules</strong>.&nbsp;And that&#8217;s just a sample of the readability and maintainability issues when using primitives.</p>



<p>When domain-specific classes&nbsp;are used:</p>



<ul class="wp-block-list">
<li><strong>Semantics become clearer</strong> because we are thinking in domain-related terms, not Strings or ints.</li>



<li>All <strong>business rules</strong> <strong>have&nbsp;an obvious place for implementation</strong> &#8211; the domain-specific classes.&nbsp;Code and idea duplication can be avoided.</li>



<li><strong>Only allowed functionality and methods are exposed to users</strong>, making the API&nbsp;easier to understand and use.</li>



<li><strong>Implementation details can be hidden from users</strong>, making the code less coupled and easier to change.</li>



<li><strong>Methods are easier to understand, and the compiler will help with using correct arguments</strong> &#8211; e.g., there are no more methods with many Strings and ints as arguments where it&#8217;s easy to replace the order &#8211; someMethod(String a, String b, String c, int x, int y, int z)</li>
</ul>



<h2 class="wp-block-heading">Don&#8217;t create a general solution for a specific&nbsp;problem</h2>



<p><strong>Premature generalization</strong> happens when we implement generalizations in a code for possible and unclear features that&nbsp;are not required for current and known tasks. Dan North explained that in an excellent blog, &#8220;<em><a href="https://dannorth.net/best-simple-system-for-now/" target="_blank" rel="noreferrer noopener">Best Simple System for Now</a></em>&#8220;.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Most of us are working on applications that need to solve some specific problem. So, we should implement only those particular features that we understand well enough to implement. Too often, I see <strong>code that has (half-)support for enabling future and unknown features</strong>, which makes implementation much more complex than needed for the initial and specific requirements.&nbsp;Those future features are&nbsp;always&nbsp;different&nbsp;from what is&nbsp;expected or are never required and won&#8217;t&nbsp;be implemented.&nbsp;</p>
</blockquote>



<p>However,&nbsp;<strong>some additional features will be required to implement</strong>, and their implementation will be more complex due to unnecessary generalization. </p>



<p>Therefore, the next step should be <strong>the removal of unnecessary generalization before introducing the new feature</strong>; however, often, a new feature is added to the code with unnecessary generalization. The tech debt is growing, and future development is becoming increasingly complex.</p>



<h2 class="wp-block-heading">I&#8217;ll share my &#8220;secret&#8221; with you</h2>



<p>In my experience, the&nbsp;best&nbsp;way to implement features is to&nbsp;use&nbsp;<a href="https://shiftmag.dev/test-driven-development-fail-and-success-1118/" target="_blank" rel="noreferrer noopener">Test-Driven Development (TDD)</a>&nbsp;and Behavior-Driven Development (BDD) to stay focused on the essential requirements.</p>



<p>When working on applications, if generalization is needed to support new features, we can typically achieve it using the <strong>refactoring tools provided by modern IDEs</strong>. Since we&#8217;re guided by explicit requirements, any generalizations we introduce are purposeful and aligned with actual user needs.</p>



<p>To sum up: <strong>primitive obsession and premature generalization are common pitfalls, but they are easily avoided</strong>. Using clear, domain-specific types and delaying generalization until it’s truly needed keeps your code readable and maintainable. By focusing on actual requirements and leveraging TDD and BDD, you build simpler, cleaner solutions &#8211; no more ancient hieroglyphics, just clear, understandable code.</p>
<p>The post <a href="https://shiftmag.dev/wfa-this-is-how-two-simple-changes-can-improve-your-codes-maintainability-5352/">This is how two simple changes can improve your code’s maintainability</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The dilemma of quality versus speed is false</title>
		<link>https://shiftmag.dev/the-dilemma-of-quality-versus-speed-is-false-3310/</link>
		
		<dc:creator><![CDATA[Denis Kranjcec]]></dc:creator>
		<pubDate>Mon, 13 May 2024 12:11:04 +0000</pubDate>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[code quality]]></category>
		<category><![CDATA[Pair programming]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Test-driven development]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=3310</guid>

					<description><![CDATA[<p>Why do software developers claim there's a speed-quality trade-off? Adding features is faster and easier in good code than bad code. </p>
<p>The post <a href="https://shiftmag.dev/the-dilemma-of-quality-versus-speed-is-false-3310/">The dilemma of quality versus speed is false</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2024/05/quality-versus-speed.png?x91379" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2024/05/quality-versus-speed.png 1200w, https://shiftmag.dev/wp-content/uploads/2024/05/quality-versus-speed-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2024/05/quality-versus-speed-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2024/05/quality-versus-speed-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p>No one says, &#8220;This code is a &#8220;big ball of mud,&#8221; but adding new features is quick and easy.&#8221;</p>



<p>But still, too often, I see <strong>developers attempt to be faster by skipping refactorings, tests, and other practices</strong> that help create good-quality code. They just start adding new lines, but the change soon becomes too complex. Since they are developers, they will make it work in the end.</p>



<p>Sometimes, they may be even faster making that one change. However, the design will be harder to understand, implementation complexity will be higher (high coupling, low cohesion, etc.), and testability will be lower, making every following change harder and slower. </p>



<p>After a few times cutting corners like this, <strong>the code will become too complex to understand</strong>, and every subsequent change, no matter how little, will be risky.</p>



<h2 class="wp-block-heading"><span id="the-snowball-effect-of-losing-quality">The snowball effect of (losing) quality</span></h2>



<p>Even worse, when the next developer needs to work on a new feature in that codebase, <strong>it will be easier to continue working with little attention to quality</strong> because it&#8217;s evident in the codebase that quality is not a priority (I think it would be evident that development speed is also not a priority).</p>



<p>With such a cycle, in a relatively short time, any codebase can become complex, risky, and expensive to change.</p>



<p>There is also a problem with what software quality means and how to measure it. I like the quote from &#8220;<a href="https://services.google.com/fh/files/misc/2022_state_of_devops_report.pdf" target="_blank" rel="noreferrer noopener">2022 Accelerate State of DevOps Report</a>&#8220;:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>The ease with which an organization can safely and confidently change its software is a marker of the software&#8217;s quality.</p>



<p></p>
<cite>David Farley</cite></blockquote>



<p><strong>Creating quality software takes time,</strong> usually more than taking shortcuts during development, <strong>but it will enable future changes and speed</strong>. And it&#8217;s not always easy, as <a href="https://twitter.com/KentBeck/status/250733358307500032?lang=en" target="_blank" rel="noreferrer noopener">Kent Beck warns us</a>: &#8220;For each desired change, make the change easy (warning: this may be hard), then make the easy change&#8221;</p>



<p>Might be interesting to note that Beck gives a lot of practical advice and guides on when and how to improve your code in his excellent book: &#8220;<a href="https://learning.oreilly.com/library/view/tidy-first/9781098151232/" target="_blank" rel="noreferrer noopener">Tidy First</a>?&#8221; – and there are many other books on creating quality code and software.</p>



<h2 class="wp-block-heading"><span id="quality-is-the-prerequisite-for-speed">Quality is the prerequisite for speed</span></h2>



<p>There is no lack of people building on the myth that there is a trade-off between quality and speed. It’s just the opposite: <strong>quality leads to speed</strong>.</p>



<p>In his video &#8220;<a href="https://www.youtube.com/watch?v=NgFVrvwth-Q" target="_blank" rel="noreferrer noopener">How To Build Quality Software Fast</a>&#8220;, Dave Farley explains why there is &#8220;No Trade-Off Between Speed &amp; Quality”, noting that cutting corners leads to slower, not faster, development.</p>



<p>Adam Tornhill shows data that confirm how a good-quality codebase improves development speed in his presentation &#8220;<a href="https://youtu.be/ty9d7wEVTwc" target="_blank" rel="noreferrer noopener">The Code Quality Advantage: How Empirical Data Shatters the Speed vs. Quality Myth</a>&#8220;. He also shows <strong>when to invest in better quality and when it may not be needed</strong> (for example, in codebases that are rarely changed).</p>



<p>Even the State of DevOps reports that &#8220;teams who score well on speed consistently score well on quality&#8221; – and they report that every year.</p>



<h2 class="wp-block-heading"><span id="hurry%e2%80%a6-in-small-steps">Hurry… in small steps</span></h2>



<p>In my experience, the best way to achieve both speed and quality in software development is to do <a href="https://shiftmag.dev/pair-programming-benefits-challenges-563/" target="_blank" rel="noreferrer noopener">pair programming</a> using <a href="https://shiftmag.dev/test-driven-development-fail-and-success-1118/" target="_blank" rel="noreferrer noopener">test-driven</a> and <a href="https://www.infobip.com/developers/blog/trunk-based-development-vs-feature-branching" target="_blank" rel="noreferrer noopener">trunk-based development</a> with a great deployment pipeline. </p>



<p><strong>That combination makes you work in small (tiny) steps </strong>and ensures fast feedback from your programming partner, tests, and deployment pipeline &#8211; meaning you&#8217;ll quickly correct and adapt to any design and coding error.  By breaking up complex problems into smaller and simpler ones, we can implement them faster because we are working in small steps that are easy to understand, implement, and verify.</p>



<p>What is your experience with speed and software quality? Is there a trade-off? Please share your experience with me on <a href="https://twitter.com/kranjcec" target="_blank" rel="noreferrer noopener">Twitter</a> or <a href="https://www.linkedin.com/in/kranjcec/" target="_blank" rel="noreferrer noopener">LinkedIn</a>! <br><strong><br>MORE READING:</strong></p>



<figure class="wp-block-embed is-type-wp-embed is-provider-shiftmag wp-block-embed-shiftmag"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="VbWjapUUI2"><a href="https://shiftmag.dev/good-enough-code-is-just-not-good-enough-2844/">&#8220;Good enough&#8221; code is just not good enough</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;&#8220;Good enough&#8221; code is just not good enough&#8221; &#8212; ShiftMag" src="https://shiftmag.dev/good-enough-code-is-just-not-good-enough-2844/embed/#?secret=UcYn74S8zB#?secret=VbWjapUUI2" data-secret="VbWjapUUI2" width="500" height="282" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>
<p>The post <a href="https://shiftmag.dev/the-dilemma-of-quality-versus-speed-is-false-3310/">The dilemma of quality versus speed is false</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I failed at Test-Driven Development and what it took to get it right</title>
		<link>https://shiftmag.dev/test-driven-development-fail-and-success-1118/</link>
		
		<dc:creator><![CDATA[Denis Kranjcec]]></dc:creator>
		<pubDate>Tue, 12 Sep 2023 07:30:00 +0000</pubDate>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Dave Farley]]></category>
		<category><![CDATA[Domain driven development]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=1118</guid>

					<description><![CDATA[<p>It took some time before I could say that TDD really works (for me). I don't think the problem was TDD, but my design and coding skills.</p>
<p>The post <a href="https://shiftmag.dev/test-driven-development-fail-and-success-1118/">How I failed at Test-Driven Development and what it took to get it right</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2023/08/TDD.png?x91379" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/08/TDD.png 1200w, https://shiftmag.dev/wp-content/uploads/2023/08/TDD-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/08/TDD-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/08/TDD-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p>I&#8217;ve always liked the idea of test-driven development, and it&#8217;s three simple steps &#8211; write a test, make it pass, and refactor &#8211; but it took some time before I could say that TDD really works (for me). </p>



<p>I first heard about it over 20 years ago, probably when somebody talked about Kent Beck&#8217;s Extreme Programming:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>In XP, when possible, tests are written in advance of implementation.</p>



<p>If I am programming test-first, I write one failing test, make it work, and then write the next failing test.</p>
</blockquote>



<p>In <em>Growing Object-Oriented Software, Guided by Tests</em>,&nbsp;Steve Freeman and Nat Pryce further define it as follows:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>The cycle at the heart of TDD is: write a test; write some code to get it working; refactor the code to be as simple an implementation of the tested features as possible. Repeat.</p>
</blockquote>



<p><a href="https://www.youtube.com/watch?v=llaUBH5oayw&amp;list=PLwLLcwQlnXByqD3a13UPeT4SMhc3rdZ8q" target="_blank" rel="noreferrer noopener">Using TDD</a> should result in <strong>significantly fewer production bugs</strong> by having code that works as expected (in tests) and with <strong>better design and higher quality of the code</strong> (&#8220;easier to change&#8221;). The code should be <strong>modular, loosely coupled, cohesive, separate concerns well</strong>, and provide <strong>good encapsulation</strong>.</p>



<p>Dave Farley made it almost a haiku:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>The goal of TDD is:</p>



<p>Well Designed Code,</p>



<p>That We Know Works!</p>
</blockquote>



<h2 class="wp-block-heading"><span id="a-luke-warm-introduction-to-tdd">A luke-warm introduction to TDD</span></h2>



<p>Initially, I listened to and learned about TDD through conference sessions, online tutorials, and books, as well as trying it out in my (test) projects. I always got the &#8220;green bar,&#8221; but<strong> I didn&#8217;t think my code was significantly better than before</strong>, with tests written after the code.</p>



<p>One notable difference was that the code was testable (or at least more testable than before). But I didn&#8217;t see all the benefits I&#8217;ve read about.</p>



<p>Nevertheless, many authors, presenters, and software engineers I liked and learned other things from, and whose frameworks and libraries I used, kept talking about TDD and the many benefits they reaped from it.</p>



<p>So I kept at it, but every time, it didn&#8217;t feel like I was doing it correctly, and I definitely didn&#8217;t think I got the &#8220;advertised&#8221; results.</p>



<h2 class="wp-block-heading"><span id="my-mistake-taking-too-big-of-a-bite">My mistake: Taking too big of a bite</span></h2>



<p>Later, I started working on complex information systems, implementing complex business rules with a relatively small and stable team, where the developers were domain experts.</p>



<p>The ever-growing and ever-changing business rules made me more appreciative of a <strong>codebase that was easy to change</strong>, but that too often wasn&#8217;t the case with (my) code. At the time, we were writing some unit tests, more functional tests (actual use-case tests), and doing a decent continuous integration on most applications.</p>



<p>I refactored code daily to make it more readable and understandable. I mostly used rename/extract variable/method/class, and the code was better each time, but again, it wasn&#8217;t as easy to change as I would have liked it. The problem was that my <strong>object design wasn&#8217;t the best</strong>, and I tried to find a way to improve it. I also often tested implementation instead of functionality.</p>



<p>What helped bring me closer to TDD and up my object design <a href="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?crid=3S0U1NQ94BFFN" target="_blank" rel="noreferrer noopener">Domain-Driven Design (DDD).</a> For me, the largest breakthrough came from internalizing the concepts of <a href="https://martinfowler.com/bliki/BoundedContext.html" target="_blank" rel="noreferrer noopener">bounded contexts</a> and <a href="https://martinfowler.com/bliki/UbiquitousLanguage.html" target="_blank" rel="noreferrer noopener">ubiquitous language</a>, but Entities, Value Objects, and Service Objects, including Aggregates, helped me with object design.&nbsp;</p>



<p>When I was writing code (in Java), influenced by DDD,<strong> the code was usually easier to understand</strong>, but the<strong> tests I wrote after the code were too hard to write and maintain.</strong> So, again, I tried TDD. Once again, my code was better, not to the full extent TDD enthusiasts raved about.</p>



<p>I later understood that my biggest mistake was that I wasn&#8217;t working in small steps, starting with the simplest (&#8220;boring&#8221;) use cases and building up to the more complex ones. The other mistake was that I didn&#8217;t refactor the code to &#8220;Well Designed Code,&#8221; so the <strong>methods and classes were too complex</strong> and coupled. The tests were simply too complex to set up and maintain.</p>



<p>And I&#8217;m not the only one who made that mistake, according to <a href="https://www.davefarley.net/?p=260" target="_blank" rel="noreferrer noopener">Dave Farley:</a></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Over-complicating the solution is one of the commonest mistakes that I see TDD beginners make. They try to capture too much in one step. They prefer to have fewer more complex tests than many, small, simple tests that prod and probe at the behaviour of their system. The small steps, in thinking and in code, help a lot. Don’t be afraid of many small simple tests.</p>
</blockquote>



<h2 class="wp-block-heading"><span id="go-tdd-or-go-home">Go TDD or go home</span></h2>



<p>In the end, the circumstances pushed me all the way to TDD. I found myself in a situation where I had to maintain and further develop an application that processed billions of messages daily, had only a few tests, and had no access to developers who initially built it. It had complex and large classes and methods, scalability and reliability issues, and high hardware demands.</p>



<p>The only way to survive that was implementing much better code than I was doing before.</p>



<p>So, once again, I turned to books, videos, and courses about <a href="https://www.jbrains.ca/training/course/worlds-best-intro-to-tdd/" target="_blank" rel="noreferrer noopener">TDD</a>, <a href="https://martinfowler.com/articles/refactoring-2nd-ed.html" target="_blank" rel="noreferrer noopener">refactoring</a>, <a href="https://www.youtube.com/watch?v=tXTeLCwQZME" target="_blank" rel="noreferrer noopener">creating APIs</a>, and <a href="http://to%20https:/www.davefarley.net/?p=352" target="_blank" rel="noreferrer noopener">code quality</a> to improve my object design and its implementation.</p>



<p>This time, I implemented many (small?) changes in my designing and coding way of doing TDD:</p>



<ol class="wp-block-list" type="1" start="1">
<li>Working <a href="https://www.geepawhill.org/2021/09/29/many-more-much-smaller-steps-first-sketch/">in sm</a><a href="https://www.geepawhill.org/2021/09/29/many-more-much-smaller-steps-first-sketch/" target="_blank" rel="noreferrer noopener">a</a><a href="https://www.geepawhill.org/2021/09/29/many-more-much-smaller-steps-first-sketch/">ll, really small, steps</a> with a commit after each step (many 10s per day)</li>



<li>Stopping the <a href="https://ted.dev/articles/2023/05/30/your-classes-are-too-big-talk/" target="_blank" rel="noreferrer noopener">primitive obsession</a></li>



<li>Refactoring until the API design is good (&#8220;You are the first user of the API&#8221;) and tests are easy to write, understand, and maintain (&#8220;Tests are trying to tell you something&#8221;)</li>



<li>Doing <a href="https://shiftmag.dev/pair-programming-benefits-challenges-563/" target="_blank" rel="noreferrer noopener">pair programming</a></li>
</ol>



<p>I noticed significant changes in my code in a few months. It was <strong>simpler to understand,</strong> and the <strong>methods and classes were much shorter </strong>(but there were more classes). Adding new features wasn&#8217;t a challenge anymore, and other developers could help me in hours or, later, in minutes, <strong>without lengthy onboarding.</strong></p>



<p>With <a href="https://blog.thecodewhisperer.com/permalink/surviving-legacy-code-with-golden-master-and-sampling" target="_blank" rel="noreferrer noopener">Golden Master tests</a> and using TDD for new or changed and refactored code, soon there were enough tests and, as a result, confidence that <strong>changes to the code won&#8217;t carry any significant risk.</strong></p>



<p>In that short time, using TDD daily, I got very predictive and almost constant progress in the right direction with my coding, and I could provide value to my users better and faster.&nbsp;</p>



<h2 class="wp-block-heading">It wasn&#8217;t TDD; it was me</h2>



<p>In retrospect, I think that my problem with getting better code with TDD was in my design and coding skills, not in TDD. Not that they were particularly bad &#8211; I did manage to create and maintain large, complex, and successful applications/systems.</p>



<p>But <strong>I missed some (or many?) details that make TDD something people rave about</strong>. If you have the chance, find someone good at TDD and <a href="https://shiftmag.dev/pair-programming-benefits-challenges-563/" target="_blank" rel="noreferrer noopener">pair program</a> with them for a few days to see if it works for you.</p>



<p>What was your turning point in using TDD and getting good results? Please share your experience with me on&nbsp;<a href="https://twitter.com/kranjcec">Twitter</a>&nbsp;or&nbsp;<a href="https://www.linkedin.com/in/kranjcec/">LinkedIn</a>!&nbsp;</p>
<p>The post <a href="https://shiftmag.dev/test-driven-development-fail-and-success-1118/">How I failed at Test-Driven Development and what it took to get it right</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Two years into pair programming: The good and the challenging </title>
		<link>https://shiftmag.dev/pair-programming-benefits-challenges-563/</link>
		
		<dc:creator><![CDATA[Denis Kranjcec]]></dc:creator>
		<pubDate>Wed, 31 May 2023 10:25:31 +0000</pubDate>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Mob programming]]></category>
		<category><![CDATA[Pair programming]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=563</guid>

					<description><![CDATA[<p>In an attempt to speed up our development process, my teammates and I took a somewhat controversial route – we introduced pair programming. And it worked. </p>
<p>The post <a href="https://shiftmag.dev/pair-programming-benefits-challenges-563/">Two years into pair programming: The good and the challenging </a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2023/05/Pair-Programming.png?x91379" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/05/Pair-Programming.png 1200w, https://shiftmag.dev/wp-content/uploads/2023/05/Pair-Programming-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/05/Pair-Programming-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/05/Pair-Programming-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p>The team comprises developers with different backgrounds and levels of experience. The idea was to use pair programming to level the team and make everyone faster and more independent in developing new features. We already had positive experiences with pair/mob sessions when troubleshooting production problems or supporting our users (other engineers and support teams), so we gave it a go.&nbsp;</p>



<p>We&#8217;ve been at it for <strong>two years and are happily reaping the benefits</strong>.&nbsp;&nbsp;</p>



<h2 class="wp-block-heading"><span id="what-is-pair-programming">What is pair programming?&nbsp;</span></h2>



<p>Even though programming in a pair has been practiced since the dawn of programming, the practice was first introduced to a broader audience in the 90s. In his excellent book &#8220;<a href="https://learning.oreilly.com/library/view/extreme-programming-explained/0201616416/" target="_blank" rel="noreferrer noopener">Extreme Programming Explained</a>&#8221; from 1999., <strong>Kent Beck</strong> defined pair programming as follows:&nbsp;</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>All production code is written with two people looking at one machine, with one keyboard and one mouse. [&#8230;]There are two roles in each pair. One partner, the one with the keyboard and the mouse, is thinking about the best way to implement this method right here. The other partner is thinking more strategically..</em>.</p>
<cite>Kent Beck, Extreme Programming Explained, 1999</cite></blockquote>



<p>Today, there are more options for pair programming than sitting together in front of a computer with one keyboard and mouse, from simple screen sharing to specialized tools like <strong>Code With Me</strong> from JetBrains. However, the above-mentioned principle remains the same.&nbsp;</p>



<p>I heard about pair programming long ago and was always intrigued by it, but I hadn&#8217;t had practical experience before we introduced it two years ago. I heard a lot of positive experiences with it, and the success stories were impressive.&nbsp;</p>



<p>There is also a fair amount of skepticism, whereas the main concerns are that pair programming is expensive, slow, and necessarily ends in frustration – everything you would like to avoid in a team. And diametrically opposed to what we were trying to achieve.&nbsp;</p>



<h2 class="wp-block-heading"><span id="rocky-start-stellar-results">Rocky start, stellar results&nbsp;</span></h2>



<p>As the team was already collaborative and had a proven record of great teamwork, we weren&#8217;t afraid of pair programming ending in infighting. And yet,<strong> we were off to a rocky start.</strong>&nbsp;</p>



<p>Although everyone was theoretically up for trying pair programming, we didn&#8217;t want to make it mandatory. This meant that, in reality, people were quite shy about asking for pair programming.&nbsp;</p>



<p>One of the issues was that they often didn&#8217;t deem a feature valuable or complex enough to have two developers working on it, or there was pressure to code a feature as fast as possible – and talking about it all day long seemed like a waste of valuable time.&nbsp;There were also some social fears: <strong>What if other team members saw everything I don&#8217;t know, what I have to Google, how slow I am?&nbsp;&nbsp;</strong></p>



<p>We gave up on pair programming on routine, repetitive, and simple tasks because we didn&#8217;t get any added value. In that case, pair programming did prove too expensive. But, <strong>when adding new features, we saw more and more benefits</strong>.&nbsp;</p>



<p>It also took us some time to figure out how to be productive without frustrating each other with unhelpful comments and remarks. We found ways to work through things that bothered us (talking to team members can solve almost anything, right?). We took a pause when needed or moved programming sessions to different times. We didn&#8217;t use any specific tool for pair programming, just screen share and audio call.&nbsp;</p>



<p>Despite our hesitations, even the first pair programming sessions were a positive experience &#8211; mainly because we all learned more than we expected not only about programming, frameworks, or tools we used but also about the domain and the feature/problem we need to solve.&nbsp;&nbsp;</p>



<p>We noticed that the <strong>ratio between talking and coding was much higher than we expected</strong>. Since we better understood the problem, the developed solutions and code were better than they would have been if we were coding alone.&nbsp;</p>



<h2 class="wp-block-heading"><span id="better-readability-predictability-and-quality">Better readability, predictability, and quality&nbsp;</span></h2>



<p>In the beginning, the most experienced team member was the driver of most sessions, and we rarely switched roles during sessions. Still, we were noticeably more productive than working alone.&nbsp;&nbsp;</p>



<p>We paired for <strong>3-4 hours a day</strong>, as we had other operations and support we needed to attend to. Not to mention that pair programming requires complete focus and can be exhausting, so 3-4 hours per day was the maximum anyway.&nbsp;</p>



<p>Focus was strictly on the task at hand, without the usual interruptions (Slack, mail, phone&#8230;). We never got stuck on a problem and always learned from each other. Exhaustion aside, we were satisfied with the progress, and <strong>the results were better and more predictable than coding alone</strong>.&nbsp;</p>



<p>After a few months, we started with pair programming more often and switching roles. That&#8217;s when another positive side effect surfaced: The code was always readable because if it wasn&#8217;t, you immediately had questions about it.&nbsp;</p>



<p>The code quality, in general, was very good. And by quality, I&#8217;m referring to Dave Farley&#8217;s description: &#8220;<a href="https://twitter.com/davefarley77/status/1562834939204231168" target="_blank" rel="noreferrer noopener">The ability to change software easily, safely, and with confidence is a marker of its quality.</a>&#8220;. I would say that the solutions we implement regularly are the best that team could implement (in a similar timeframe), regardless of the way of the work.</p>



<p>When we switched to <a href="https://www.infobip.com/developers/blog/trunk-based-development-vs-feature-branching" target="_blank" rel="noreferrer noopener">trunk-based development</a>, the experience was even better. My favorite part was no pull requests or pull request reviews. The code was reviewed continuously, and since we had solid automated tests, we got all the benefits of continuous integration.&nbsp;</p>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<blockquote class="twitter-tweet" data-width="500" data-dnt="true"><p lang="en" dir="ltr">&quot;Why you&#39;re not using PRs in your project?&quot;<br>&quot;Because we prefer to use CI/CD&quot;<br>&quot;But but&#8230;&quot;<br>&quot;Listen, <a href="https://twitter.com/KentBeck?ref_src=twsrc%5Etfw">@KentBeck</a> invented CI, <a href="https://twitter.com/davefarley77?ref_src=twsrc%5Etfw">@davefarley77</a> invented CD. They both agree that PRs and feature branches are incompatible with CI/CD.<br>What do you know that they don&#39;t?&quot;</p>&mdash; Uberto Barbini (@ramtop) <a href="https://twitter.com/ramtop/status/1641690501416984578?ref_src=twsrc%5Etfw">March 31, 2023</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div></figure>



<h2 class="wp-block-heading"><span id="mob-programming">Mob programming&nbsp;</span></h2>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/05/Mob-Programming-1024x538.png?x91379" alt="" class="wp-image-635" srcset="https://shiftmag.dev/wp-content/uploads/2023/05/Mob-Programming-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/05/Mob-Programming-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/05/Mob-Programming-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/05/Mob-Programming.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>If two programmers do a better job than one, then three, four, or more programmers must do it even better, right? After our initial success with pair programming, we decided to try <strong>mob programming as well</strong>.&nbsp;</p>



<p>Whether you call it mob/team/ensemble/collaborative programming or software teaming, the practice follows <a href="https://twitter.com/WoodyZuill" target="_blank" rel="noreferrer noopener">Woody Zuill</a>&#8216;s definition from &#8220;<a href="https://softwareteaming.com/" target="_blank" rel="noreferrer noopener">Software Teaming</a>&#8221; book:&nbsp;<em>All the brilliant minds working together on the same thing, at the same time, in the same space, and at the same computer.</em></p>



<p>Or, in more practical terms:&nbsp;</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Software Teaming is a software development approach where the whole team works together on the same thing, at the same time, in the same space, and at the same computer. This is similar to Pair Programming, where two people sit at the same computer and collaborate on the same code at the same time. However, with Software Teaming, we extend the collaboration to everyone on the team while still using a single computer for writing the code and doing other work.</p>
<cite>Woody Zuill, Software Teaming</cite></blockquote>



<p>We were doing mob programming sessions online, sharing screens the way we do when pair programming. <strong>It showed the same benefits as pair programming but wasn&#8217;t much of an upgrade from it.&nbsp;</strong></p>



<p>We noticed it was even harder to stay focused. Usually, the driver and one navigator were actively paying attention, but others got distracted by other work. We opted to do more pair programming sessions instead but are leaving our options open.&nbsp;</p>



<p>Since we have been spending more time at the office recently, we will try to do<strong> mob programming sessions live to see if it makes a difference</strong>.<em> </em>If you&#8217;d like to know more about mob programming or try it out yourself, check the aforementioned book &#8220;<a href="https://softwareteaming.com/" target="_blank" rel="noreferrer noopener">Software Teaming</a>.&#8221; Dave Farley also <a href="https://www.youtube.com/watch?v=ikilHGYk5Fs" target="_blank" rel="noreferrer noopener">has a great video</a> on the topic, and Thierry de Pauw shared a lot of practical tips &amp; tricks <a href="https://twitter.com/tdpauw/status/1582318541906190337" target="_blank" rel="noreferrer noopener">in this thread.</a>&nbsp;</p>



<h2 class="wp-block-heading"><span id="intrigued-i-certainly-hope-so">Intrigued? I certainly hope so!&nbsp;</span></h2>



<p>Pair programming and trunk-based development have proven to be an excellent combination for us. We also started practicing <strong>test-driven development</strong> with more discipline to see if it would improve our work. That combination resulted in continuous progress and predictive feature releases every time we used it.&nbsp;</p>



<p>If this article has motivated you to try pair programming, here are some great resources to get you started:&nbsp;</p>



<ol class="wp-block-list" start="1">
<li><a href="https://martinfowler.com/articles/on-pair-programming.html" target="_blank" rel="noreferrer noopener">On Pair Programming &#8211; Birgitta Böckeler, Nina Siessegger</a>&nbsp;</li>



<li><a href="https://www.youtube.com/watch?v=fLG4m2kMkD4" target="_blank" rel="noreferrer noopener">Key to Pivotal Software&#8217;s success: Pair programming! (Rob Mee)</a>&nbsp;</li>



<li><a href="https://www.youtube.com/watch?v=RCDfBioUgts" target="_blank" rel="noreferrer noopener">I&#8217;ve Pair Programmed for 30,000 Hours: Ask Me Anything! — Joe Moore</a>&nbsp;</li>



<li><a href="https://www.youtube.com/watch?v=t92iupKHo8M" target="_blank" rel="noreferrer noopener">You Must Be Crazy To Do Pair Programming • Dave Farley • GOTO 2022</a>&nbsp;</li>



<li><a href="https://twitter.com/thiagoghisi/status/1621303250917163008" target="_blank" rel="noreferrer noopener">Remote Pair Programming Good Practices &#8211; Thiago Ghisi</a>&nbsp;</li>
</ol>



<p>And if you are already pair programming, share your experience with me on <a href="https://twitter.com/kranjcec" target="_blank" rel="noreferrer noopener">Twitter</a> or <a href="https://www.linkedin.com/in/kranjcec/">LinkedIn</a>!&nbsp;</p>
<p>The post <a href="https://shiftmag.dev/pair-programming-benefits-challenges-563/">Two years into pair programming: The good and the challenging </a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: shiftmag.dev @ 2026-04-20 02:34:39 by W3 Total Cache
-->