<?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"><channel><title><![CDATA[Beyond Code: Advance Your Tech Journey]]></title><description><![CDATA[An exploration of the skills and insights needed to excel in a career in software and thrive in the ever-evolving tech industry.]]></description><link>https://blog.jakedoran.co.uk</link><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 08:52:36 GMT</lastBuildDate><atom:link href="https://blog.jakedoran.co.uk/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How AI Is Changing What It Means to Be a "Good" Developer]]></title><description><![CDATA[With every new advance in technology, we are always redefining what it means to be a "good" developer.
In the pioneering days of the 1960s and 70s, a "good" developer was a master of precision. When y]]></description><link>https://blog.jakedoran.co.uk/how-ai-is-changing-what-it-means-to-be-a-good-developer</link><guid isPermaLink="true">https://blog.jakedoran.co.uk/how-ai-is-changing-what-it-means-to-be-a-good-developer</guid><category><![CDATA[AI]]></category><category><![CDATA[Career Growth]]></category><category><![CDATA[software development]]></category><category><![CDATA[TechTrends]]></category><category><![CDATA[Futureofwork]]></category><category><![CDATA[developer productivity]]></category><dc:creator><![CDATA[Jake Doran]]></dc:creator><pubDate>Wed, 08 Apr 2026 12:22:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/65152926f52ea9f9d5e3ce80/29155a0a-7755-400c-b4ce-69b50c0ba8ca.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With every new advance in technology, we are always redefining what it means to be a "good" developer.</p>
<p>In the pioneering days of the 1960s and 70s, a "good" developer was a master of precision. When you were punching holes into cards, a single typo wasn’t just an error, it was a wasted day of processing. Success meant having an intimate, low-level relationship with the hardware. You were responsible for managing every byte of memory and every CPU cycle.</p>
<p>As personal computing took hold, the goalposts shifted from hardware limitation to structural integrity. Being "good" meant writing robust, maintainable code. We turned our focus toward structured programming and object-oriented design, prioritising the longevity of a system and its ability to scale without collapsing under its own complexity.</p>
<p>Then the cloud age forced a third evolution: service-first thinking. Suddenly, a functional algorithm was insufficient. A "good" developer had to master the abstractions of distributed systems, scalability, and DevOps. You were no longer merely writing a program; you were architecting a resilient, 24/7 ecosystem.</p>
<p>Today, we stand at the threshold of a fourth redefinition.</p>
<p>And this one is more radical than the others.</p>
<p>The AI era is doing more than automating tasks, it is reshaping the traditional hierarchy of the industry. For decades, software development relied on a broad base of junior contributors handling high-volume implementation work, while a smaller number of architects made the decisive technical choices at the summit.</p>
<p>That pyramid is compressing into a flatter landscape. As portions of implementation are becoming commoditised, the baseline expectation for many developers is being pulled upward. More developers are being expected to think like solution architects earlier in their careers.</p>
<p>In this new reality, value is no longer derived from commit frequency or ticket velocity, but it is instead found in your ability to orchestrate, audit, and direct.</p>
<h2>The New Normal</h2>
<p>A developer’s skill is no longer measured solely by their technical grounding, but by their ability to translate complex logic into unambiguous intent. Communication has become a primary technical discipline.</p>
<p>Before AI a developer could find job security within the labyrinth of the code; if you were able to navigate a convoluted codebase, you were considered valuable by default. But as AI assumes the heavy lifting of boilerplate and implementation, the bottleneck has shifted from the keyboard to the mind. We are entering the age of intent-based development, where the primary task is no longer the manual construction of implementation logic, but the delivery of a flawless mental model to a machine capable of building it.</p>
<p>As the corporate mandate to "do more with less" accelerates, the traditional developer role is evolving under the pressure of AI-assisted velocity. In this high-stakes environment, AI literacy is no longer seen as a competitive edge, but rather a baseline requirement for professional survival.</p>
<p>True literacy, however, is not merely knowing how to "chat" with a model; it is a deep understanding of its underlying logic, its limitations, and its specific capabilities. Ultimately, this is the line of demarcation in the modern industry: the difference between a developer who is replaced by a machine and one who uses that machine to amplify their own architectural vision.</p>
<h3>Prompting as Functional Specification</h3>
<p>In a professional SDLC, we have never lacked context. Between design systems, Agile ceremonies, and explicit acceptance criteria, the "what" has always been well defined. Historically, however, the gap between a human-readable user story and a machine-executable program was bridged by a developer’s manual labour. The most effective developers were those who could internalise a nuanced requirement and mentally map out the precise technical constraints, data structures, and edge cases. They were translators, converting business intent into logical architecture that they would then disseminate to others to be manually built out.</p>
<p>In this new paradigm, the AI has effectively become the recipient of that delegation.</p>
<p>As execution becomes cheaper, specification becomes the primary engineering activity. The manual execution phase is no longer the differentiator it once was. Instead, the developer becomes the bridge between a Product Owner’s vision and a machine’s literalism. Within this framework, prompting must be reframed from a conversational shortcut into an exercise in functional specification discipline. While a human can infer meaning from a bullet point in a Jira ticket, a machine cannot.</p>
<p>As a result, "good" is now defined by the ability to transform high-level business goals into high-fidelity technical instructions. This demands a mastery of techniques that go beyond simple queries. We are all now required to think like architects, precisely because the machine has assumed the role of the scribe.</p>
<h3>From Author to Authority</h3>
<p>We are transitioning from a world where we are judged by the code we produce to one where we are judged by the code we permit to exist. Unlike traditional peer review (where one can assume shared human intuition and a mutual understanding of "why"), auditing AI requires a fundamental shift toward radical skepticism. You are no longer reviewing a colleague; you are interrogating an entity that possesses technical fluency but inconsistent judgement.</p>
<p>Consequently, the "good" developer now acts as a high-stakes editor for a tool capable of brilliant synthesis one moment and confident hallucination the next. It can optimise a function, but it cannot understand the domain-specific "why" behind a feature's existence. This requires acknowledging that while an AI is a great assistant, it remains blind to the nuances of business logic and the long-term trade-offs of maintainability, security, and systemic side effects.</p>
<p>In this new hierarchy, seniority is found in the authority to sign off on a solution rather than the manual labour of authoring it. This demands a specialised intuition for spotting the subtle logical flaws that a predictive model naturally glosses over in its rush to provide a correct-looking answer. Your role is to ensure that the sheer velocity of AI-assisted production remains aligned with the structural integrity and the commercial objective of the project.</p>
<p>Ultimately, the most vital skill in the modern toolkit is the wisdom to know exactly when to tell the machine "no."</p>
<h2>The Future-Fit Developer</h2>
<p>The industry’s transformation doesn't just change how software is written; it collapses the traditional model that once defined developer growth. We are entering an era where exposure to architectural responsibility arrives far earlier in a career than it used to.</p>
<p>In previous generations, a “junior” developer focused primarily on learning the mechanics of implementation. Today, as AI can produce senior-level output at junior-level cost, the role is shifting: the constraint is no longer throughput but judgement. Developers are increasingly expected to evaluate solutions and make architectural trade-offs, not merely execute them.</p>
<p>This shift introduces what might be called a wisdom gap: the space between a machine’s ability to generate solutions and a developer’s ability to verify whether those solutions are appropriate in context.</p>
<p>To bridge that gap, the "good" developer evolves from a polyglot implementer into a contextual navigator of systems. Progression is no longer defined by how well you can code; it is defined by how well you understand boundaries, trade-offs, and consequences across a system.</p>
<p>Professional longevity, therefore, is no longer found in attempting to outpace the machine, but in the collaborative intelligence required to guide it. AI accelerates the path to the “Aha!” moment, but it does not remove the responsibility of deciding what should happen next. In this environment, developers are no longer just builders of components, they are stewards of direction.</p>
<h3>Compressed Growth Trajectory</h3>
<p>If the role of the developer is changing, the timeline for becoming one is changing with it.</p>
<p>Traditionally, seniority emerged from years of accumulated exposure to implementation details and the slow internalisation of how languages behaved and how systems failed. Today, when AI can generate thousands of lines of syntactically correct code in seconds, learning is no longer tightly coupled to typing. The growth curve has shifted from repetition-driven mastery to concept-driven acceleration.</p>
<p>This changes what career progression actually measures. Increasingly, advancement depends less on how quickly a developer can implement features and more on how effectively they can evaluate solutions. AI accelerates execution, but it also amplifies the consequences of weak structural decisions.</p>
<p>As a result, Computer Science fundamentals are moving from academic background knowledge to operational decision-making tools. AI can produce working implementations quickly, but it still optimizes locally rather than globally, it does not inherently understand whether a solution aligns with long-term system constraints, scaling realities, or business context. That responsibility remains human.</p>
<h3>Intelligent Collaboration</h3>
<p>Where previous generations relied on documentation, code review cycles, and accumulated institutional knowledge to understand unfamiliar systems, today’s developer can interrogate a codebase conversationally. A “good” developer uses AI as an exploratory partner, asking why a system behaves the way it does, how a component evolved into its current shape, and what assumptions are quietly embedded in its architecture. The result is not just faster output, but faster orientation.</p>
<p>This changes how learning happens inside a project. Instead of treating implementation as the primary path to understanding, developers can now model alternative approaches before committing to them. They can ask how a different data structure might affect performance characteristics, how a boundary change might alter coupling, or how an architectural decision might influence future extensibility. The machine becomes a surface against which ideas can be tested early, cheaply, and repeatedly.</p>
<p>Crucially, this only works when AI is used as a reasoning partner rather than a reasoning substitute. Used passively, it becomes a crutch that accelerates output while quietly weakening understanding. Used deliberately, it becomes a mirror that exposes assumptions, surfaces trade-offs, and sharpens judgement. As a result, "good" developers don’t ask the system to think for them, they use it to think with them.</p>
<p>This is the shift from automation to collaboration. The developer is no longer working alone at the keyboard, nor are they delegating total responsibility to a model. Instead, they are conducting a continuous dialogue with the system. It's not about how often you use AI, but how deliberately you collaborate with it.</p>
<p>In this environment, the defining skill is no longer just writing solutions. It is knowing how to ask the kinds of questions that make solutions better before they are written. The “good” developer treats AI not as a replacement for judgement, but as a multiplier of it.</p>
<h2>Conclusion</h2>
<p>The definition of a “good” developer has never been static. It has always followed the location of the highest-leverage decisions in the software lifecycle. In previous eras, those decisions lived close to the implementation. In the AI era, they are moving upstream, into intent, structure, and judgement.</p>
<p>The developers who thrive will not be the ones who write the most code, but the ones who can translate ideas into systems with clarity and precision.</p>
]]></content:encoded></item><item><title><![CDATA[Automating Film Search with Postman and Watchmode API]]></title><description><![CDATA[With so many streaming services and so much content, it’s getting harder to keep track of what’s available where. Sure, some sites will tell you which platform a specific movie or show is on—but what if you don’t know exactly what you want to watch?
...]]></description><link>https://blog.jakedoran.co.uk/automating-film-search-with-postman-and-watchmode-api</link><guid isPermaLink="true">https://blog.jakedoran.co.uk/automating-film-search-with-postman-and-watchmode-api</guid><category><![CDATA[watchmode]]></category><category><![CDATA[Postman]]></category><category><![CDATA[api]]></category><category><![CDATA[PostmanTesting]]></category><category><![CDATA[film]]></category><dc:creator><![CDATA[Jake Doran]]></dc:creator><pubDate>Fri, 17 Oct 2025 20:54:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/MAYsdoYpGuk/upload/73c19144fe81ca3a22bb55a6b86b565e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With so many streaming services and so much content, it’s getting harder to keep track of what’s available where. Sure, some sites will tell you which platform a specific movie or show is on—but what if you don’t know <em>exactly</em> what you want to watch?</p>
<p>That was my dilemma recently. I wanted to watch something with <strong>Jason Statham</strong>, but I wasn’t sure which film I was in the mood for. I just wanted to see what was available across my subscriptions and choose from there. In my house we have <strong>Amazon Prime</strong>, <strong>Netflix</strong>, and <strong>Disney+</strong>, and the thought of searching each one manually sounded painful.</p>
<p>So… I automated it.</p>
<p>Using a <strong>Postman collection</strong> and a <strong>Watchmode API</strong> key, I built a small platform-agnostic search tool that pulls together every Statham title and tells me where I can stream it. Watchmode’s data isn’t perfect, but it’s reliable enough for casual browsing, and the API is so simple that you can be up and running in minutes.</p>
<h2 id="heading-the-watchmode-api-requests">The Watchmode API Requests</h2>
<ol>
<li><p>Make a request to the ‘search’ endpoint with the name of the actor you’re interested in to get their Watchmode id:<br /> <code>https://api.watchmode.com/v1/search/?apiKey={{api_key}}&amp;search_field=name&amp;search_value={{actor}}</code></p>
</li>
<li><p>Make a request to the ‘list-titles’ endpoint with that actor’s id to get their films as known by Watchmode:<br /> <code>https://api.watchmode.com/v1/list-titles/?apiKey={{api_key}}&amp;person_id={{actor_id}}</code></p>
</li>
<li><p>Make a request to the title’s ‘sources’ endpoint for each film listed to get the streaming services Watchmode think has it available:<br /> <code>https://api.watchmode.com/v1/title/{{title_id}}/sources/?apiKey={{api_key}}=GB</code></p>
</li>
</ol>
<p>You could run these manually - copying IDs from one response into the next - but where’s the fun in that? Let’s automate it.</p>
<h2 id="heading-making-it-dynamic-with-postman-variables">Making It Dynamic with Postman Variables</h2>
<p>If you’re new to Postman, the double braces (<code>{{api_key}}</code>, <code>{{actor}}</code>, etc.) represent <strong>variables</strong>. They let you store reusable values (like your API key or actor name) that Postman automatically substitutes into requests.</p>
<p>In this example:</p>
<ul>
<li><p><code>{{actor}}</code> might be <strong>Jason Statham</strong></p>
</li>
<li><p><code>{{api_key}}</code> is your Watchmode developer key</p>
</li>
</ul>
<h2 id="heading-automating-the-workflow">Automating the Workflow</h2>
<p>One of Postman’s best features is that you can run <strong>custom JavaScript</strong> before and after each request using the <strong>Pre-request Script</strong> and <strong>Tests</strong> tabs. This lets you capture response data, save it as variables, and use it in later requests - all automatically.</p>
<p>Here’s what our flow now looks like:</p>
<ol>
<li><p><strong>Search endpoint</strong></p>
<ul>
<li><p>Make a request for the actor’s name</p>
</li>
<li><p>Extract the actor’s Watchmode ID</p>
</li>
<li><p>Save it as a collection variable: <code>{{actor_id}}</code></p>
</li>
</ul>
</li>
<li><p><strong>List-titles endpoint</strong></p>
<ul>
<li><p>Use <code>{{actor_id}}</code> to fetch all films</p>
</li>
<li><p>Store each film’s ID and title as an array of objects in <code>{{titles}}</code></p>
</li>
</ul>
</li>
<li><p><strong>Sources endpoint</strong></p>
<ul>
<li><p>Loop over each title in <code>{{titles}}</code></p>
</li>
<li><p>Request the available streaming sources for each film</p>
</li>
<li><p>Save the results in a final variable: <code>{{available_on}}</code></p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-the-final-result">The Final Result</h2>
<p>With just a handful of lines of JavaScript and Postman’s Collection Runner, you can pull every title for an actor and see exactly which of your streaming subscriptions carry it - all without leaving Postman. Here’s what Jason Statham films Watchmode API said was available for my chosen streaming services:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"13"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"Operation Fortune: Ruse de Guerre"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"A Working Man"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"Fast &amp; Furious Presents: Hobbs &amp; Shaw"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"The Expendables 2"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"Meg 2: The Trench"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"Spy"</span>:[<span class="hljs-string">"Disney+"</span>],
    <span class="hljs-attr">"The Mechanic"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"The Expendables 3"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"The Expendables"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"Collateral"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"Homefront"</span>:[<span class="hljs-string">"Netflix"</span>,<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"The Transporter"</span>:[<span class="hljs-string">"Disney+"</span>],
    <span class="hljs-attr">"Transporter 2"</span>:[<span class="hljs-string">"Disney+"</span>],
    <span class="hljs-attr">"Transporter 3"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"Crank: High Voltage"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"Hummingbird"</span>:[<span class="hljs-string">"Disney+"</span>],
    <span class="hljs-attr">"Revolver"</span>:[<span class="hljs-string">"Netflix"</span>,<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"Cellular"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"Expend4bles"</span>:[<span class="hljs-string">"Netflix"</span>],
    <span class="hljs-attr">"Safe"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"Gnomeo &amp; Juliet"</span>:[<span class="hljs-string">"Prime Video"</span>],
    <span class="hljs-attr">"In the Name of the King: A Dungeon Siege Tale"</span>:[<span class="hljs-string">"Prime Video"</span>]
}
</code></pre>
<p>In the end I settled on <em>13,</em> a gritty and suspensful film about a desperate young man unknowingly entering an underworld game of Russian roulette.</p>
<h2 id="heading-how-it-works">How It Works</h2>
<p><strong>Test script</strong> for our ‘search’ request to get the actor id:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Parse JSON response</span>
<span class="hljs-keyword">let</span> jsonData = pm.response.json();

<span class="hljs-comment">// Ensure people_results exists</span>
<span class="hljs-keyword">if</span> (jsonData.people_results &amp;&amp; jsonData.people_results.length &gt; <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">let</span> person = jsonData.people_results[<span class="hljs-number">0</span>];
    <span class="hljs-keyword">let</span> actorId = person.id;

    <span class="hljs-comment">// Save actor ID</span>
    pm.collectionVariables.set(<span class="hljs-string">"actor_id"</span>, actorId);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`✅ Saved actor_id <span class="hljs-subst">${actorId}</span>`</span>);
}
</code></pre>
<p><strong>Test script</strong> for our ‘list-titles’ request to get the films:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> jsonData = pm.response.json();

<span class="hljs-keyword">if</span> (jsonData.titles &amp;&amp; jsonData.titles.length &gt; <span class="hljs-number">0</span>) {
    <span class="hljs-comment">// Save titles array</span>
    <span class="hljs-keyword">let</span> titlesArray = jsonData.titles.map(<span class="hljs-function"><span class="hljs-params">t</span> =&gt;</span> ({ <span class="hljs-attr">id</span>: t.id, <span class="hljs-attr">title</span>: t.title }));
    pm.collectionVariables.set(<span class="hljs-string">"actor_titles"</span>, <span class="hljs-built_in">JSON</span>.stringify(titlesArray));

    <span class="hljs-comment">// Initialize index for looping - used in our final request to loop over each title</span>
    pm.collectionVariables.set(<span class="hljs-string">"current_index"</span>, <span class="hljs-number">0</span>);

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"✅ Saved actor_titles and initialized current_index"</span>);
}
</code></pre>
<p><strong>Pre-request script</strong> for our ‘sources’ request to handle the looping over titles:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> titles = <span class="hljs-built_in">JSON</span>.parse(pm.collectionVariables.get(<span class="hljs-string">"actor_titles"</span>) || <span class="hljs-string">"[]"</span>);
<span class="hljs-keyword">let</span> index = <span class="hljs-built_in">parseInt</span>(pm.collectionVariables.get(<span class="hljs-string">"current_index"</span>) || <span class="hljs-string">"0"</span>);

<span class="hljs-keyword">let</span> currentTitle = titles[index];

<span class="hljs-keyword">if</span> (currentTitle) {
    pm.variables.set(<span class="hljs-string">"title_id"</span>, currentTitle.id);
    pm.variables.set(<span class="hljs-string">"title_name"</span>, currentTitle.title);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`\n🎬 [Title <span class="hljs-subst">${index + <span class="hljs-number">1</span>}</span>/<span class="hljs-subst">${titles.length}</span>] Processing: "<span class="hljs-subst">${currentTitle.title}</span>" (ID: <span class="hljs-subst">${currentTitle.id}</span>)`</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"⚠️ No title found for this index"</span>);

    <span class="hljs-comment">// Close the iterations</span>
    postman.setNextRequest(<span class="hljs-literal">null</span>);
}
</code></pre>
<p><strong>Test script</strong> for our ‘sources’ request to get the streaming sources offering each film:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Parse JSON response for sources</span>
<span class="hljs-keyword">let</span> sources = pm.response.json();

<span class="hljs-comment">// Retrieve existing results</span>
<span class="hljs-keyword">let</span> allResults = pm.collectionVariables.get(<span class="hljs-string">"available_on"</span>);
allResults = allResults ? <span class="hljs-built_in">JSON</span>.parse(allResults) : {};

<span class="hljs-comment">// Get current title info</span>
<span class="hljs-keyword">let</span> titleId = pm.variables.get(<span class="hljs-string">"title_id"</span>);
<span class="hljs-keyword">let</span> titleName = pm.variables.get(<span class="hljs-string">"title_name"</span>);

<span class="hljs-comment">// Target streaming services - the services I have access to</span>
<span class="hljs-comment">// Can add 'Amazon' if you're open to renting</span>
<span class="hljs-keyword">let</span> targetSources = [<span class="hljs-string">"Netflix"</span>, <span class="hljs-string">"Prime Video"</span>, <span class="hljs-string">"Disney+"</span>];

<span class="hljs-comment">// Array to hold found services</span>
<span class="hljs-keyword">let</span> servicesFound = [];

<span class="hljs-keyword">let</span> normalizedSources = sources.map(<span class="hljs-function"><span class="hljs-params">src</span> =&gt;</span> ({
    <span class="hljs-attr">name</span>: src.name ? src.name.trim().toLowerCase() : <span class="hljs-string">""</span>,
    <span class="hljs-attr">web_url</span>: src.web_url
}));

targetSources.forEach(<span class="hljs-function"><span class="hljs-params">target</span> =&gt;</span> {
    <span class="hljs-keyword">let</span> matched = normalizedSources.find(<span class="hljs-function"><span class="hljs-params">src</span> =&gt;</span> src.name.includes(target.toLowerCase()));
    <span class="hljs-keyword">if</span> (matched) {
        servicesFound.push(target);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`✅ Found <span class="hljs-subst">${target}</span> for "<span class="hljs-subst">${titleName}</span>"`</span>);
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`❌ <span class="hljs-subst">${target}</span> not found for "<span class="hljs-subst">${titleName}</span>"`</span>);
    }
});

<span class="hljs-comment">// Only set title if it's offered by our chosen services</span>
<span class="hljs-keyword">if</span> (servicesFound.length &gt; <span class="hljs-number">0</span>) {
    allResults[titleName] = servicesFound;
}

<span class="hljs-comment">// Save results</span>
pm.collectionVariables.set(<span class="hljs-string">"available_on"</span>, <span class="hljs-built_in">JSON</span>.stringify(allResults));

<span class="hljs-comment">// Increment index</span>
<span class="hljs-keyword">let</span> titles = <span class="hljs-built_in">JSON</span>.parse(pm.collectionVariables.get(<span class="hljs-string">"actor_titles"</span>) || <span class="hljs-string">"[]"</span>);
<span class="hljs-keyword">let</span> index = <span class="hljs-built_in">parseInt</span>(pm.collectionVariables.get(<span class="hljs-string">"current_index"</span>) || <span class="hljs-string">"0"</span>) + <span class="hljs-number">1</span>;

<span class="hljs-comment">// Loop or finish</span>
<span class="hljs-keyword">if</span> (index &lt; titles.length) {
    pm.collectionVariables.set(<span class="hljs-string">"current_index"</span>, index);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`➡️ Moving to next title (<span class="hljs-subst">${index + <span class="hljs-number">1</span>}</span> of <span class="hljs-subst">${titles.length}</span>)`</span>);
    postman.setNextRequest(<span class="hljs-string">"Request 3"</span>); <span class="hljs-comment">// loop to same request</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"✅ All titles processed!"</span>);
    postman.setNextRequest(<span class="hljs-literal">null</span>); <span class="hljs-comment">// stop run</span>
}
</code></pre>
<p>With everything configured, open Postman’s <strong>Collection Runner</strong>, select your collection, and set the request order to <strong>Search → Titles → Sources</strong>. Hit <strong>Run</strong>, and Postman will take care of the rest. When the run finishes, check your collection variables — you should see a new <code>{{available_on}}</code> variable containing your JSON blob of movie data.</p>
<p>In just a few clicks, you’ve built a custom, cross-platform movie search that finds films in seconds across all your streaming services.</p>
]]></content:encoded></item><item><title><![CDATA[Love and Leadership: Why a Good Manager is Basically the Perfect Valentine]]></title><description><![CDATA[Valentine’s Day is here, and while some are busy writing love letters to their significant others, let’s take a moment to appreciate the unsung heroes of our daily lives: great managers (such as myself). Because, let’s be honest - many of the qualiti...]]></description><link>https://blog.jakedoran.co.uk/love-and-leadership-why-a-good-manager-is-basically-the-perfect-valentine</link><guid isPermaLink="true">https://blog.jakedoran.co.uk/love-and-leadership-why-a-good-manager-is-basically-the-perfect-valentine</guid><category><![CDATA[valentine]]></category><category><![CDATA[valentines]]></category><category><![CDATA[management]]></category><category><![CDATA[satire]]></category><category><![CDATA[leadership]]></category><category><![CDATA[teamwork]]></category><dc:creator><![CDATA[Jake Doran]]></dc:creator><pubDate>Fri, 14 Feb 2025 08:52:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Y9mWkERHYCU/upload/380836635b570a8c6ccf31f198c4e72e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Valentine’s Day is here, and while some are busy writing love letters to their significant others, let’s take a moment to appreciate the unsung heroes of our daily lives: great managers (such as myself). Because, let’s be honest - many of the qualities that make an excellent leader also make for a fantastic partner. So, if you’re still searching for “the one”, maybe you should just date your boss! Just kidding - HR wouldn’t approve. Anyway here’s why the best managers might also be the ideal Valentine:</p>
<h3 id="heading-1-they-communicate-clearly">1. <strong>They Communicate Clearly</strong></h3>
<p>A good manager never leaves you in the dark. They check in, provide constructive feedback, and let you know where you stand. Just like in a healthy relationship, they won’t ghost you for weeks and then hit you with an unexpected “We need to talk”. They articulate expectations clearly, ensuring you feel secure and valued rather than confused or anxious.</p>
<h3 id="heading-2-they-have-a-sense-of-humour">2. <strong>They Have a Sense of Humour</strong></h3>
<p>A little workplace banter, a well-timed joke, or a funny meme in the team chat - good managers know how to keep things light. A sense of humour can make tough situations more bearable, whether it's a stressful deadline or a meet the parents style disaster. And let’s be real, a shared sense of humour is what makes both great workplaces and great relationships thrive.</p>
<iframe src="https://giphy.com/embed/lQ1nXVifuLqyVAH2Gu" width="480" height="398" class="giphy-embed"></iframe>

<h3 id="heading-3-they-respect-boundaries">3. <strong>They Respect Boundaries</strong></h3>
<p>Good managers know that you have a life outside of work (or at least, they should). They respect your personal time, ensuring that work doesn’t consume your entire existence. Similarly, a great partner wouldn’t expect you to be available 24/7 or guilt-trip you for needing space. If your manager texts you at all hours of the day with <em>urgent</em> tasks, well… that’s a different kind of relationship, and not the healthy kind.</p>
<h3 id="heading-4-they-make-you-feel-valued">4. <strong>They Make You Feel Valued</strong></h3>
<p>The best managers understand that feeling appreciated is key to motivation and satisfaction. They acknowledge hard work, show gratitude, and make their team members feel like an important part of something bigger. Likewise, a great partner consistently expresses appreciation, making sure you know just how much you mean to them. Whether it’s a thoughtful “thank you” or a grand gesture, knowing your efforts are seen and valued strengthens any relationship.</p>
<iframe src="https://giphy.com/embed/S6qkS0ETvel6EZat45" width="480" height="398" class="giphy-embed"></iframe>

<h3 id="heading-5-theyre-reliable-and-trustworthy">5. <strong>They’re Reliable and Trustworthy</strong></h3>
<p>In both business and love, trust is everything. A solid manager follows through on promises, ensures fairness, and always has your back. Just like a good partner remembers your anniversary, a dependable manager won’t suddenly switch priorities or ignore you when you need guidance.</p>
<h3 id="heading-6-they-handle-conflict-with-maturity">6. <strong>They Handle Conflict with Maturity</strong></h3>
<p>No passive-aggressive messages. No silent treatment. Just honest conversations to resolve issues efficiently. A great manager addresses conflicts head-on, listens to all sides, and works toward a solution instead of holding grudges. If only every relationship operated this smoothly - no more “I’m fine” and silent treatment when they’re definitely not fine!</p>
<iframe src="https://giphy.com/embed/j4qrUOkGoggBqXPTOU" width="480" height="398" class="giphy-embed"></iframe>

<h3 id="heading-7-they-celebrate-wins-in-meaningful-ways">7. <strong>They Celebrate Wins in Meaningful Ways</strong></h3>
<p>Much like a great partner cheers you on and is always by your side, a good manager makes sure your successes, big or small, don’t go unnoticed. But beyond simple recognition, they find ways to celebrate in meaningful ways - whether it’s a heartfelt shoutout in a meeting, a pizza lunch, or a simple but sincere slack message of appreciation. A partner who does the same - remembering milestones and making a big deal out of them - makes life that much sweeter.</p>
<h3 id="heading-8-they-offer-constructive-feedback">8. <strong>They Offer Constructive Feedback</strong></h3>
<p>A good manager doesn’t just point out what’s wrong - they help you improve by providing actionable and timely feedback and encouragement. Similarly, a good partner won’t just tell you that your cooking is bad - they’ll politely commend you for your efforts and gently suggest takeout when you offer to cook again.</p>
<iframe src="https://giphy.com/embed/fW5qirp4Nm9bC2qAHy" width="480" height="398" class="giphy-embed"></iframe>

<h3 id="heading-9-they-encourage-teamwork">9. <strong>They Encourage Teamwork</strong></h3>
<p>Micromanagers make terrible bosses, just like controlling partners make terrible significant others. A great manager makes their team feel heard and included, giving them the autonomy to work independently while offering support when needed. Likewise, a great partner trusts you to make your own choices, respects your independence, and cares about your opinions rather than trying to dictate everything.</p>
<h3 id="heading-10-they-adapt-to-changing-situations">10. <strong>They Adapt to Changing Situations</strong></h3>
<p>The best managers can navigate shifting priorities, unexpected challenges, and last-minute curveballs with grace. They don’t panic or shut down when things go off-script; they pivot, problem-solve, and keep things moving forward. Just like an ideal partner doesn’t crumble when date night plans fall apart or when life throws surprises their way. Instead, they roll with the punches, finding ways to make the best of any situation.</p>
<iframe src="https://giphy.com/embed/UrbnbuU24p1zgyDMUH" width="480" height="398" class="giphy-embed"></iframe>

<p>So this Valentine’s Day, if you’re single, don’t despair - just appreciate your great manager. They might not bring you chocolates, but at least they’re contractually obligated to care about you.</p>
<p>Happy Valentine’s Day to all the leaders, lovers, and those just trying to survive another day in the office!</p>
<p>- <em>Made with love and ChatGPT</em> ❤️</p>
]]></content:encoded></item><item><title><![CDATA[Mastering the Codebase: How to Quickly Achieve Actionable Understanding]]></title><description><![CDATA[As a software developer, your codebase is your most important asset. Much like a craftsman knowing their tools inside and out, understanding your codebase at a deep level is essential. Not only does this allow you to navigate your environment confide...]]></description><link>https://blog.jakedoran.co.uk/mastering-the-codebase-how-to-quickly-achieve-actionable-understanding</link><guid isPermaLink="true">https://blog.jakedoran.co.uk/mastering-the-codebase-how-to-quickly-achieve-actionable-understanding</guid><category><![CDATA[Career]]></category><category><![CDATA[Junior developer ]]></category><category><![CDATA[career advice]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Jake Doran]]></dc:creator><pubDate>Mon, 12 Aug 2024 17:41:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/v-3ujvHWuz0/upload/e920003d22e47c118ababe6d7837b176.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a software developer, your codebase is your most important asset. Much like a craftsman knowing their tools inside and out, understanding your codebase at a deep level is essential. Not only does this allow you to navigate your environment confidentially, it greatly improves the likelihood of making accurate estimates of effort and complexity and supports you in delivering high-quality work. Conversely, a lack of familiarity with the codebase can lead to misjudged timelines, increased technical debt, a higher likelihood of introducing bugs and/or inefficiencies and even stagnation in your professional development and career.</p>
<p>This post will explore practical strategies to help you get to know your codebase better, regardless of whether you're starting a new job or looking to get ahead professionally in your current position.</p>
<h2 id="heading-trace-code-execution">Trace code execution</h2>
<p>Following a piece of functionality through the codebase gives you a clear idea of the system's flow and operation. Are there lots of moving parts? Is everything handled in one place? Is the code new or old? By simply taking an action and unravelling its inner workings, you can quickly grasp the architecture and design of the code.</p>
<p>Start with the UI elements, if relevant, and then work through the code. This will allow you to compare the user flow with the code flow. Does it make sense? Are the two aligned? Compare the use of wording against variable and function names, are they conveying the same meaning?</p>
<p><strong>Tip:</strong> Take note of the filenames and endpoints as you trace the execution, this creates a sort of stack trace for you to follow. Additionally, check to see if there is any documentation covering the aspect of the system you're investigating. If there isn't any, your stack trace could become the basis of a new piece of technical documentation.</p>
<h2 id="heading-pair-program">Pair program</h2>
<p>If you're starting a piece of work in a new area or hear about someone working on something you haven't explored yet but find interesting, ask if you can work on it together. Pair programming with someone more familiar with the area allows you to ask questions and get up to speed more quickly, bypassing much of the trial and error and upfront investigation necessary when working alone.</p>
<p><strong>Tip:</strong> Before starting a pair programming session, ensure that goals of what you want to achieve from the session are clear. Agree on a specific problem to solve or a piece of the codebase to explore. Make sure to consider who performs the roles of "driver" and "navigator", as that might steer the learnings you can expect to gather.</p>
<h2 id="heading-take-advantage-of-pull-requests">Take advantage of Pull Requests</h2>
<p>Pull requests (PRs) are a great way to stay updated on the changes being implemented in the system. They also offer an opportunity to ask questions and understand different areas of the codebase you may not have worked on yet. This not only shows that you’re engaged but also helps you learn why certain decisions were made. Engaging with pull requests helps you learn from others’ work and keep a pulse on the evolving state of the code. Remember that you don't need to leave a review (approve, decline, request changes etc.) to be able to ask questions. So you can peruse at your leisure without having to worry about overstepping your mark by reviewing unsolicited.</p>
<p><strong>Tip:</strong> When reviewing pull requests, try to source them from as many different contributors as possible. This allows you to be exposed to a greater variety of ways of working and areas of the system.</p>
<h2 id="heading-review-and-update-documentation">Review and update documentation</h2>
<p>Although often seen as more of a chore than a resource, reviewing, producing, and updating documentation can be a valuable method for improving your knowledge of the codebase. By documenting what you know, you reinforce your understanding and create an easily accessible explanation of the system's inner workings. This also creates a valuable resource for others which in turn elevates their perception of you.</p>
<p><strong>Tip:</strong> As you review documentation check the change log/history if there is one. If you come across a section that hasn't been updated for a while, it could suggest its out of date.</p>
<h2 id="heading-review-the-commit-history">Review the commit history</h2>
<p>Understanding the evolution of the codebase and the rationale behind changes can provide context and insights into its current state. This can help you assess whether the foundation of the codebase is solid or problematic. With this knowledge, you can better estimate the feasibility of extending or maintaining the functionality.</p>
<p>In addition, when reviewing the commit history look for patterns in the types of changes being made. If you are consistently seeing bug fixes being applied to a particular area or module, it could suggest its no longer in active development and just in maintenance.</p>
<p><strong>Tip:</strong> Use IDE plugins/addons such as Git Lens and Git Blame to see the commit history from within your preferred IDE. Additionally, try to reach out to the developers who made significant changes to gain insights into their thought processes and any challenges they encountered.</p>
<h2 id="heading-start-by-writing-tests">Start by writing tests</h2>
<p>Writing unit tests, integration tests, or end-to-end tests forces you to understand the functionality and edge cases of the code. Reviewing existing tests can also provide valuable insights into code behaviour. If there are no automated tests, try using debugging tools to step through the code execution and learn how it operates.</p>
<p><strong>Tip:</strong> When writing tests, start with edge cases and boundary conditions that are most likely to expose bugs. If you're stepping through the code instead, use breakpoints strategically to pause at key points in the code. This allows you to observe the flow and state of the application at critical points. If you encounter unexpected behaviour, take note of the variables and their values and consider raising a ticket to address the issue.</p>
<h2 id="heading-play-around">Play around</h2>
<p>Try refactoring the code and observing what breaks! Does the whole system crash after a simple change, or is it a relatively painless experience? Knowing how easy or difficult it is to modify the code helps you predict how straightforward it will be to extend the functionality in the future.</p>
<p><strong>Tip:</strong> If you encounter any issues or quirks you weren't expecting, raise them as tickets or query them with other members of the team. Taking the initiative allows you to present yourself as proactive.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Mastering your codebase is a crucial step in your journey as a developer. By consistently exploring, questioning, and experimenting within the code, you’ll not only become more confident and capable but also enhance your overall effectiveness. Whether you’re starting a new job or aiming to deepen your expertise in your current role, investing time in understanding the codebase will set you apart as a knowledgeable and proactive professional. By embracing these strategies you’ll find yourself better equipped to tackle challenges, make informed decisions, and more quickly contribute meaningfully.</p>
]]></content:encoded></item><item><title><![CDATA[Estimating Effort: The Mark of an Experienced Developer]]></title><description><![CDATA[When asked to describe the qualities that define a great software developer, traits like effective communication, curiosity, teamwork, a positive attitude, creative problem-solving, and quick learning often come to mind. However, one crucial yet freq...]]></description><link>https://blog.jakedoran.co.uk/estimating-effort-the-mark-of-an-experienced-developer</link><guid isPermaLink="true">https://blog.jakedoran.co.uk/estimating-effort-the-mark-of-an-experienced-developer</guid><category><![CDATA[Career]]></category><category><![CDATA[Estimation]]></category><category><![CDATA[estimates]]></category><category><![CDATA[Junior developer ]]></category><category><![CDATA[Career Coach]]></category><dc:creator><![CDATA[Jake Doran]]></dc:creator><pubDate>Sun, 11 Aug 2024 15:21:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Cv1IZqKJQzU/upload/639195a4b776677af7e133590d85b77f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When asked to describe the qualities that define a great software developer, traits like effective communication, curiosity, teamwork, a positive attitude, creative problem-solving, and quick learning often come to mind. However, one crucial yet frequently overlooked and undervalued skill is the ability to accurately estimate the effort and complexity of a specific task. This skill not only reflects a developer's deep understanding of their craft and environment, but also plays a pivotal role in the success of projects and teams. In this blog post, we will explore the importance of estimation and why precise estimation is often a signifier of more senior software developers.</p>
<h2 id="heading-the-importance-of-accurate-estimations">The Importance of Accurate Estimations</h2>
<p>As software developers, the estimates we provide carry significant weight and often have broader implications than we might anticipate. Although these estimates are not meant to be commitments or promises, they are frequently interpreted as such by our colleagues, both technical and non-technical. These estimates can influence project plans, roadmaps, budgets, and resource allocation. Consequently, an inaccurate estimate can reflect poorly not only on ourselves but also on our team, department, and even the entire organisation.</p>
<p>This significance is amplified when providing estimates to individuals outside our team and organisation. When dealing with vendors, industry partners, and clients, our estimates are even more likely to be interpreted as commitments. There is no faster way to disappoint a third party than by overpromising and underdelivering.</p>
<p>So why are our estimates often taken out of context and misconstrued as promises? The reason lies in the differing languages spoken by developers and everyone else. We understand that a task's complexity can vary and that our estimates are informed guesses - nothing more. However, others deal in absolutes. When they hear "probably tomorrow," they interpret it as "tomorrow." This misunderstanding can lead to miscommunication, such as a client expecting a quick resolution to a support case or the board anticipating forecasted revenue from a newly developed product or feature.</p>
<h2 id="heading-the-difference-between-junior-and-senior-developers">The Difference Between Junior and Senior Developers</h2>
<p>It is clear then that accurate estimates are vital for any successful project. However, mastering this skill is a key factor that distinguishes junior developers from their more senior colleagues. In my opinion, it can also play an essential part in the success and rate of progress of a developer's career.</p>
<p>While you may think that being a good estimator comes down more to experience and expertise than to anything else, there are a lot more nuances involved in estimations. An estimate is a culmination of experience, ability, certainty, knowledge of the codebase, and an awareness of the wider environment.</p>
<p>Throughout my career, I have observed several common challenges that junior developers face with estimations:</p>
<ol>
<li><p><strong><em>Taking tasks at face value</em>:</strong> Junior developers often estimate only what is explicitly mentioned in a ticket, overlooking hidden complexities or dependencies that may affect the overall effort required.</p>
</li>
<li><p><strong><em>Limited knowledge of the codebase</em>:</strong> New developers may struggle to foresee how changes in one part of the codebase can ripple through other components or external dependencies, impacting their estimation accuracy.</p>
</li>
<li><p><strong><em>Overestimating their abilities</em>:</strong> Early in their careers, developers may underestimate the time and effort needed to complete tasks, not yet fully aware of the intricacies involved or the potential for unforeseen obstacles.</p>
</li>
<li><p><strong><em>Neglecting non-coding aspects</em>:</strong> Estimation involves more than just writing code. Junior developers may overlook tasks such as writing tests, undergoing code reviews, or obtaining approvals from other teams, leading to underestimated completion times.</p>
</li>
<li><p><strong><em>Difficulty in breaking tasks down</em>:</strong> Junior developers may attempt to tackle large tasks as a whole rather than breaking them down into smaller, manageable sub-tasks. This can lead to confusion and inaccurate estimations as they wade through the complexity they have unknowingly ventured into.</p>
</li>
</ol>
<p>Although juniors often struggle with estimating effort, it's important to note that senior developers are not infallible; they too face challenges. However, they are usually more adept at anticipating obstacles, breaking tasks into manageable chunks, and considering the broader implications of their work.</p>
<h2 id="heading-good-vs-bad-estimation">Good vs Bad Estimation</h2>
<p>After discussing the importance of estimation and the common pitfalls, let's now explore some typical types of estimators - both good and bad.</p>
<ul>
<li><p><strong><em>The People Pleaser</em></strong> - Nobody wants to be the bearer of bad news, especially when it comes to important tasks and deadlines, but no one avoids bad news as much as the people pleaser. In an effort to stay in everyone's good books they provide estimates based on what they think people want to hear rather than the reality. You will often find people pleasers giving unrealistic estimates just to keep others happy. An example could be agreeing to a shorter turnaround and then working overtime to make it happen, often leading to burnout or setting unrealistic expectations for future projects.</p>
</li>
<li><p><strong><em>The Overpromiser</em></strong> - A cousin to the people pleaser is the overpromiser. The overpromiser people pleases in a different way by providing estimates beyond expectation in order to appear more competent than perhaps they are. The overpromiser will often provide estimates without real investigation in order to seem in control and knowledgeable. However, often they underestimate the size of the task and are left looking incompetent, which can undermine trust and strain team collaboration. An example could be providing an estimate on a bug fix without investigating the issue first, stating something along the lines of "oh I know that what that is, it should be easy - 10 minutes tops". Low and behold 10 minutes go by and the issue is still nowhere near complete.</p>
</li>
<li><p><strong><em>The Underpromiser</em></strong> - The opposite of the overpromiser is the underpromiser. The underpromiser <strong>purposefully</strong> exaggerates their estimates so that they can always better them, with the hope that this makes them seem like a better developer. In reality, however, their lack of accuracy makes them appear unreliable and can be just as damaging as overpromising, often leading to unnecessary delays and missed opportunities for optimisation.</p>
</li>
<li><p><strong><em>The Evader</em></strong> - For fear of becoming a people pleaser or overpromiser, our next type of estimator refuses to estimate at all unless they are completely confident in their estimation. Choosing to evade the accountability of providing a bad estimate, the evader only acts in confidence. They hide behind terms such as "I don't know," "how long is a piece of string," and "I couldn't possibly say" in order to shirk responsibility. However, what they don’t realize is that providing no estimate at all can be more detrimental than offering a poor one, as it leaves teams and stakeholders without direction and unable to plan effectively.</p>
</li>
<li><p><strong><em>The Adjuster</em></strong> - The adjuster understands that estimates aren't always accurate and can change as new information surfaces. By transparently adjusting their estimates, they help stakeholders prepare for potential changes and build trust through ongoing communication. This approach allows teams to stay agile and responsive to evolving project demands.</p>
</li>
<li><p><strong><em>The Professional</em></strong> - The final type of estimator is the professional. Professionals understand that one estimate isn't accurate enough to depict the variability of software tasks. Instead, as described in Robert C. Martin's <em>The Clean Coder</em>, they provide three estimates; an optimistic estimate (perfect conditions), a nominal estimate (most likely conditions) and a pessimistic estimate (worse conditions). These estimates produce a distribution that highlights the possible timeframe for a task and allows project managers to better anticipate variance, leading to more realistic roadmaps and successful project outcomes.</p>
</li>
</ul>
<p>While there are many types of estimators, few consistently hit the mark. It’s not about always providing three estimates but about understanding the nuances of estimation and striving for continuous improvement. If you can relate to any of the more negative types of estimator, ask yourself what actions you can take to improve your consistency and reliability.</p>
<h2 id="heading-what-your-estimates-say-about-you">What Your Estimates Say About You</h2>
<p>By now, this should be clear: your estimates are more than just numbers - they are a reflection of your competency, consistency, and reliability. When you provide accurate and well-considered estimates, it demonstrates a deep understanding of your work and builds trust with your team and stakeholders. Consistency in your estimates signals that you can reliably gauge the scope of tasks, fostering confidence in your ability to deliver. On the other hand, frequent inaccuracies can lead others to question your expertise and dependability, potentially damaging your reputation. In essence, your estimates are a key factor in how others perceive your professional capabilities.</p>
<h2 id="heading-improving-your-estimates">Improving Your Estimates</h2>
<p>Having explored the variance, necessity, and importance of estimation, it's now time to focus on how to improve this critical skill. Estimation isn't just about guessing; it’s a craft that can be honed with the right techniques and mindset. Fortunately, there are many practical methods that aspiring developers can use to enhance their estimation accuracy. Let’s dive into some strategies to help you become a more reliable and confident estimator.</p>
<h3 id="heading-knowing-what-you-know"><strong>Knowing What You Know</strong></h3>
<p>Everyone loves a good four-box diagram, and one particularly relevant to estimation is the concept of <em>unknown unknowns</em>. By cultivating self-awareness and understanding the differences between what you know and what you don’t, you can factor in knowledge gaps and the potential for surprises in your nominal and pessimistic estimations. This approach helps you to be better prepared, justify your estimations, and support them with sound reasoning.</p>
<ul>
<li><p><strong><em>Known Knowns</em></strong> - These are things you know that you know.</p>
</li>
<li><p><strong><em>Known Unknowns</em></strong> - These are things you know that you don’t know.</p>
</li>
<li><p><strong><em>Unknown Knowns</em></strong> - These are things you don’t realize you know.</p>
</li>
<li><p><strong><em>Unknown Unknowns</em></strong> - These are things you don’t know that you don’t know.</p>
</li>
</ul>
<p>Let's look at this concept through the eyes of a worked example. Imagine you are tasked with improving the performance of a webpage by reducing the amount of upfront load and necessary database calls.</p>
<ul>
<li><p><strong><em>Known Knowns</em></strong> - You may already be aware of the tools and techniques available, such as lazy loading, caching strategies, and optimizing database queries and have experience of using them in other projects.</p>
</li>
<li><p><strong><em>Known Unknowns</em></strong> - You might know that there could be performance bottlenecks within your current database structure, but at this stage you're not sure where they are or how significant they might be in regards to improving the performance.</p>
</li>
<li><p><strong><em>Unknown Knowns</em></strong> - You might have access to team members or resources with relevant expertise that you haven’t fully explored.</p>
</li>
<li><p><strong><em>Unknown Unknowns</em></strong> - While working through the problem you might discover unknown dependencies or interactions within the codebase that you weren’t aware of. It could be that code is more tightly coupled that you realised meaning that the change you were planning to make might have unintended knock-on effects throughout the wider system.</p>
</li>
</ul>
<p>When you start to view problems through this lens it is easier to avoid overly optimistic estimations as you are bringing the possibility of unknown obstacles to your attention.</p>
<h3 id="heading-get-to-know-the-codebase">Get To Know The Codebase</h3>
<p>Just as a surgeon wouldn't operate without a thorough understanding of human anatomy, software developers shouldn't work without a deep knowledge of the codebase they're working on. Fortunately, gaining deep knowledge of your codebase doesn’t come with a hefty price tag or years of training, but it can be just as rewarding for your professional career.</p>
<p>When you have a thorough understanding of the environment in which you're working, you minimise the risk of nasty surprises. This not only makes your estimates more accurate and reliable but also provides the satisfaction of becoming a true domain expert. Best of all, achieving this level of understanding is possible regardless of your experience.</p>
<p>For a deeper dive into practical methods for mastering your codebase, check out this <a target="_blank" href="https://blog.jakedoran.co.uk/mastering-the-codebase-how-to-quickly-achieve-actionable-understanding">detailed guide</a>.</p>
<h3 id="heading-provide-a-range">Provide a Range</h3>
<p>We've already touched on this in <em>Good vs Bad Estimation</em>, but get used to providing a range of estimates instead of a single estimate. If your team only deals with one estimate currently, propose the idea of providing more than one. For example, workflow management tools like Jira often allow you to customise your tickets with as many pieces of information as you'd like, allowing you to represent all your estimates on the ticket. If the team shoots down your idea, then you can continue to implement the approach alone by communicating your optimistic, nominal and pessimistic estimates when you start a new piece of work.</p>
<h3 id="heading-take-time-to-reflect">Take Time to Reflect</h3>
<p>While team retrospectives are a key part of agile software development, individual reflection on a task-by-task level is a technique that’s often overlooked. Yet, it’s something you can easily implement to consistently improve your estimation skills. By taking time to reflect at the end of each task, you can identify aspects you’re proud of and areas where you may have fallen short.</p>
<p>Consider a task you either grossly underestimated or overestimated. Reviewing why your estimate was off in hindsight allows you to apply that knowledge to future tasks. If you simply move on to the next task without reflection, you miss an opportunity to refine your ability to estimate accurately. Not only that, but reflection can also highlight areas for improvement in other aspects of your software development career, such as code quality, test coverage, and documentation.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Estimation is more than just a technical skill - it's a hallmark of experience and professionalism in software development. As we’ve explored, the ability to accurately estimate the effort and complexity of tasks is essential not only for the success of individual projects but also for the long-term trajectory of your career. Accurate estimations build trust, enhance collaboration, and drive better decision-making within your team and organisation.</p>
<p>Whether you’re just starting out or looking to refine your skills, remember that great estimators are made, not born. By understanding the common challenges, learning from your experiences, and continuously improving your knowledge of the codebase and your environment, you can become a more reliable and respected developer. Estimation is a craft that evolves with time, practice, and reflection. Embrace the journey, and you'll find that the rewards extend far beyond just hitting deadlines - they define your impact as a developer.</p>
<p>As you continue to hone this vital skill, keep in mind that your estimates are more than just numbers. They are a reflection of your competency, consistency, and reliability, influencing how others perceive your professional capabilities. So, invest the time to master the art of estimation, and watch it transform your work, your team’s success, and your career.</p>
]]></content:encoded></item><item><title><![CDATA[The Ripple Effect: Understanding Language and Influence]]></title><description><![CDATA[As a manager, you find yourself in a unique position of responsibility and influence. However, while your responsibilities dominate your day to day, it is easy to forget the influence you hold. A momentary lapse in judgment, a harsh truth spoken, or ...]]></description><link>https://blog.jakedoran.co.uk/the-ripple-effect-understanding-language-and-influence</link><guid isPermaLink="true">https://blog.jakedoran.co.uk/the-ripple-effect-understanding-language-and-influence</guid><category><![CDATA[engagement]]></category><category><![CDATA[management]]></category><category><![CDATA[Culture]]></category><category><![CDATA[workplace]]></category><dc:creator><![CDATA[Jake Doran]]></dc:creator><pubDate>Sun, 04 Feb 2024 17:27:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FdLRkwDSkFw/upload/bec2f6de86c67ef8dd069a09c70cb5ea.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a manager, you find yourself in a unique position of responsibility and influence. However, while your responsibilities dominate your day to day, it is easy to forget the influence you hold. A momentary lapse in judgment, a harsh truth spoken, or uncaught body language can cause an unintended ripple effect, polluting your organisational culture both locally within your team and potentially even globally throughout the entire organisation.</p>
<p>To succeed in a managerial role then, it is essential to master the art of navigating and mitigating snap judgements, personal flaws and cognitive biases. But how can you maintain self-awareness and stay true to yourself, while simultaneously fostering a positive culture conducive to success? Throughout the following paragraphs hopefully the answer to that question will become clear, but before we delve into a solution we must first better understand the problem.</p>
<h2 id="heading-what-is-influence">What is influence?</h2>
<p>Influence refers to the capacity <mark>to have an effect on the thoughts, behaviours, or actions of others</mark>. It involves the ability <mark>to shape or sway opinions, decisions, and outcomes</mark>, often through leadership, or example. Influence can manifest in various forms, such as social influence, where <mark>individuals impact each other's attitudes and behaviours within a group</mark>, or professional influence, where leaders guide and motivate their team members.</p>
<p>Now that we've defined what is meant by the term influence in the context of this article, let's now analyse how our choice of language and position of influence can sometimes lead to unintended consequences.</p>
<h2 id="heading-the-impact-of-language"><strong>The impact of language</strong></h2>
<p>It is clear to see that a leader's actions and use of language extends beyond the immediate interaction from which it originates. Looking back at our definition of influence, I have highlighted what I believe to be the key points:</p>
<ul>
<li><p><strong><em>To have an effect on the thoughts, behaviours, or actions of others</em></strong> i.e. what we say and do has the potential to immediately impact those around us and often in ways that isn't immediately obvious.</p>
</li>
<li><p><strong><em>To shape or sway opinions, decisions, and outcomes</em></strong> i.e. others might think highly of our opinions and passing comments could lead to unintended decision making and outcomes if taken out of context or not fully understood.</p>
</li>
<li><p><strong><em>Individuals impact each other's attitudes and behaviours within a group</em></strong> i.e. we are also influenced by those around us and should be conscious of the messaging that we permit others in the group to share.</p>
</li>
</ul>
<p>Breaking down the definition in this way demonstrates how nuanced and subtle influence can be, as well as how important it is to be clear with our use of language. Any ambiguity is an opportunity to invite misinterpretation and confusion guaranteeing that the original intention is misunderstood. This is more noticeable with messaging tools like Slack and Microsoft Teams, where instant messages can be void of essential characteristics for meaning such as intonation, tone and emotion.</p>
<p>The dark side of influence is something that we don't usually consider in the moment but come to regret in future. Here is a recent example from LinkedIn where Duolingo's use of the word "quitter" was being interpreted as derogatory, rather than motivational/humorous which I assume their intention to have been. Reading the comments it is interesting to see how people's opinions differ based on their background and locality.</p>
<iframe src="https://www.linkedin.com/embed/feed/update/urn:li:share:7141519232000864256" height="910" width="504"></iframe>

<h2 id="heading-how-influence-shapes-culture">How influence shapes culture</h2>
<p>While it's largely common sense that influence shapes culture, it is worth knowing why and how. Edgar Schein, a well known and respected management professor at MIT, argues that "culture and leadership are two sides of the same coin." Having spent his career as an organisational expert, his experience studying corporations has led him to believe that culture is not a collection of mission statements, slogans and values but instead a product of a leader's interactions with their teams.</p>
<p>Ron Friedman references and summarises Schein's research in <em>The Best Place To Work</em>, highlighting that there are four main ways in which a leader can influence culture:</p>
<ul>
<li><p><strong><em>What leaders pay attention to (and what they ignore)</em></strong> i.e. where leaders decide to place their focus infers what they consider important and a priority. Always focussing on one item or always ignoring another, subconsciously suggests to the team what is and isn't important.</p>
</li>
<li><p><strong><em>Emotional outbursts</em></strong> i.e. what causes a leader to experience negative emotions such as anger, frustration and stress, signals what a leader truly cares about.</p>
</li>
<li><p><strong><em>Reactions to incidents and crises</em></strong> i.e. how a leader handles pressure and crisis creates a model for how team members will handle them in future.</p>
</li>
<li><p><strong><em>How leaders allocate rewards and status</em></strong> i.e. what actions and behaviours a leader chooses to positively reinforce are what others are likely to repeat and demonstrate.</p>
</li>
</ul>
<p>Clearly then, even the most casual or innocent remark could have long-term implications and consequences that shape the future of a workplace culture. In the following section I will share some real life examples that I've noticed from my own experiences.</p>
<h2 id="heading-examples-from-the-workplace">Examples from the workplace</h2>
<p>When you take the time to reflect and analyse why the things are the way they are, you begin to notice correlations between the way leaders act and the environment that surrounds them. Here are some examples of what I have noticed over the years and how they might have affected culture both positively and negatively:</p>
<ul>
<li><p><strong><em>Focussing on the edge cases -</em></strong> As we now know, what leaders pay attention to quickly permeates throughout the team. I've previously worked with engineering managers who have perhaps given too much attention to the edge cases of a particular piece of work. While sound in theory, after all no body wants to ship a broken feature, placing too much emphasis on finding edge cases created an environment in which things were overengineered and overcomplicated. Unfortunately, this impacted the feasibility of extending features and the refinement of new work was framed in the mindset of "what could go wrong" ultimately limiting innovation.</p>
</li>
<li><p><strong><em>Pandering to problem clients</em></strong> - When a client complains and is given preferential treatment in response to resolve their issue, it creates an environment in which he who shouts the loudest wins. It puts the client on a pedestal and elevates their position even above those in the team. Sadly, when this happens not only does the team find themselves in a position where they have to create one-off/temporary solutions, to often minor problems, but it also comes at the price of working on something else. From my own experiences, when this happens it impacts the engagement, motivation and morale of those involved as well as the potential future of the business.</p>
</li>
<li><p><strong><em>Promoting ownership and accountability</em></strong> - If you're looking to create trust and a high performance team, then promoting ownership is one way to do so. When a manager cares deeply about accountability and rewards those who hold themselves accountable for their actions, it signals to others that ownership is important. Working in an environment where ownership is not only encouraged but expected, wonderful things happen. Team member confidence increases, collaboration happens naturally and issues are resolved quickly.</p>
</li>
</ul>
<p>With these examples in mind, lets turn our attention to consciously building positive culture through the use of Schein's observations and our understanding of language and influence.</p>
<h2 id="heading-building-positive-culture">Building positive culture</h2>
<p>In the course of this article we have mostly concentrated on the negative consequences of influence. However, while it is possible to create a negative culture almost absentmindedly, it is just as easy to create a positive culture consciously.</p>
<p>Edgar Schein's key observations on corporate culture provide us with a framework in which we can operate. By taking advantage of the knowledge and the psychology behind his observations, we can use them to intentionally influence our workplace environment. This is the ripple effect in action.</p>
<p>By understanding and leveraging these points you can influence change in almost any area:</p>
<ul>
<li><p>Consciously focus on the things you care about as a leader and use praise and recognition to promote positive reinforcement.</p>
</li>
<li><p>Limit your emotional outbursts or use them, sparingly, to your advantage by ensuring its over something that you deem important.</p>
</li>
<li><p>Keep a cool head in times of crisis and use them as an opportunity to lead by example.</p>
</li>
</ul>
<p>As such if communication is something that is important to you, here is just one in which you can use the actions above to influence a more communicative culture:</p>
<ul>
<li><p>Give recognition and praise to good communication, be it client facing, internal documentation or otherwise.</p>
</li>
<li><p>Don't ignore bad communication as that would suggest that it is permissible. Instead highlight how it can be improved through actionable feedback.</p>
</li>
<li><p>Demonstrate that communication is important by creating metrics/OKRs and making it a focus point. For example, set a coverage goal for internal documentation or during refinement sessions make a point to consider what communication might be needed both internally and externally.</p>
</li>
<li><p>Use emotion tactfully. If there is a particularly bad example of communication (or lack of communication) you could consider using emotion to signal how important it is that it doesn't happen again. However, outbursts of emotion could have other side effects such as loss of team trust and fear of conflict.</p>
</li>
<li><p>Finally, if you find yourself in the unfortunate position of being in a crisis, use it as an opportunity to demonstrate good communication and lead by example. This could be done as easily as emphasising the need to communicate the incident internally e.g. by communicating the issue to support so they can be proactive rather than reactive to incoming help cases. Or it could be used as a learning opportunity by writing an incident report/conducting a post-mortem.</p>
</li>
</ul>
<p>While the given example of improving communication is a simple one, hopefully it illustrates the potential of the underlying framework.</p>
<h3 id="heading-reflection">Reflection</h3>
<p>To conclude then, these days it is simply not enough to only focus on your team, you also have to focus on yourself. Without self-awareness and introspection to keep yourself in check, the signals you subconsciously transmit could set your team and workplace down a negative path. The consequences of which you could be dealing with for years to come. As such, take the time to reflect and ensure you are fostering a positive workplace culture rather than a negative one. Regularly ask yourself the following questions:</p>
<ul>
<li><p>Are you focussing on the right tasks?</p>
</li>
<li><p>Do you show emotion at work?</p>
</li>
<li><p>How do you act under pressure?</p>
</li>
<li><p>Which behaviours do you publicly reward?</p>
</li>
<li><p>What language do you use when you talk about team members?</p>
</li>
</ul>
<p>By taking action, you are committing to building a workplace where influence is wielded responsibly, and language is a force for positive change. Remember, the impact of your actions today will shape the future of your team and organisation. Take the initiative and start consciously building a workplace culture that enables you and your team to thrive.</p>
<h3 id="heading-recommended-reading">Recommended Reading</h3>
<ul>
<li><p><em>The Best Place To Work</em> by Ron Friedman</p>
</li>
<li><p><em>Organisational Culture and Leadership</em> by Edgar Schein</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Engineering Management: Expectations vs. Realities]]></title><description><![CDATA[Embarking on a career in engineering management is often a journey filled with high aspirations and big dreams. As young engineers transition into leadership roles, they bring with them idealistic visions of how to lead teams, innovate, and drive cha...]]></description><link>https://blog.jakedoran.co.uk/engineering-management-expectations-vs-realities</link><guid isPermaLink="true">https://blog.jakedoran.co.uk/engineering-management-expectations-vs-realities</guid><category><![CDATA[engineering]]></category><category><![CDATA[engineering-management]]></category><category><![CDATA[management]]></category><category><![CDATA[reflection]]></category><category><![CDATA[career advice]]></category><dc:creator><![CDATA[Jake Doran]]></dc:creator><pubDate>Mon, 02 Oct 2023 17:56:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/mVwqZT2Ah6A/upload/b824b58ab5b58b3edcb3cd33de58b460.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Embarking on a career in engineering management is often a journey filled with high aspirations and big dreams. As young engineers transition into leadership roles, they bring with them idealistic visions of how to lead teams, innovate, and drive change. However, the path from idealism to realism is a transformative one, marked by challenges, learning curves, and the need for adaptability.</p>
<p>In this article, I shed light on my initial, somewhat naive, expectations of engineering management and contrast them with the actual experiences I have so far encountered in my role as Lead Developer at <a target="_blank" href="https://unity5.com/">Unity5</a>. It's essential to acknowledge that every company has its distinctive characteristics and ways of working, so you may encounter variations of what I detail below. Nevertheless, I aim to provide you with valuable insights that can serve as a guiding framework if you're contemplating going beyond the code and into management.</p>
<p>Here's a closer look at what I initially expected versus what I've learned through experience:</p>
<p><strong>Expectation:</strong> <em>To feel confident in all aspects of my role I would require sufficient management training.</em><br /><strong>Reality:</strong> Although I did participate in a one-day management workshop, which offered some valuable insights, it primarily reinforced that becoming a comfortable and effective manager would depend more on gaining experience rather than formal training. The realisation that it's acceptable not to have all the answers, has given me the confidence to fully embrace the role knowing that whatever happens, I'll be more prepared for future challenges.</p>
<p><strong>Expectation:</strong> <em>My workload would change from mostly technical duties towards mostly managerial ones.</em><br /><strong>Reality:</strong> Aside from conducting quarterly performance reviews and holding regular one-to-ones, my daily tasks have remained largely consistent. I continue to dedicate most of my time to feature development, code reviews and deployments. I'd estimate that on average my workload is split between roughly 80% development and 20% management each week.</p>
<p><strong>Expectation:</strong> <em>There might be a change in the dynamic within the team as I move from being a peer to a manager.</em><br /><strong>Reality:</strong> Becoming a manager brought about a shift in the team's dynamics but fortunately, it was a positive one. As we transitioned away from a flat team structure, team members began to feel that their voices were being heard more effectively and that they were receiving more personal attention. This has led to an increase in the engagement and job satisfaction of those in my team.</p>
<p><strong>Expectation:</strong> <em>I would have the time to think of big-picture ideas and processes.</em><br /><strong>Reality:</strong> Due to my continued involvement in product development, to get the time I need to think about things on a larger scale, I need to carve it out and reserve it for myself. As such, I typically allocate the last hour of each working day for "focus time" so that I can work on the things that are important to me.</p>
<p><strong>Expectation:</strong> <em>I would be involved in a lot more meetings.</em><br /><strong>Reality:</strong> A common cliché of engineers turned managers is that they are taken out of the code and dropped into a neverending cycle of meetings. However, I've found that the frequency of meetings I attend doesn't significantly differ from my time as a senior developer, though this will vary depending on the company.</p>
<p><strong>Expectation:</strong> <em>Working longer hours would become more the norm rather than the exception.</em><br /><strong>Reality:</strong> While I occasionally work outside of regular hours, it's not something I do regularly. That said, I can understand why I initially thought it might be necessary and why other managers may feel compelled to do so. If you find yourself unable to safeguard your time during working hours to focus on essential tasks, working outside of regular hours might seem like the only option. However, this just emphasises the significance of allocating dedicated time for yourself and for tasks that only you can do.</p>
<p><strong>Expectation:</strong> <em>I would more easily be able to bring about change.</em><br /><strong>Reality:</strong> Even within a fast-paced environment, introducing change can pose challenges. Not only does change necessitate questioning the status quo, but substantial changes also depend on gaining the support of others. In the end, it's not merely about enforcing change but rather about influencing it. This is something I didn't completely grasp until I stepped into a management role, and I acknowledge that I may have been somewhat ignorant of it beforehand.</p>
<p>Through reflecting on my journey into management and writing the above, it's clear that my initial expectations didn't align with the realities I've encountered, but in a surprisingly good way. Numerous concerns I had have been addressed, and my initial negative assumptions have been proven wrong. I am now a year into my new role and the position still provides me with a satisfying and meaningful challenge, offering opportunities to enact change within both the team and the larger organisation. While, in hindsight, I might have approached some aspects differently, I don't regret my decision to go beyond the code. I hope this introspection helps you if you are considering doing the same.</p>
]]></content:encoded></item></channel></rss>