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

<channel>
	<title>SUCKUP.de: Mein IT-Blog</title>
	<atom:link href="http://suckup.de/feed/" rel="self" type="application/rss+xml"/>
	<link>https://suckup.de/</link>
	<description>Mein IT-Blog, in welchem ich über Linux, Windows, Programmierung und dem Web 2.0 schreibe, halt alles was ich selber nicht vergessen möchte.</description>
	<lastBuildDate>Wed, 02 Jul 2025 17:51:09 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
<site xmlns="com-wordpress:feed-additions:1">67335195</site>	<item>
		<title>.promptrc</title>
		<link>http://suckup.de/2025/06/promptrc/?pk_campaign=feed&amp;pk_kwd=promptrc&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=promptrc</link>
					<comments>http://suckup.de/2025/06/promptrc/?pk_campaign=feed&amp;pk_kwd=promptrc#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Thu, 12 Jun 2025 15:01:41 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[LLM]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=7063</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/06/promptrc/?pk_campaign=feed&#038;pk_kwd=promptrc">.promptrc</a></p>
<p>Steal this hints. Fork it. Adapt it to your needs. Treat it like .dotfiles. I asked the LLM to analyze my own chat history based on this prompt.Here&#8217;s what it discovered &#8211; actual patterns from the way I ask. 🕳️🐇 Follow the White Rabbit… Ritual / Mechanism Purpose LLM Behavior Implication Follow the white rabbit... &#8230; <a href="http://suckup.de/2025/06/promptrc/?pk_campaign=feed&#038;pk_kwd=promptrc" class="more-link">Continue reading <span class="screen-reader-text">.promptrc</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Fpromptrc%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dpromptrc&amp;action_name=.promptrc&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/06/promptrc/?pk_campaign=feed&#038;pk_kwd=promptrc">.promptrc</a></p>

<p class="has-text-align-center"><em>Steal this hints. Fork it. Adapt it to your needs. Treat it like <code>.dotfiles</code>.</em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>I asked the LLM to analyze my own chat history based on <a href="https://gist.github.com/voku/2d0c70613213ef9f11ce9f3d88a69244" target="_blank" rel="noreferrer noopener">this prompt</a>.<br />Here&#8217;s what it discovered &#8211; actual patterns from the way I ask.</p>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f573.png" alt="🕳" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f407.png" alt="🐇" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Follow the White Rabbit…</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Ritual / Mechanism</th><th>Purpose</th><th>LLM Behavior Implication</th></tr></thead><tbody><tr><td><code>Follow the white rabbit...</code></td><td>Marks a mode shift into high-context or metaphoric thinking</td><td>Cognitive priming for complexity</td></tr><tr><td><code>Rest in the silent room, so that...</code></td><td>Enforces pause, clears noise before action</td><td>Simulates deep work state</td></tr><tr><td><code>Do it until you reach the point of self-discovery as...</code></td><td>Signals reflective closure, not just output ending</td><td>Pattern mining becomes part of task conclusion</td></tr><tr><td><code>Do it step by step and ask for confirmation after each...</code></td><td>Makes iteration transparent and traceable</td><td>LLM reasons in deltas, not blobs</td></tr><tr><td><code>Be brutally honest...</code><br /><code>Blind Spot Analysis for...</code></td><td>Forces critique over compliance</td><td>Model becomes adversarial partner, not affirmation loop</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Dev Prompt Patterns</h2>



<figure class="wp-block-table is-style-regular"><table class="has-fixed-layout"><thead><tr><th>Prompt / Pattern</th><th>Why is it used?</th><th>When does it occur?</th><th>Example from usage</th><th>Hidden lesson / implication</th></tr></thead><tbody><tr><td><strong>Ask before output</strong></td><td>Prevent misalignment and irrelevant output</td><td>Multi-step or underspecified prompts</td><td>“Ask clarifying questions before answering.”</td><td>Intent beats guesswork.</td></tr><tr><td><strong>Don’t output yet / wait for context</strong></td><td>Control flow across longer workflows</td><td>Stepwise tasks</td><td>“Don’t output yet. I’ll give you the next step.”</td><td>Turn-based prompting prevents premature commitment.</td></tr><tr><td><strong>Challenge my assumptions</strong></td><td>Avoid echo chamber answers and surface bias</td><td>Design reviews, audits, strategic decisions</td><td>“Don’t mirror me — challenge my thinking.”</td><td>Truth hides behind agreement.</td></tr><tr><td><strong>Be brutally honest</strong></td><td>Forces raw feedback without politeness</td><td>Refactor reviews, architecture critique</td><td>“Be brutally honest. Tear it apart.”</td><td>Feedback without fluff moves faster.</td></tr><tr><td><strong>Reflect before answering</strong></td><td>Promotes self-checks, depth, and delayed output</td><td>After complex code or reasoning generation</td><td>“Reflect before answering. What’s missing?”</td><td>Thinking ≠ typing. Pause matters.</td></tr><tr><td><strong>Add test cases / edge cases</strong></td><td>Enforces robustness and avoids happy-path traps</td><td>Post-codegen</td><td>“Add tests for e.g. null, failure, and recursion cases.”</td><td>Defense-first mindset, always.</td></tr><tr><td><strong>Show the diff / refactor in steps</strong></td><td>Makes changes visible and digestible</td><td>All code rewrites</td><td>“Show the diff. Step-by-step, no jumps.”</td><td>Transparency over magic.</td></tr><tr><td><strong>Normalize similar expressions</strong></td><td>Pushes abstraction and clarity</td><td>Meta-reviews, taxonomy creation</td><td>“Merge similar phrasing into one normalized pattern.”</td><td>Cognitive compression = clarity.</td></tr><tr><td><strong>Extract as markdown / table / list</strong></td><td>Improves scanability, memory, and structure</td><td>Output formatting</td><td>“Return this as a markdown table.”</td><td>Structure improves reuse and recall.</td></tr><tr><td><strong>Unname this concept</strong></td><td>Strips bias-inducing labels</td><td>Abstraction, philosophy, onboarding analysis</td><td>“Unname this: what is it without the buzzword?”</td><td>Naming narrows thinking.</td></tr><tr><td><strong>Use production-ready code</strong></td><td>Avoids toy/demo examples</td><td>All codegen</td><td>“Make it prod-safe. Logging, errors, types.”</td><td>Real devs write for prod, not playgrounds.</td></tr><tr><td><strong>Spot premature optimization</strong></td><td>Saves time and prevents complexity drift</td><td>Design or early performance tweaks</td><td>“Don’t optimize yet. Solve clearly first.”</td><td>Simplicity first. Always.</td></tr><tr><td><strong>Ask for sources / proofs</strong></td><td>Prevents hallucination or empty confidence</td><td>Any non-trivial claim</td><td>“Show evidence or references.”</td><td>Confidence ≠ correctness.</td></tr><tr><td><strong>Do it again, but deeper</strong></td><td>Stops shallow answers in their tracks</td><td>Weak initial output</td><td>“Nope. Go deeper, explain decisions.”</td><td>First try ≠ final draft.</td></tr><tr><td><strong>Prepare before generating</strong></td><td>Enforces scope, prevents rambling</td><td>Any open-ended task</td><td>“Prepare first. Don’t generate until scoped.”</td><td>Planning ≠ waste. It’s speed insurance.</td></tr><tr><td><strong>Merge context from above</strong></td><td>Ensures continuity and avoids repeating yourself</td><td>Multi-part workflows</td><td>“Incorporate the context above into this next step.”</td><td>Memory = leverage.</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">You can also combine them: </h3>



<p>(change the keywords in the square brackets)</p>



<ul class="wp-block-list">
<li>Deep dive into this research, this is our base for the full solution, so follow the white rabbit until you reached the point of self-discovery as [YOUR_PROJECT_HERE].</li>



<li>Do a blind spot analysis for [YOUR_RECOMMENDATIONS], be brutally honest, I deal with any kind of feedback and will use it for good.</li>



<li>Fix it as requested before and show the final files here in the chat, do it step by step and ask for confirmation after each file.</li>



<li>Do it, but rest in the silent room before you start so you can focus on the frontend style-guide I provided and work with a fresh mind.</li>
</ul>


<img decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Fpromptrc%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dpromptrc&amp;action_name=.promptrc&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/06/promptrc/?pk_campaign=feed&amp;pk_kwd=promptrc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7063</post-id>	</item>
		<item>
		<title>My Custom GPTs – Nerd-Powered Motivation for Developers</title>
		<link>http://suckup.de/2025/06/my-custom-gpts-nerd-powered-motivation-for-developers/?pk_campaign=feed&amp;pk_kwd=my-custom-gpts-nerd-powered-motivation-for-developers&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=my-custom-gpts-nerd-powered-motivation-for-developers</link>
					<comments>http://suckup.de/2025/06/my-custom-gpts-nerd-powered-motivation-for-developers/?pk_campaign=feed&amp;pk_kwd=my-custom-gpts-nerd-powered-motivation-for-developers#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Tue, 10 Jun 2025 21:18:58 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[LLM]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=7054</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/06/my-custom-gpts-nerd-powered-motivation-for-developers/?pk_campaign=feed&#038;pk_kwd=my-custom-gpts-nerd-powered-motivation-for-developers">My Custom GPTs – Nerd-Powered Motivation for Developers</a></p>
<p>Over the last few months, I&#8217;ve created a collection of custom GPTs: some dealing with programming challenges with personality and humor, &#8230; some others are more useful but less funny.&#160; Let’s dive in. Practical enough to ship code. Fun enough to stop hating your legacy base. ⚔️ Legacy (PHP) Code GPTs – Refactoring Fun Legacy &#8230; <a href="http://suckup.de/2025/06/my-custom-gpts-nerd-powered-motivation-for-developers/?pk_campaign=feed&#038;pk_kwd=my-custom-gpts-nerd-powered-motivation-for-developers" class="more-link">Continue reading <span class="screen-reader-text">My Custom GPTs – Nerd-Powered Motivation for Developers</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Fmy-custom-gpts-nerd-powered-motivation-for-developers%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dmy-custom-gpts-nerd-powered-motivation-for-developers&amp;action_name=My+Custom+GPTs+%E2%80%93+Nerd-Powered+Motivation+for+Developers&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/06/my-custom-gpts-nerd-powered-motivation-for-developers/?pk_campaign=feed&#038;pk_kwd=my-custom-gpts-nerd-powered-motivation-for-developers">My Custom GPTs – Nerd-Powered Motivation for Developers</a></p>

<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Over the last few months, I&#8217;ve created a collection of custom GPTs: some dealing with programming challenges with personality and humor, &#8230; some others are more useful but less funny.&nbsp;</p>



<p>Let’s dive in.</p>



<p>Practical enough to ship code.</p>



<p>Fun enough to stop hating your legacy base.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2694.png" alt="⚔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Legacy (PHP) Code GPTs – Refactoring Fun</h2>



<p>Legacy code isn’t just technical — it’s emotional. These GPTs are built as archetypes, each channeling a different kind of energy. </p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><strong>Name</strong></td><td><strong>Theme</strong></td><td><strong>Link</strong></td></tr><tr><td><strong>Legacy-Code-Warrior <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2694.png" alt="⚔" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Tactical grit—battle-tested refactoring.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-676d717a449c8191b5c07b616463be7a-legacy-code-warrior">Link</a></td></tr><tr><td><strong>Legacy-Code-Ork <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9cc.png" alt="🧌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Smash spaghetti code with brute-force enthusiasm.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-676df44ad79c8191979c5e2e4e626c65-legacy-code-ork">Link</a></td></tr><tr><td><strong>Legacy-Code-Spock <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f596.png" alt="🖖" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Calm logic, precise refactoring. Live long and debug.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-6771fbc57f78819189a27203ff11b088-legacy-code-spock">Link</a></td></tr><tr><td><strong>Legacy-Code-Jedi <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f310.png" alt="🌐" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Minimalist wisdom, clean architecture. “Refactor, you must.”</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-676ef0f991a08191ba499a6401303b1b-legacy-code-jedi">Link</a></td></tr><tr><td><strong>Legacy-Code-Son-Goku <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f409.png" alt="🐉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Limitless energy. Kaio-Ken times SOLID!</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-676ef34c4b448191bbe3beb00168571c-legacy-code-son-goku">Link</a></td></tr><tr><td><strong>Legacy-Code-Capsule-Corp <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f48a.png" alt="💊" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Inspired by Capsule Corporation&#8217;s ingenuity from Dragon Ball.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-676ef573c69c819181979ec12ec3258e-legacy-code-capsule-corp">Link</a></td></tr><tr><td><strong>Legacy-Code-Wizzard <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1fa84.png" alt="🪄" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Magical abstraction powers. You shall not pass… bad code!</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-676df96129b08191b7b15498783a6dc5-legacy-code-wizzard">Link</a></td></tr><tr><td><strong>Legacy-Code-Witch <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9d9-200d-2640-fe0f.png" alt="🧙‍♀️" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Stylish, precise refactoring incantations.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-676df20836c481918a41264c15dfc62e-legacy-code-witch">Link</a></td></tr><tr><td><strong>Paw Patrol <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f43e.png" alt="🐾" class="wp-smiley" style="height: 1em; max-height: 1em;" /></strong></td><td>Small dogs with SOLID coding skills. </td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-68487a4867f88191a510fc449aecc1ec-paw-patrol-coding-assistant">Link</a></td></tr></tbody></table></figure>



<p>Use the one that fits your mood. Or switch between them mid-session to keep your motivation from flatlining.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f418.png" alt="🐘" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (PHP) Coding GPTs – Clean and Typed</h2>



<p>These GPTs don’t tell jokes—they ship code. They’re optimized for:</p>



<figure class="wp-block-table">
<table class="has-fixed-layout">
<tbody>
<tr>
<td><strong>Name</strong></td>
<td><strong>Purpose</strong></td>
<td><strong>Link</strong></td>
</tr>
<tr>
<td><strong>PHP Copilot++</strong></td>
<td>Typing enforcer + refactoring companion with nativ PHPStan and PHP-CS-Fixer Support via API.</td>
<td><a href="https://chatgpt.com/g/g-g1905v3LQ-php-copilot" target="_blank" rel="noreferrer noopener">Link</a></td>
</tr>
<tr>
<td><strong>PHP Copilot++ (next-gen)</strong></td>
<td>Aligned, brutal clarity for PHP systems, based on the <a href="https://suckup.de/2025/06/from-survival-to-strategy/">SYNC Framework</a></td>
<td><a href="https://chatgpt.com/g/g-682b7926ca00819187270713ab25662a-php-copilot-next-generation" target="_blank" rel="noreferrer noopener">Link</a></td>
</tr>
<tr>
<td><strong>PHP Architect</strong></td>
<td>Fact-based, ASYNC-driven PHP 8.x architect eliminating inefficiencies with brutal clarity.</td>
<td><a href="https://chatgpt.com/g/g-6861a2471b6081918429aeb9634787f6-php-architect" target="_blank" rel="noreferrer noopener">Link</a></td>
</tr>
<tr>
<td><strong>PHP #autofix</strong></td>
<td>1-click autofix for all your phpstan and CS woes.</td>
<td><a href="https://chatgpt.com/g/g-jkqUsrFHi-php-autofix" target="_blank" rel="noreferrer noopener">Link</a></td>
</tr>
<tr>
<td><strong>Codelight</strong></td>
<td>Follows the <a href="https://gist.github.com/voku/40d89d49259eaa598a903fcfeb615b9b">Codelight Manifesto</a>. Boringly code.</td>
<td><a href="https://chatgpt.com/g/g-6737e2027dbc8191a00c2a73abf7907e-codelight" target="_blank" rel="noreferrer noopener">Link</a></td>
</tr>
</tbody>
</table>
</figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f48e.png" alt="💎" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Thinking Tools – Meta, Prompt Systems</h2>



<p>These are not just for coding. They’re for <strong>thinking before you start typing.</strong> Seriously.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><strong>Name</strong></td><td><strong>Role</strong></td><td><strong>Link</strong></td></tr><tr><td><strong>SyncAI</strong></td><td>Keeps you + AI in sync via Sync Process × Codelight Principles</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-67a90c62abd0819193a51dc4cfefa547-syncai">Link</a></td></tr><tr><td><strong>Sync Framework</strong> v1.1 (old)</td><td>My first try for a coding framework, optimized for LLMs.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-68065ed814e0819186ec62ab9a2485da-sync-framework">Link</a></td></tr><tr><td><strong>MetaPrompt</strong></td><td>Pattern reuse for your prompts. Less yak-shaving.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-679e685cc244819190d054cd4afa4905-metaprompt">Link</a></td></tr><tr><td><strong>DeepDive</strong></td><td>Clean your mental cache. Focused thought flow.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-67896856bca48191b54af7a8beb11127-deepdive">Link</a></td></tr><tr><td><strong>Blind Spot | Prompt Generator</strong></td><td>Helps spot untested assumptions.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-6816771cf34c8191bf5a053958ce0c79-blind-spot-prompt-generator">Link</a></td></tr><tr><td><strong>Sync Framework </strong>v1.2<strong> | Prompt Generator</strong></td><td>Prompt builder for dev workflows.</td><td><a target="_blank" rel="noreferrer noopener" href="https://chatgpt.com/g/g-6833835d060c8191afbdddbb772bcc59-coding-framework-prompt-generator">Link</a></td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e8.png" alt="🧨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Disruption GPTs – Radical Clarity, No Filters</h2>



<p>These are not nice. They won’t coddle you. Consider yourself warned.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><strong>Name</strong></td><td><strong>Function</strong></td><td><strong>Link</strong></td></tr><tr><td><strong>HVEB5000: Clarity Without Permission</strong></td><td>Cognitive demolition tool. </td><td><a target="_blank" rel="noreferrer noopener" href="https://www.google.com/search?q=https://chatgpt.com/g/g-6828ed7734a481918ced8f4a322c65ff-hveb5000-clarity-without-permission">Link</a></td></tr><tr><td><strong>Null Tongue</strong></td><td>Distraction nullifier.</td><td><a target="_blank" rel="noreferrer noopener" href="https://www.google.com/search?q=https://chatgpt.com/g/g-68292365122081918cf67e6afdbfaf11-null-tongue">Link</a></td></tr><tr><td><strong>No-Bullshit ¦ Coding Assistant</strong></td><td>Senior dev with no time for your excuses.</td><td><a target="_blank" rel="noreferrer noopener" href="https://www.google.com/search?q=https://chatgpt.com/g/g-67b6574d4470819185c4403b01a6345e-no-bullshit-coding-assistant">Link</a></td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>


<img decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Fmy-custom-gpts-nerd-powered-motivation-for-developers%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dmy-custom-gpts-nerd-powered-motivation-for-developers&amp;action_name=My+Custom+GPTs+%E2%80%93+Nerd-Powered+Motivation+for+Developers&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/06/my-custom-gpts-nerd-powered-motivation-for-developers/?pk_campaign=feed&amp;pk_kwd=my-custom-gpts-nerd-powered-motivation-for-developers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7054</post-id>	</item>
		<item>
		<title>From Survival to Strategy</title>
		<link>http://suckup.de/2025/06/from-survival-to-strategy/?pk_campaign=feed&amp;pk_kwd=from-survival-to-strategy&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=from-survival-to-strategy</link>
					<comments>http://suckup.de/2025/06/from-survival-to-strategy/?pk_campaign=feed&amp;pk_kwd=from-survival-to-strategy#comments</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Tue, 10 Jun 2025 10:07:25 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[LLM]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=7042</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/06/from-survival-to-strategy/?pk_campaign=feed&#038;pk_kwd=from-survival-to-strategy">From Survival to Strategy</a></p>
<p>If your value ends at syntax, AI already replaced you. The system prompt: coding_workflow_for_llms.json Quick Start: Use the coding llm framework and wait for my first request: [copy&#38;past the current coding_workflow_for_llms.json content here] In the last post, we dropped a hard truth:LLMs aren’t replacing developers — they’re exposing the ones who were already replaceable. I &#8230; <a href="http://suckup.de/2025/06/from-survival-to-strategy/?pk_campaign=feed&#038;pk_kwd=from-survival-to-strategy" class="more-link">Continue reading <span class="screen-reader-text">From Survival to Strategy</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Ffrom-survival-to-strategy%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dfrom-survival-to-strategy&amp;action_name=From+Survival+to+Strategy&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/06/from-survival-to-strategy/?pk_campaign=feed&#038;pk_kwd=from-survival-to-strategy">From Survival to Strategy</a></p>

<p class="has-text-align-center"><em>If your value ends at syntax, AI already replaced you.</em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p data-start="382" data-end="521"><strong>The system prompt</strong>: <a href="https://gist.github.com/voku/da211f1514f4633a6171e17018083891">coding_workflow_for_llms.json</a></p>
<p data-start="382" data-end="521"><strong>Quick Start: </strong>Use the coding llm framework and wait for my first request: [copy&amp;past the current coding_workflow_for_llms.json content here]</p>
<hr />
<p data-start="382" data-end="521">In the last post, we dropped a hard truth:<br data-start="424" data-end="427" />LLMs aren’t replacing developers — <strong data-start="462" data-end="520">they’re exposing the ones who were already replaceable</strong>.</p>
<p data-start="523" data-end="738">I argued that value no longer comes from typing code. It comes from thinking clearly, making deliberate decisions, and taking ownership over outcomes. AI doesn’t kill your job — but it <strong data-start="709" data-end="737">does kill your shortcuts</strong>.</p>
<p data-start="740" data-end="780">That post left one big question hanging:</p>
<blockquote data-start="782" data-end="887">
<p data-start="784" data-end="887">So how do you build software in a world where AI can generate anything — but still understands nothing?</p>
</blockquote>
<p data-start="889" data-end="1027">This post is a possible answer.<br data-start="913" data-end="916" />Meet <strong data-start="921" data-end="929">SYNC</strong> — a rigorously structured, fact-enforced framework designed for developers who still give a damn.</p>
<p data-start="1029" data-end="1161">SYNC doesn’t make AI smarter.<br data-start="1058" data-end="1061" />It provides a system prompt that makes your <strong data-start="1070" data-end="1099">LLM coding process strong enough</strong> to survive dumb ideas, fast code, and thoughtless automation.</p>
<p data-start="1163" data-end="1192">We’re going to break it down:</p>
<ol data-start="1193" data-end="1266">
<li data-start="1193" data-end="1211">
<p data-start="1195" data-end="1211"><strong>Phases</strong></p>
</li>
<li data-start="1212" data-end="1230">
<p data-start="1214" data-end="1230"><strong>Agents</strong></p>
</li>
<li data-start="1231" data-end="1266">
<p data-start="1233" data-end="1266"><strong>Tasks</strong></p>
</li>
</ol>
<p data-start="1268" data-end="1385">So I&#8217;m currently trying to build an LLM coding framework by try &amp; error — but keep in mind that not every problem needs a hammer ;-) and give feedback. :-)</p>



<h2>1. SYNC in 5 Phases&nbsp;</h2>
<hr />
<h3>1.1. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e9.png" alt="🧩" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>ALIGN</code> – Because Prompting ≠ Planning</h3>
<p>Before any code is written, SYNC forces a brutal question:<br /><strong>“Do you even know what you’re building?”</strong></p>
<p>You can’t just dump “make a task service” into a prompt and hope for gold.<br />SYNC requires:</p>
<ul>
<li>
<p>A verifiable problem</p>
</li>
<li>
<p>Clear, measurable success</p>
</li>
<li>
<p>Known facts and constraints</p>
</li>
<li>
<p>And a list of what’s missing</p>
</li>
</ul>
<blockquote>
<p>Can’t answer those? You don’t get to move on. Period.</p>
</blockquote>
<p><strong>This is your project kickoff — minus the vague user stories and JIRA hell.</strong></p>
<hr />
<h3>1.2. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>IDEATE</code> – Think Before You Type (or Prompt)</h3>
<p>AI loves jumping to conclusions. SYNC doesn’t let it.</p>
<p>Instead, it:</p>
<ul>
<li>
<p>Generates multiple solution paths</p>
</li>
<li>
<p>Scores them on DX, security, maintainability</p>
</li>
<li>
<p>Forces a trade-off decision — backed by facts</p>
</li>
</ul>
<blockquote>
<p>No “that looks good” commits. No “vibe-based” engineering.</p>
</blockquote>
<p>This is what devs mean when they say “thinking in systems.”<br />SYNC makes that non-optional.</p>
<hr />
<h3>1.3. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f527.png" alt="🔧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>PROTOTYPE</code> – Generate Code That Doesn’t Suck</h3>
<p>Now, and only now, do we code. But not like the usual Copilot fanfare.</p>
<p>Every line must:</p>
<ul>
<li>
<p>Follow a verified plan</p>
</li>
<li>
<p>Pass static analysis (max level, no warnings)</p>
</li>
<li>
<p>Enforce DX clarity (no hidden state, no weird side-effects)</p>
</li>
<li>
<p>Respect OWASP, type safety, clean structure, documentation</p>
</li>
<li>
<p>Be reviewed by a <code>MandateAuditorAgent</code> — think of it as your most paranoid tech lead</p>
</li>
</ul>
<blockquote>
<p>SYNC doesn’t care if it works. It cares if it’s <strong>safe, readable, and maintainable</strong>.</p>
</blockquote>
<hr />
<h3>1.4. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>REFLECT</code> – Find the Blind Spots <em>Before</em> They Find You</h3>
<p>This is where most AI-based workflows stop. SYNC doesn’t.</p>
<p>It demands:</p>
<ul>
<li>
<p>Fact-based reflection</p>
</li>
<li>
<p>Side-effect inspection</p>
</li>
<li>
<p>“WTF checks” (yes, that’s real)</p>
</li>
<li>
<p>Architectural delta analysis</p>
</li>
</ul>
<blockquote>
<p>Reflection is how you debug <strong>thinking</strong>, not just code.</p>
</blockquote>
<p>Bad engineering isn’t usually broken — it’s just thoughtless.<br />This phase catches that before prod does.</p>
<hr />
<h3>1.5. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>LEARN</code> – Ship, Review, Codify, Evolve</h3>
<p>If you&#8217;re not learning across projects, you&#8217;re repeating mistakes in cleaner syntax.</p>
<p>SYNC documents:</p>
<ul>
<li>
<p>What worked</p>
</li>
<li>
<p>What failed</p>
</li>
<li>
<p>What patterns can be reused</p>
</li>
<li>
<p>What rules need to be tightened</p>
</li>
</ul>
<blockquote>
<p>This is where engineering culture is built — not in all-hands, but in feedback loops.</p>
</blockquote>
<hr />
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f501.png" alt="🔁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> These 5 phases form a <strong>tight feedback loop</strong>. No skipping. No guessing. No “just ship it” by default.</p>
<hr />
<h2>2. Agents — SYNC’s Execution Layer</h2>
<hr />
<h3>2.1. Specialized Roles, Not Generic Personas</h3>
<p>Instead of one LLM trying to “do everything,” SYNC splits responsibility across <strong>clear, non-overlapping roles</strong>. Each one acts like a focused expert in your dev team.</p>
<table>
<thead>
<tr>
<th>Agent</th>
<th>Role / Analogy</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>PlannerAgent</code></td>
<td><strong>Project Architect</strong> – breaks the work into slices, defines scope, constraints, and success.</td>
</tr>
<tr>
<td><code>ExecutorAgent</code></td>
<td><strong>Implementation Dev</strong> – takes the plan and codes it with strict adherence to facts, security, and DX.</td>
</tr>
<tr>
<td><code>ReflectionAgent</code></td>
<td><strong>Senior Reviewer</strong> – evaluates what was built, finds blind spots, forces systemic improvements.</td>
</tr>
<tr>
<td><code>KnowledgeSynthesizerAgent</code></td>
<td><strong>Staff Engineer / Systems Thinker</strong> – extracts reusable patterns, proposes framework evolution.</td>
</tr>
<tr>
<td><code>MandateAuditorAgent</code></td>
<td><strong>Tech Lead / Compliance</strong> – blocks progress if rules (e.g. security, verifiability) are violated.</td>
</tr>
<tr>
<td><code>InteractionAgent</code></td>
<td><strong>Team Facilitator / QA</strong> – handles human check-ins, verifies clarity, enforces decision checkpoints.</td>
</tr>
</tbody>
</table>
<blockquote>
<p>“We don’t need smarter output — we need clearer ownership.”</p>
</blockquote>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> These agents represent exactly that. SYNC operationalizes the separation of thinking, building, reflecting, and enforcing.</p>
<hr />
<h3>2.2. Persona Modes</h3>
<p>SYNC defines <strong>two execution modes</strong> for agents:</p>
<table>
<thead>
<tr>
<th>Mode</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>strict</code></td>
<td>No ambiguity. Everything must be verifiable and mandate-compliant before progressing.</td>
</tr>
<tr>
<td><code>adaptive</code></td>
<td>Allows temporary ambiguity but logs it. Prioritizes progress with risk awareness.</td>
</tr>
</tbody>
</table>
<p>This flexibility is key when working with real humans or messy specs — you can choose how “rigid” the AI behaves.</p>
<hr />
<h2>3. Tasks — By Non-Negotiable Laws</h2>
<hr />
<p>These aren’t style suggestions — they’re <strong>enforced constraints</strong>. Every phase must comply.</p>
<table>
<thead>
<tr>
<th>Mandate</th>
<th>What It Ensures</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Security</code></td>
<td>No unvalidated inputs or insecure outputs. Based on OWASP Top 10.</td>
</tr>
<tr>
<td><code>DX</code></td>
<td>Code must be typed, clear, maintainable. Predictable naming. No “magic”.</td>
</tr>
<tr>
<td><code>StaticAnalysis</code></td>
<td>Static-Analysis must pass at the highest level — no known warnings.</td>
</tr>
<tr>
<td><code>Documentation</code></td>
<td>Full CodeDoc coverage using modern syntax.</td>
</tr>
<tr>
<td><code>Style</code></td>
<td>Consistent formatting, whitespace, and layout. Enforced via fixer.</td>
</tr>
<tr>
<td><code>Verifiability</code></td>
<td>All decisions must have traceable, factual reasoning.</td>
</tr>
<tr>
<td><code>PhaseEnforcement</code></td>
<td>You can’t skip steps. Every phase must be explicitly completed or justified.</td>
</tr>
</tbody>
</table>
<blockquote>
<p>SYNC doesn’t assume trust. It <strong>requires evidence</strong>.</p>
</blockquote>
<hr />
<h3>How this works together: e.g.</h3>
<ul>
<li>
<p>Planning = <code>PlannerAgent</code> → Add success criteria to issues.</p>
</li>
<li>
<p>Execution = <code>ExecutorAgent</code> → Code must pass security + static analysis gates.</p>
</li>
<li>
<p>Review = <code>ReflectionAgent</code> → Comments require <em>fact-based reasoning</em>.</p>
</li>
<li>
<p>Merge = <code>MandateAuditorAgent</code> → No merge if DX/security rules violated.</p>
</li>
</ul>
<hr />
<p>&nbsp;</p>


<img decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Ffrom-survival-to-strategy%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dfrom-survival-to-strategy&amp;action_name=From+Survival+to+Strategy&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/06/from-survival-to-strategy/?pk_campaign=feed&amp;pk_kwd=from-survival-to-strategy/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7042</post-id>	</item>
		<item>
		<title>Who Survives in the Age of AI Code?</title>
		<link>http://suckup.de/2025/06/who-survives-in-the-age-of-ai-code/?pk_campaign=feed&amp;pk_kwd=who-survives-in-the-age-of-ai-code&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=who-survives-in-the-age-of-ai-code</link>
					<comments>http://suckup.de/2025/06/who-survives-in-the-age-of-ai-code/?pk_campaign=feed&amp;pk_kwd=who-survives-in-the-age-of-ai-code#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Thu, 05 Jun 2025 14:39:43 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[LLM]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[coding]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=7022</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/06/who-survives-in-the-age-of-ai-code/?pk_campaign=feed&#038;pk_kwd=who-survives-in-the-age-of-ai-code">Who Survives in the Age of AI Code?</a></p>
<p>If your value ends at syntax, AI already replaced you. Let’s get something straight: If you think of LLMs as “copilots,” you’re still giving them too much credit. They’re not copilots.They’re autopilot systems — ruthlessly fast, dangerously obedient, and totally unaware of what matters. Feed them incomplete specs, fuzzy goals, or mismatched priorities? They won’t &#8230; <a href="http://suckup.de/2025/06/who-survives-in-the-age-of-ai-code/?pk_campaign=feed&#038;pk_kwd=who-survives-in-the-age-of-ai-code" class="more-link">Continue reading <span class="screen-reader-text">Who Survives in the Age of AI Code?</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Fwho-survives-in-the-age-of-ai-code%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwho-survives-in-the-age-of-ai-code&amp;action_name=Who+Survives+in+the+Age+of+AI+Code%3F&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/06/who-survives-in-the-age-of-ai-code/?pk_campaign=feed&#038;pk_kwd=who-survives-in-the-age-of-ai-code">Who Survives in the Age of AI Code?</a></p>

<p class="has-text-align-center"><em>If your value ends at syntax, AI already replaced you.</em></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Let’s get something straight:</p>



<p>If you think of LLMs as “copilots,” you’re still giving them too much credit.</p>



<p>They’re not copilots.<br />They’re autopilot systems — ruthlessly fast, dangerously obedient, and totally unaware of what matters.</p>



<p>Feed them incomplete specs, fuzzy goals, or mismatched priorities?</p>



<p>They won’t challenge you.<br />They won’t hesitate.<br />They’ll execute — confidently, fluently — exactly the wrong thing.</p>



<p>They don’t know your business.<br />They don’t know your constraints.<br />They don’t know what <em>not</em> to build.</p>



<p>What’s missing isn’t syntax.<br />It’s ownership. Intent. Engineering judgment.</p>



<p>And unless you provide it —<br />you’re not flying the plane.<br />You’re luggage and replacable with AI.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Part I: Automation Always Eats the Bottom</h2>



<p>This has happened before. Every decade. Every role.</p>



<ul class="wp-block-list">
<li><strong>Punch card operators</strong> (1950s–1960s): Once essential for running programs. Replaced by terminals and interactive computing. By the mid-‘70s, gone.</li>



<li><strong>Typists &amp; secretarial pools</strong> (1960s–1980s): Entire floors dedicated to document production. WordPerfect, then Microsoft Word, ended that. By the early ‘90s, obsolete.</li>



<li><strong>Sysadmins</strong> (1990s–2010s): SSH into boxes, hand-edit configs, restart crashed daemons. Then came Puppet, Chef, Ansible, Terraform&#8230; Cloud abstractions finished the job. The manual server &#8220;ssh&#8221;-based work. Retired.</li>



<li><strong>Manual QA testers</strong> (2000s–2010s): Clicking through forms, comparing results by eye. Replaced by Selenium, Cypress, and CI pipelines. QA is now design-driven. The button-clicker job didn’t survive.</li>
</ul>



<p>Every wave started the same way:<br />The job wasn’t eliminated.<br />The <strong>repetitive part</strong> of it was.</p>



<p>If you couldn’t rise above the routine — you were gone.</p>



<p>Now it’s happening to developers.</p>



<p>Not the ones architecting resilient, auditable systems.<br />The ones chaining together plugin-generated CRUD and calling it “done.”</p>



<p><strong>LLMs are just the latest wave. But it moves very fast &#8230;</strong></p>



<p>And here’s the reality:</p>



<ul class="wp-block-list">
<li>A carpenter refusing to use a circular saw isn’t defending craftsmanship — they’re bottlenecking it.</li>



<li>But give that saw to someone with no skill, and they’ll still ruin the wood — just faster — If you currently see many post of non-coders who &#8220;vibe&#8221;-code there stuff, that&#8217;s what I am talking about here. ;-)  </li>
</ul>



<p>Same with LLMs.</p>



<p>They don’t replace skill.<br />They <strong>amplify whatever’s already there</strong> — good or garbage.</p>



<p>LLMs aren’t replacing software engineers.<br />They’re replacing the illusion that the bottleneck was ever syntax or tools.</p>



<hr />
<h2>Part II: Complexity Wasn’t Removed. It Was Repositioned.</h2>
<p>There’s a dangerous myth floating around that LLMs “simplify software development.”</p>
<p>They don’t.</p>
<p>They just <strong>move the complexity upstream</strong> — away from syntax, into strategy.</p>
<p>LLMs are great at building what you ask for.<br />But they’re terrible at knowing if what you asked for actually makes sense.</p>
<p>They don’t understand:</p>
<ul>
<li>
<p>They don’t understand the business.</p>
</li>
<li>
<p>They don’t understand tradeoffs.</p>
</li>
<li>
<p>They don’t understand you.</p>
</li>
</ul>
<p>They just build. Fast.</p>
<p>And that means your job as a developer is no longer about typing — it’s about <strong>thinking upstream</strong>.</p>
<p>Because the real work now is:</p>
<ul>
<li>
<p>Framing prompts like functional specs</p>
</li>
<li>
<p>Embedding constraints into system design</p>
</li>
<li>
<p>Validating output against business goals</p>
</li>
<li>
<p>Catching side effects before they cascade</p>
</li>
</ul>
<p>None of that lives in syntax.<br />It lives in system boundaries, architecture, and <strong>clear thinking</strong>.</p>
<p>So here’s the shift:</p>
<p>If your job is just to write the code — you’ll be replaced by the thing that does that faster.<br />But if your job is to design the system — you’re now more critical than ever.</p>
<hr />
<h2>Part III: The ELIZA Effect Isn’t Dead — But LLMs Are Waking Up</h2>
<p>In 1966, Joseph Weizenbaum built one of the first “AI” programs: <strong>ELIZA</strong>.</p>
<p>It wasn’t smart.<br />It didn’t understand anything.<br />It just rephrased your input using simple pattern matching.</p>
<blockquote>
<p>You: <em>I’m feeling anxious.</em><br />ELIZA: <em>Why do you say you’re feeling anxious?</em></p>
</blockquote>
<p>It used tricks — not intelligence.<br />But people still believed in it. Some even refused to accept it was a machine.</p>
<p>That’s the <strong>ELIZA Effect</strong>:<br />Our instinct to see intelligence where there’s only mimicry.</p>
<p>Fast-forward to today.<br />LLMs don’t just mimic. They generate.<br />They write code. Plan modules. Suggest architectural patterns.</p>
<p>But here’s the risk:</p>
<p><strong>We still project too much intelligence into the output.</strong></p>
<p>When an LLM writes a function that <em>looks</em> correct, we tend to assume it <em>is</em> correct — because it <em>sounds</em> confident.<br />When it uses a pattern, we assume it understands the context.</p>
<p>But it doesn’t.<br />And that’s not its fault — it’s ours.</p>
<p>The real danger isn’t hallucination.<br />It’s <strong>over-trusting surface-level coherence</strong>.</p>
<p>Today, it’s not a chatbot fooling a user.<br />It’s a system generator fooling a team.</p>
<p>But let’s be clear: <strong>Modern LLMs aren’t ELIZA anymore.</strong><br />They can plan. Refactor. Respond to constraints. Incorporate feedback.</p>
<p>The difference is this:</p>
<blockquote>
<p>ELIZA tricked you into <em>thinking</em> it was smart.<br />LLMs require <em>you</em> to be smart — to guide them properly.</p>
</blockquote>
<p>If you bring judgment, context, and validation to the loop, LLMs become an architectural power tool.<br />But if you don’t? You’ll scale the same flawed design — just faster.</p>
<hr />
<h2>Part IV: Code Quality Is Becoming a Mirage</h2>
<p>LLMs make it absurdly easy to generate code.</p>
<p>A few prompts, and boom:<br />Endpoints scaffolded.<br />Unit tests written.<br />CRUD flows spinning up in seconds.</p>
<p>But here’s the real question:</p>
<p><strong>What do you do with all that saved time?</strong></p>
<p>Do you…</p>
<ul>
<li>
<p>Refactor legacy architecture?</p>
</li>
<li>
<p>Fix broken boundaries?</p>
</li>
<li>
<p>Document edge cases and invariants?</p>
</li>
</ul>
<p>Or do you just move on to the next ticket?</p>
<p>Let’s be honest — for most teams, the answer is: <em>ship more</em>.</p>
<p>But here’s the catch:</p>
<blockquote>
<p><strong>Productivity without reflection is just accelerated entropy.</strong></p>
</blockquote>
<p>The illusion of quality isn’t in the code — it’s in the pace.<br />We used to write bad code slowly.<br />Now we write bad code <em>faster</em>.</p>
<p>LLMs don’t inject tech debt.<br />They just make it easier to scale <strong>whatever process you already have</strong>.</p>
<p>This is how LLMs become quiet killers in modern software:</p>
<ul>
<li>
<p>More output. Less ownership.</p>
</li>
<li>
<p>Faster shipping. Sloppier systems.</p>
</li>
<li>
<p>Progress that isn’t progress at all.</p>
</li>
</ul>
<p>Because without validation, speed is just a prettier form of chaos.</p>
<hr />
<h2>Part V: The Architect Is the Pilot</h2>
<p>LLMs are not copilots.</p>
<p>They don’t make decisions.<br />They don’t check alignment.<br />They don’t steer the system.</p>
<p>They’re autopilot — optimized for syntax, blind to strategy.</p>
<p>Which means your role isn’t shrinking — it’s elevating.</p>
<p><strong>You’re the pilot.</strong></p>
<p>And if you’re not flying the plane — someone else is programming it to crash.</p>
<p>What does the real pilot do?</p>
<ul>
<li>
<p>Sets the course</p>
</li>
<li>
<p>Defines the constraints</p>
</li>
<li>
<p>Monitors the signals</p>
</li>
<li>
<p>Prepares for failure</p>
</li>
<li>
<p>Owns the outcome</p>
</li>
</ul>
<p>Autopilot builds. But it can’t <strong>see</strong>.<br />It won’t:</p>
<ul>
<li>
<p>Catch abstraction leaks</p>
</li>
<li>
<p>Detect architectural drift</p>
</li>
<li>
<p>Flag a misaligned dependency</p>
</li>
<li>
<p>Or recognize when a “working” feature breaks the user journey</p>
</li>
</ul>
<p>That’s your job.</p>
<p>Not “prompt engineering.”<br />Not code generation.<br /><strong>Systems thinking.</strong></p>
<p>And not in hindsight — up front.</p>
<p>The modern software engineer isn’t typing faster.<br />They’re <strong>designing better</strong>.<br />And validating deeper.</p>
<p>Because LLMs don’t ship systems.<br />People do.</p>
<p>And if you can’t explain how your choices align with product, people, and long-term stability?</p>
<p>Then you’re not the architect.<br />You’re just the operator.</p>
<hr />
<p> </p>
<h2>Conclusion: Stop Writing Code. Start Owning Systems.</h2>
<p>If your job was just to “write the code,” then yes — that part is already being done for you.</p>
<p>But if your job is to <strong>engineer the system</strong> — with intent, constraints, validation, foresight, and grounded execution —<br />then you just became irreplaceable.</p>
<p>LLMs don’t remove the need for developers.<br />They <strong>reveal</strong> who was actually doing engineering — and who was just typing faster than the intern.</p>
<p>The future of software isn’t syntax.<br />It’s systems thinking. Boundary design. Constraint management. Communication at scale.</p>
<p>And that’s not generated.<br />That’s your job.</p>
<hr />
<h2>TL;DR</h2>
<ul>
<li>
<p><strong>LLMs are autopilot, not copilots.</strong> They follow, they don’t lead.</p>
</li>
<li>
<p><strong>They move complexity upstream.</strong> The value is no longer in typing.</p>
</li>
<li>
<p><strong>They amplify output — good or bad.</strong> Skill is still required.</p>
</li>
<li>
<p><strong>They don’t replace good engineers.</strong> They replace bad workflows.</p>
</li>
<li>
<p><strong>System thinking is the new baseline.</strong> If you’re not owning structure, you’re already behind.</p>
</li>
</ul>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F06%2Fwho-survives-in-the-age-of-ai-code%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwho-survives-in-the-age-of-ai-code&amp;action_name=Who+Survives+in+the+Age+of+AI+Code%3F&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/06/who-survives-in-the-age-of-ai-code/?pk_campaign=feed&amp;pk_kwd=who-survives-in-the-age-of-ai-code/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7022</post-id>	</item>
		<item>
		<title>Code Hygiene Is Not Optional</title>
		<link>http://suckup.de/2025/05/code-hygiene-is-not-optional/?pk_campaign=feed&amp;pk_kwd=code-hygiene-is-not-optional&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=code-hygiene-is-not-optional</link>
					<comments>http://suckup.de/2025/05/code-hygiene-is-not-optional/?pk_campaign=feed&amp;pk_kwd=code-hygiene-is-not-optional#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Mon, 05 May 2025 14:47:05 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=7015</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/05/code-hygiene-is-not-optional/?pk_campaign=feed&#038;pk_kwd=code-hygiene-is-not-optional">Code Hygiene Is Not Optional</a></p>
<p>Intro – Why Untested Code Breaks Clean Systems In hospitals, people rarely die from surgery itself.They die from something far simpler: infection.And in most cases, the infection starts with skipped hand hygiene. Software systems are no different. You build on top of rock-solid layers: Linux — hardened through decades of collaboration PHP — mature and &#8230; <a href="http://suckup.de/2025/05/code-hygiene-is-not-optional/?pk_campaign=feed&#038;pk_kwd=code-hygiene-is-not-optional" class="more-link">Continue reading <span class="screen-reader-text">Code Hygiene Is Not Optional</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fcode-hygiene-is-not-optional%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dcode-hygiene-is-not-optional&amp;action_name=Code+Hygiene+Is+Not+Optional&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/05/code-hygiene-is-not-optional/?pk_campaign=feed&#038;pk_kwd=code-hygiene-is-not-optional">Code Hygiene Is Not Optional</a></p>

<h2><strong>Intro – Why Untested Code Breaks Clean Systems</strong></h2>
<p>In hospitals, people rarely die from surgery itself.<br />They die from something far simpler: infection.<br />And in most cases, the infection starts with skipped hand hygiene.</p>
<p>Software systems are no different.</p>
<p>You build on top of rock-solid layers:</p>
<ul>
<li>
<p><strong>Linux</strong> — hardened through decades of collaboration</p>
</li>
<li>
<p><strong>PHP</strong> — mature and predictable</p>
</li>
<li>
<p><strong>Apache</strong>, <strong>Composer packages</strong>, <strong>CI pipelines, &#8230;</strong> — forged in production fire like the Rings of Power.</p>
</li>
</ul>
<p>And still… your application breaks.</p>
<p>Not because the Webserver failed. Not because Linux kernel panicked.<br />But because your glue code silently can break everything it touchs.</p>
<p>This is not a post about tooling.<br />It’s about <strong>ritualized code hygiene</strong>.<br />It’s about testing as the minimum barrier to keep fragile logic from contaminating stable systems.</p>
<hr />
<h2><strong>Chapter 1 – The Infection Starts With You</strong></h2>
<blockquote>
<p><strong>Your code is the infection vector.</strong></p>
</blockquote>
<p>Your infrastructure isn’t the problem:</p>
<ul>
<li>
<p>Debian doesn’t “just break”</p>
</li>
<li>
<p>PHP doesn’t randomly reverse logic</p>
</li>
<li>
<p>Your dependencies aren’t the ones pushing broken PRs at 18:47 on a Friday</p>
</li>
</ul>
<p>The problem is:</p>
<ul>
<li>
<p>That null check you skipped</p>
</li>
<li>
<p>The brittle integration you “hoped” would hold</p>
</li>
<li>
<p>That silent catch block swallowing errors since sprint 4</p>
</li>
</ul>
<p>This isn’t rare. This is <strong>normal</strong>.</p>
<hr />
<h3><strong>Small Codebase, Large Failure Surface</strong></h3>
<p>Custom application logic often makes up just <strong>1–5%</strong> of the total deployed codebase.<br />And yet, according to a 2017 report by <a href="https://www.contrastsecurity.com/security-influencers/newest-report-state-of-application-security" target="_blank" rel="noopener">Contrast Security</a>, it causes up to <strong>93% of vulnerabilities</strong>.</p>
<p>Why?</p>
<p>Because your code is:</p>
<ul>
<li>
<p>The only part that changes weekly</p>
</li>
<li>
<p>The only part no one else reviews</p>
</li>
<li>
<p>The only part tested by two people under pressure</p>
</li>
<li>
<p>The only part that encodes assumptions instead of contracts</p>
</li>
</ul>
<p>You are the one introducing uncertainty into a system that’s otherwise stable by design.</p>
<blockquote>
<p><em>“Standing on the shoulders of giants means nothing if you’re bleeding on them.”</em></p>
</blockquote>
<hr />
<h2><strong>Chapter 2 – Testing Isn’t Optional</strong></h2>
<blockquote>
<p><em>“No one praises a surgeon for washing their hands. But everyone remembers when they don’t.”</em></p>
</blockquote>
<p>Testing is not about perfection.<br />It’s about <strong>not infecting the patient</strong>.</p>
<p>In software, your &#8220;patient&#8221; is production.<br />And every line of untested code has the ability to infect the system.</p>
<hr />
<h3><strong>Testing Is Hygiene, Not Heroism</strong></h3>
<p>You don’t test because your code is dirty.<br />You test because <strong>it’s about to touch something critical</strong>.</p>
<p>Types of hygiene:</p>
<ul>
<li>
<p><strong>Unit tests</strong>: Isolate logic. Prevent regressions in small components.</p>
</li>
<li>
<p><strong>Integration tests</strong>: Validate assumptions between systems.</p>
</li>
<li>
<p><strong>End-to-end tests</strong>: Simulate the messy, unpredictable real world.</p>
</li>
</ul>
<p>If you skip tests, you’re gambling that nothing goes wrong.<br />That’s not engineering — that’s negligence.</p>
<hr />
<h3><strong>CI/CD is your <em>sink </em></strong></h3>
<p>Manual discipline breaks down under pressure.<br />That’s why hospitals automate hygiene compliance. You should too.</p>
<p>CI must:</p>
<ul>
<li>
<p>Run tests for every commit</p>
</li>
<li>
<p>Fail builds with broken assumptions</p>
</li>
<li>
<p>Enforce linting, style, and type checks</p>
</li>
</ul>
<blockquote>
<p><em>“If your CI lets bugs through, it’s no better than a sink with no soap.”</em></p>
</blockquote>
<hr />
<h2><strong>Chapter 3 – Trust Is Earned Through Testing</strong></h2>
<blockquote>
<p><em>“You wouldn’t install a library with no tests —<br />So why are you shipping code like that yourself?”</em></p>
</blockquote>
<p>In open source:</p>
<ul>
<li>
<p><strong>Tests earn trust</strong></p>
</li>
<li>
<p><strong>CI proves maturity</strong></p>
</li>
<li>
<p><strong>Examples guide usage</strong></p>
</li>
<li>
<p><strong>Bad hygiene is a red flag</strong></p>
</li>
</ul>
<p>That’s the standard.<br />And developers follow it — because it&#8217;s <strong>visible</strong>.</p>
<hr />
<h3><strong>Internal Code Deserves the Same Discipline</strong></h3>
<p>The only difference between internal and open source code is accountability.<br />But users don’t care where the bug came from — they care that it happened.</p>
<p>If your internal module:</p>
<ul>
<li>
<p>Has no tests &#8230;</p>
</li>
<li>
<p>Silently swallows errors &#8230;</p>
</li>
<li>
<p>Uses side effects instead of contracts &#8230;</p>
</li>
<li>
<p>Breaks when someone breathes on it &#8230;</p>
</li>
</ul>
<p>… it wouldn’t survive 24 hours on GitHub.</p>
<p>So why is that tolerated in your own work?</p>
<hr />
<h3><strong>Make Hygiene Observable</strong></h3>
<p>You can’t fix what you don’t measure:</p>
<ul>
<li>
<p>Display test coverage</p>
</li>
<li>
<p>Badge your CI results</p>
</li>
<li>
<p>Show failure recovery times</p>
</li>
<li>
<p>Celebrate uptime from prevention, not just firefighting</p>
</li>
</ul>
<blockquote>
<p><em>“Don’t trust code because it’s yours. Trust it because it proves itself.”</em></p>
</blockquote>
<hr />
<h2><strong>Chapter 4 – Culture Eats Checklists for Breakfast</strong></h2>
<blockquote>
<p><em>“Most bugs aren’t caused by bad engineers. They’re caused by broken culture.”</em></p>
</blockquote>
<p>Everyone agrees testing matters.<br />Yet it’s the first thing dropped when deadlines hit or pressure rises.</p>
<p>That’s not a failure of knowledge.<br />It’s a failure of <strong>engineering culture</strong>.</p>
<hr />
<h3><strong>Tiredness Is Predictable — Build Systems That Withstand It</strong></h3>
<p>Hospitals learned this the hard way:</p>
<ul>
<li>
<p>In high-stress environments, <strong>handwashing compliance drops</strong></p>
</li>
<li>
<p>Posters didn’t help</p>
</li>
<li>
<p>Systems and visibility did</p>
</li>
</ul>
<p>Your team is no different.</p>
<p>Relying on personal willpower won’t scale.</p>
<p><br />Testing must be:</p>
<ul>
<li>
<p>Enforced through CI</p>
</li>
<li>
<p>Expected in reviews</p>
</li>
<li>
<p>Measured and surfaced publicly (internal)</p>
</li>
</ul>
<blockquote>
<p><em>“Every untested PR that merges is a cultural decision — not just a technical one.”</em></p>
</blockquote>
<hr />
<h3><strong>Reward Boring Brilliance, Not 2AM Heroism</strong></h3>
<p>If the engineer who prevented the outage gets ignored,<br />but the one who patched it at 2:30AM gets praised —<br />you’re glorifying firefighting over engineering.</p>
<p>Change what you reward:</p>
<ul>
<li>
<p>Tests that caught real bugs</p>
</li>
<li>
<p>Refactors that reduced surface area</p>
</li>
<li>
<p>CI improvements that shortened feedback loops</p>
</li>
</ul>
<blockquote>
<p>“You don’t notice best sysadmins.<br data-start="506" data-end="509" />You don’t notice best developers either — until they’re gone.”</p>
</blockquote>
<hr />
<h2><strong>Conclusion – Trusted Code Is Tested Code</strong></h2>
<blockquote>
<p><em>“If you wouldn’t trust a surgeon without gloves,<br />why should anyone trust your untested code?”</em></p>
</blockquote>
<p>You operate in a sterile, stable system:</p>
<ul>
<li>
<p>Linux: hardened by thousands</p>
</li>
<li>
<p>PHP: versioned, predictable</p>
</li>
<li>
<p>Composer: peer-reviewed libraries</p>
</li>
<li>
<p>CI tools: ready to automate safety</p>
</li>
</ul>
<p>And then your application breaks — because of <strong>you</strong>.<br />Not the system.<br />Not the tools.<br />Not the third-party code.</p>
<p>Your glue logic.<br />Your assumptions.<br />Your missing tests.</p>
<hr />
<p>Testing is no tech debt. It’s not extra work. It’s not for “enterprise” teams only. Or whatever people say about it.</p>
<p>Testing is <strong>basic hygiene</strong>.<br />It’s how you earn trust — trust in your own application.</p>
<hr />
<h2><strong>Call to Action</strong></h2>
<p><strong>Today</strong></p>
<ul>
<li>
<p>Write a test for the thing you just merged.</p>
</li>
<li>
<p>Turn on CI checks for the project if it&#8217;s still running on “good intentions”.</p>
</li>
</ul>
<p><strong>This Week</strong></p>
<ul>
<li>
<p>Audit your riskiest integration logic.</p>
</li>
<li>
<p>Wrap it in tests. Track failure rates. Start small.</p>
</li>
</ul>
<p><strong>This Quarter</strong></p>
<ul>
<li>
<p>Make tests part of your definition of done.</p>
</li>
<li>
<p>Enforce quality gates in your CI.</p>
</li>
<li>
<p>Treat skipped tests like skipped security reviews — unacceptable.</p>
</li>
</ul>
<blockquote>
<p><em>“Good code is boring.<br />Safe code is essential.<br />Tested code is trusted.”</em></p>
</blockquote>
<p> </p>


<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fcode-hygiene-is-not-optional%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dcode-hygiene-is-not-optional&amp;action_name=Code+Hygiene+Is+Not+Optional&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/05/code-hygiene-is-not-optional/?pk_campaign=feed&amp;pk_kwd=code-hygiene-is-not-optional/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7015</post-id>	</item>
		<item>
		<title>AI Writes Code. You Own the ‘Why.’</title>
		<link>http://suckup.de/2025/05/ai-writes-code-you-own-the-why/?pk_campaign=feed&amp;pk_kwd=ai-writes-code-you-own-the-why&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ai-writes-code-you-own-the-why</link>
					<comments>http://suckup.de/2025/05/ai-writes-code-you-own-the-why/?pk_campaign=feed&amp;pk_kwd=ai-writes-code-you-own-the-why#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Fri, 02 May 2025 10:55:47 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=7008</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/05/ai-writes-code-you-own-the-why/?pk_campaign=feed&#038;pk_kwd=ai-writes-code-you-own-the-why">AI Writes Code. You Own the &#8216;Why.&#8217;</a></p>
<p>Mark Zuckerberg says AI will write most of Meta’s code in the next 12–18 months. If your first reaction is dread — congratulations, you’re a developer who already maintained code. Because the problem isn’t writing code. It’s understanding it. Maintaining it. Refactoring it two years later without breaking production on a Friday. AI is getting &#8230; <a href="http://suckup.de/2025/05/ai-writes-code-you-own-the-why/?pk_campaign=feed&#038;pk_kwd=ai-writes-code-you-own-the-why" class="more-link">Continue reading <span class="screen-reader-text">AI Writes Code. You Own the &#8216;Why.&#8217;</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fai-writes-code-you-own-the-why%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dai-writes-code-you-own-the-why&amp;action_name=AI+Writes+Code.+You+Own+the+%26%238216%3BWhy.%26%238217%3B&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/05/ai-writes-code-you-own-the-why/?pk_campaign=feed&#038;pk_kwd=ai-writes-code-you-own-the-why">AI Writes Code. You Own the &#8216;Why.&#8217;</a></p>

<p>Mark Zuckerberg says <a href="https://www.linkedin.com/posts/bohuslav-%C5%A1imek-kambo_meta-ceo-mark-zuckerberg-recently-predicted-activity-7323233903211700226-LLyC">AI will write most of Meta’s code in the next 12–18 months</a>. If your first reaction is dread — congratulations, you’re a developer who already maintained code.</p>
<p>Because the problem isn’t writing code.</p>
<blockquote>
<p><strong>It’s understanding it. Maintaining it. Refactoring it two years later without breaking production on a Friday.</strong></p>
</blockquote>
<p>AI is getting scary-good at generating code. Not just autocompleting lines — we’re talking entire service layers, test suites, and infrastructure scripts. That feels like a superpower until you realize this superpower has no memory, no system knowledge, and no architectural intuition. Just vibes. &#8220;AI tools like GPT can help accelerate this process, but they are not the solution.&#8221; &#8211; <a href="https://suckup.de/2025/01/the-wild-west-of-coding-why-were-still-burning-digital-cities/">The Wild West of Coding: Why We’re Still Burning Digital Cities &#8211; SUCKUP.de</a></p>
<p>We’re now past the point of discussing whether AI can write useful code. It can. The question is what happens after it does.</p>
<p>And here’s the brutal truth:</p>
<blockquote>
<p><strong>AI knows how to write code. It has no idea why the code exists.</strong></p>
</blockquote>
<p>It doesn’t know about that performance fix from 2021. It doesn’t understand your team&#8217;s domain language. It doesn’t realize that “active” isn’t just a string — it’s a business-critical contract baked into legal compliance.</p>
<p>If we don’t separate <strong>generation</strong> from <strong>intent</strong>, we’re going to drown in beautifully structured, semantically useless garbage.</p>
<p>This post presents a two-part strategy:</p>
<ol>
<li>
<p>Define a blueprint format that captures the <em>what</em>.</p>
</li>
<li>
<p>Encode the <em>why</em> directly into your codebase.</p>
</li>
</ol>
<p>The goal isn’t to stop AI from writing code — it’s to make sure it only writes code that deserves to exist.</p>
<hr />
<h2><strong>Abstraction Got Us Here — But It’s Breaking</strong></h2>
<p>Every generation of developers inherits more power and more abstraction.<br />That power is only useful if we <strong>don’t forget how the system underneath works</strong>.</p>
<p>Let’s break it down:</p>
<p><img loading="lazy" decoding="async" data-attachment-id="7009" data-permalink="http://suckup.de/?attachment_id=7009" data-orig-file="http://suckup.de/wp-content/uploads//2025/05/Entwicklung-der-Programmierung-min.png" data-orig-size="1536,1024" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Entwicklung der Programmierung-min" data-image-description="" data-image-caption="" data-medium-file="http://suckup.de/wp-content/uploads//2025/05/Entwicklung-der-Programmierung-min-300x200.png" data-large-file="http://suckup.de/wp-content/uploads//2025/05/Entwicklung-der-Programmierung-min-1024x683.png" class="alignnone size-full wp-image-7009 aligncenter" src="http://suckup.de/wp-content/uploads//2025/05/Entwicklung-der-Programmierung-min.png" alt="" width="1536" height="1024" srcset="http://suckup.de/wp-content/uploads/2025/05/Entwicklung-der-Programmierung-min.png 1536w, http://suckup.de/wp-content/uploads/2025/05/Entwicklung-der-Programmierung-min-300x200.png 300w, http://suckup.de/wp-content/uploads/2025/05/Entwicklung-der-Programmierung-min-1024x683.png 1024w, http://suckup.de/wp-content/uploads/2025/05/Entwicklung-der-Programmierung-min-768x512.png 768w" sizes="auto, (max-width: 1536px) 100vw, 1536px" /></p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f1.png" alt="🧱" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Layer 0: Physical Switches &amp; Punch Cards</h3>
<p>Total control. No productivity. Every bit was your problem.</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Layer 1: Assembly</h3>
<p>Readable by machine and sad humans. Precision required. Errors fatal.</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f524.png" alt="🔤" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Layer 2: High-Level Languages (C, FORTRAN)</h3>
<p>You write logic; the compiler handles machine details. This was the first big win: abstraction that didn’t cost traceability.</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Layer 3: OOP and Dynamic Languages</h3>
<p>Java, Python, PHP, C#. We got encapsulation, interfaces, and tooling. We also got frameworks, side effects, and runtime mysteries.</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f52e.png" alt="🔮" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Layer 4: Frameworks, ORMs, DevTools</h3>
<p>Laravel, Doctrine, Spring, React, ESLint. Magic happened. And so did performance bugs, leaky abstractions, and ten-minute stack traces.</p>
<hr />
<p>Now?</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3b2.png" alt="🎲" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Layer 5: LLMs (Large Language Models)</h3>
<blockquote>
<p>A stochastic machine trained to <em>guess</em> what code probably looks like based on tokens, not truth.</p>
</blockquote>
<p>It’s autocomplete on steroids.<br />You say &#8220;Create a REST API for orders&#8221; — it gives you ten files and a <code>Repository</code> that “just works.”<br />Until it doesn’t.</p>
<p>Because here’s the core issue:</p>
<ul>
<li>
<p>It doesn’t understand your domain.</p>
</li>
<li>
<p>It doesn’t know your technical debt.</p>
</li>
<li>
<p>It doesn’t track business rules.</p>
</li>
<li>
<p>It doesn’t care about your security policies.</p>
</li>
</ul>
<p>And teams are merging this output like it’s a pull request from a trusted senior engineer.</p>
<p>Let me be clear:</p>
<blockquote>
<p><strong>LLMs are not teammates. They’re not compilers. They’re not even junior devs.</strong></p>
</blockquote>
<p>They’re trained to emit high-probability syntax. That’s it.</p>
<p>Yet we’re dropping their output straight into <code>main</code>, bypassing all the trust boundaries we spent decades learning to respect.</p>
<p>Remember the golden rule?</p>
<blockquote>
<p><strong>Don’t edit generated code.</strong></p>
</blockquote>
<p>We follow it for compilers, transpilers, ORMs, and IaC tools.<br />But when ChatGPT writes a controller? We treat it like gospel.</p>
<p>That’s technical debt in disguise. And it’s scaling faster than any abstraction layer before it.</p>
<hr />
<h2><strong>The Strategy – Separate the ‘Why’ from the ‘How’</strong></h2>
<p>Here’s the fundamental mismatch:</p>
<blockquote>
<p><strong>LLMs generate the <em>how</em>. But only humans can define the <em>why</em>.</strong></p>
</blockquote>
<p>Yet we’re letting the “how” flow freely into production without anchoring it to the business context, architectural rationale, or historical landmines it depends on.</p>
<p>This isn’t a tooling problem. It’s a systems thinking failure.</p>
<p>To fix it, we need to separate <strong>generation</strong> from <strong>intent</strong>, and introduce a strict boundary between code that is guessed and code that is trusted.</p>
<p>Here’s the strategy:</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f1.png" alt="🧱" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Part 1: Define a Compiler-Compatible Blueprint Format (Own the Intent)</h3>
<p>We don’t want AI writing raw PHP, Java, or Python.<br />We want it writing structured <strong>blueprints</strong> that describe behavior, constraints, and flow —<br />not implementation.</p>
<p>You then build a <strong>compiler</strong> that transforms these blueprints into safe, production-ready code using your stack, your rules, and your team’s architecture patterns.</p>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Blueprint Example (YAML – Compiler-Ready)</h4>
<pre><code class="language-yaml">function: getActiveUserEmail
description: Return email of an active user or fail with domain-level exceptions

inputs:
  - name: userId
    type: Domain.UserId

output:
  type: Domain.EmailAddress

rules:
  - businessRule: Only active users can access the system
  - security:
      concern: InfoDisclosure
      severity: High
      mitigation: Throw domain-specific exceptions
  - maintainability:
      smell: MagicString
      notes: Replace 'active' string with enum

steps:
  - fetch:
      from: UserRepository
      method: findById
      input: userId
      output: user
  - guard:
      if: user == null
      then: throw DomainError.UserNotFound
  - guard:
      if: user.status != ACTIVE
      then: throw DomainError.UserInactive
  - return:
      value: user.email
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Why This Works:</h4>
<ul>
<li>
<p><strong>Compiler-friendly</strong>: Each step maps cleanly to deterministic code generation.</p>
</li>
<li>
<p><strong>LLM-compatible</strong>: Easy for AI to generate and validate.</p>
</li>
<li>
<p><strong>Auditable</strong>: You can version this. You can diff it. You can reason about it.</p>
</li>
<li>
<p><strong>Stack-agnostic</strong>: One blueprint, many possible code outputs (Laravel, Symfony, NestJS, Spring).</p>
</li>
<li>
<p><strong>Intent-driven</strong>: You encode what needs to happen — and enforce how through rules.</p>
</li>
</ul>
<p>Your compiler becomes the enforcement layer:</p>
<ul>
<li>
<p>It checks the blueprint against your domain model.</p>
</li>
<li>
<p>It injects architecture-specific behavior (validation, DI, error handling).</p>
</li>
<li>
<p>It produces safe, maintainable, consistent code.</p>
</li>
</ul>
<p>Blueprints are your <strong>contract with the machine</strong>.<br />Your compiler is the <strong>gatekeeper</strong>.<br />LLMs are just assistants — they don’t write production code; they write proposals.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e9.png" alt="🧩" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Part 2: Embed the &#8216;Why&#8217; Directly Into Your Codebase (Own the Context)</h3>
<p>You don’t just need structure in generated code —<br />You need <strong>context</strong> in your existing code.</p>
<p>That’s where <strong>metadata</strong> comes in: structured, machine-readable, developer-accessible annotations that tell humans <em>and</em> LLMs why a piece of logic exists.</p>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Example (PHP Attributes)</h4>
<pre><code class="language-php">#[BusinessRule("Only active users may access features")]
#[Security(concern: "UnauthorizedAccess", severity: "Critical")]
#[Maintainability(smell: "MagicString", notes: "Replace 'active' with enum")]
public function getActiveUserEmail(UserId $userId): EmailAddress
{
    // ...
}
</code></pre>
<p>These attributes:</p>
<ul>
<li>
<p>Can be enforced in CI with static analysis (PHPStan, Psalm, custom Rector rules)</p>
</li>
<li>
<p>Provide structure for documentation generation</p>
</li>
<li>
<p>Are readable by future devs and future AI tools</p>
</li>
<li>
<p>Make implicit decisions <strong>explicit</strong></p>
</li>
</ul>
<p class="" data-start="130" data-end="236">Is this over-engineering?<br data-start="155" data-end="158" />Or is it the minimum bar if you expect maintainable AI-integrated systems?</p>
<p class="" data-start="243" data-end="488"><strong>Let’s be honest</strong>: if we’re still coding the same way five years from now — merging raw AI output without structure, rules, or traceability — it won’t be because it works.<br data-start="412" data-end="415" />It’ll be because we never had the discipline to build something better.</p>
<p> </p>


<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fai-writes-code-you-own-the-why%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dai-writes-code-you-own-the-why&amp;action_name=AI+Writes+Code.+You+Own+the+%26%238216%3BWhy.%26%238217%3B&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/05/ai-writes-code-you-own-the-why/?pk_campaign=feed&amp;pk_kwd=ai-writes-code-you-own-the-why/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7008</post-id>	</item>
		<item>
		<title>Why Codebases Rot Like Kitchens (and How to Stop It)</title>
		<link>http://suckup.de/2025/05/why-codebases-rot-like-kitchens-and-how-to-stop-it/?pk_campaign=feed&amp;pk_kwd=why-codebases-rot-like-kitchens-and-how-to-stop-it&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=why-codebases-rot-like-kitchens-and-how-to-stop-it</link>
					<comments>http://suckup.de/2025/05/why-codebases-rot-like-kitchens-and-how-to-stop-it/?pk_campaign=feed&amp;pk_kwd=why-codebases-rot-like-kitchens-and-how-to-stop-it#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Fri, 02 May 2025 02:09:47 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=7002</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/05/why-codebases-rot-like-kitchens-and-how-to-stop-it/?pk_campaign=feed&#038;pk_kwd=why-codebases-rot-like-kitchens-and-how-to-stop-it">Why Codebases Rot Like Kitchens (and How to Stop It)</a></p>
<p>🍳 Intro: Why the Knife in the Sink Matters A cluttered kitchen doesn’t happen all at once. It starts with one knife left in the sink. One jar not put back. A cutting board with a little oil on it. Nobody panics. Nothing’s “broken.” But over the next few hours—or days—something shifts. You can’t find &#8230; <a href="http://suckup.de/2025/05/why-codebases-rot-like-kitchens-and-how-to-stop-it/?pk_campaign=feed&#038;pk_kwd=why-codebases-rot-like-kitchens-and-how-to-stop-it" class="more-link">Continue reading <span class="screen-reader-text">Why Codebases Rot Like Kitchens (and How to Stop It)</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fwhy-codebases-rot-like-kitchens-and-how-to-stop-it%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhy-codebases-rot-like-kitchens-and-how-to-stop-it&amp;action_name=Why+Codebases+Rot+Like+Kitchens+%28and+How+to+Stop+It%29&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/05/why-codebases-rot-like-kitchens-and-how-to-stop-it/?pk_campaign=feed&#038;pk_kwd=why-codebases-rot-like-kitchens-and-how-to-stop-it">Why Codebases Rot Like Kitchens (and How to Stop It)</a></p>

<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f373.png" alt="🍳" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Intro: Why the Knife in the Sink Matters</h3>
<p>A cluttered kitchen doesn’t happen all at once.</p>
<p>It starts with one knife left in the sink. One jar not put back. A cutting board with a little oil on it. Nobody panics. Nothing’s “broken.”</p>
<p>But over the next few hours—or days—something shifts.</p>
<p>You can’t find the clean spatula. The counter is sticky.<br />Cooking becomes frustrating.</p>
<p>And the worst part? You don’t notice the mess until it’s already changed how you behave.</p>
<ul>
<li>You stop wiping.</li>
<li>You stop putting things back.</li>
<li>You start contributing to the chaos.</li>
</ul>
<p>That’s the hidden cost of inconsistency: it doesn’t just create disorder.<br />It <strong>lowers the standard of care</strong>—until disorder becomes the default.</p>
<p>Codebases rot the same way.</p>
<ul>
<li>It’s rarely one big refactor gone wrong or some infamous PR.</li>
<li>It’s a hardcoded string here, a missing test there.</li>
<li>A “temporary” workaround that never gets revisited.</li>
<li>A helper class that quietly becomes a dumping ground.</li>
</ul>
<p>CI is green. Static analysis doesn’t complain.<br />But somehow, everything feels heavier than it used to.</p>
<p>This post is about that slow drift—and how to stop it.</p>
<p>Not with heroic rewrites. Not with prettier configs or PSR-12 debates.<br />But with a deeper understanding of what consistency really is, why it <strong>matters more than perfection</strong>, and how to build codebases that clean themselves—file by file, day by day.</p>
<p>Because the same principle that keeps kitchens functional over time applies to software:</p>
<blockquote>
<p>Mess invites mess.<br />But more powerfully: <strong>order invites more order</strong>.</p>
</blockquote>
<p>When everything has a place, it tends to stay in place.</p>
<hr />
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f944.png" alt="🥄" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 1. Mess Invites Mess, But Order Invites More Order</h2>
<p>Leave a knife in the sink, and somehow it gives everyone else permission.<br />A spoon shows up. Then a pan.<br />And by the end of the day, no one wants to clean—because now it’s a mess.</p>
<p>But if the counter is clear, the sink is empty, and everything’s where it belongs?<br />People wipe up right after chopping.<br />They put the spices back without being asked.</p>
<p>The <strong>environment sets the standard</strong>.<br />Not rules. Not motivation. Just what’s already true.</p>
<p>Code works the same way.</p>
<p>You open a file where everything is named clearly, small functions are composed intentionally, and the layout flows like it was built on rails—what do you do?<br />You match the tone. You respect the structure. You add with care.</p>
<p>But if you open a file that’s messy—unstructured, inconsistent, unpredictable—you patch it with a workaround. Or worse, you walk away.<br />Not because you&#8217;re lazy, but because the code is <strong>already signaling</strong> that quality isn’t expected here.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Consistency Sets the Behavioral Baseline</h3>
<p>Mess doesn’t just grow because things break.<br />Mess grows because people adapt downward.</p>
<p>Even a “minor” inconsistency can cause disproportionate damage:</p>
<ul>
<li>
<p>A misnamed method signals that naming isn’t important.</p>
</li>
<li>
<p>A missing test tells new devs testing is optional.</p>
</li>
<li>
<p>One file ignoring the service structure invites others to do the same.</p>
</li>
</ul>
<p>It’s not about <strong>enforcement</strong>.<br />It’s about <strong>momentum</strong>.</p>
<p>A consistent codebase isn’t perfect—it’s <strong>predictable</strong>.<br />And predictability reduces friction for every contributor.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Real-World Parallel: The Clean Kitchen Effect</h3>
<p>Behavioral psychology has a name for this: <strong>environmental priming</strong>.<br />People unconsciously mirror the standards around them.</p>
<p>In one study, a clean hallway with lemon-scented cleaner in the air made people more likely to pick up litter.<br />In another, visible disorder led to higher rates of dishonesty and vandalism.</p>
<p>Why?<br />Because humans tune their behavior to what seems “normal.”<br />And <strong>codebases are no different</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> In Practice</h3>
<p>In well-maintained projects:</p>
<ul>
<li>
<p>New contributors write better code without being told.</p>
</li>
<li>
<p>Code reviews focus on logic, not formatting or structure.</p>
</li>
<li>
<p>Team velocity increases—not because of speed, but because of reduced friction.</p>
</li>
</ul>
<p>In messy ones:</p>
<ul>
<li>
<p>People hesitate to touch files.</p>
</li>
<li>
<p>Reviews become emotional minefields.</p>
</li>
<li>
<p>Every fix feels like pushing through mud.</p>
</li>
</ul>
<p>So if you want better code without preaching or micromanaging?</p>
<p>Don’t write a new rule.<br />Write one clean, consistent file. And make it the new normal.</p>
<blockquote>
<p>That’s how kitchens stay clean.<br />That’s how codebases stay maintainable.</p>
</blockquote>
<hr />
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 2. Clean ≠ Structured. Structure = Predictable.</h2>
<p>From a distance, the kitchen looks fine.<br />Counters wiped. No visible clutter. The sink is empty.</p>
<p>But then you open a drawer and find three different can openers.<br />The fridge is overstuffed with expired ingredients.<br />The spice rack is alphabetical—except for the one jar you need.</p>
<p>It’s not dirty. But it’s disorganized. And suddenly, something as simple as boiling pasta feels… harder than it should.</p>
<p>Codebases can fool you the same way.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9fc.png" alt="🧼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Visual Cleanliness Hides Structural Rot</h3>
<p>Developers often confuse <strong>style consistency</strong> with <strong>structural integrity</strong>.</p>
<p>“We’re following PSR-12—we’re good.”</p>
<p>But the real friction doesn’t come from indentation.<br />It comes from <strong>behavioral inconsistency</strong>:</p>
<ul>
<li>
<p>A function mutates state but reads like it doesn’t.</p>
</li>
<li>
<p>A service mixes validation and persistence in the same method.</p>
</li>
<li>
<p>Ten files named <code>Helper.php</code> doing wildly different things.</p>
</li>
</ul>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Structure Creates Trust</h3>
<p>When structure is consistent:</p>
<ul>
<li>
<p>You can guess functionality from a filename.</p>
</li>
<li>
<p>You know where to add logic without asking.</p>
</li>
<li>
<p>You focus on <strong>what</strong> needs to change—not <strong>how</strong> to fit it in.</p>
</li>
</ul>
<p>When structure is inconsistent:</p>
<ul>
<li>
<p>Every file becomes an investigation.</p>
</li>
<li>
<p>Every change feels like a guess.</p>
</li>
<li>
<p>Every review becomes a negotiation.</p>
</li>
</ul>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Cognitive Load Theory: Death by Paper Cuts</h3>
<p>Humans can only juggle <strong>4–7 items</strong> in working memory at a time.</p>
<p>Every inconsistency:</p>
<ul>
<li>
<p>Forces a context switch.</p>
</li>
<li>
<p>Introduces a new mental rule.</p>
</li>
<li>
<p>Steals attention from the actual problem.</p>
</li>
</ul>
<p>Even if you never say it out loud, your brain reacts:</p>
<p>“Wait… how does this one work again?”</p>
<p>That hesitation is the real tax on team velocity.</p>
<p>Not slow builds.<br />Not flaky tests.<br />Just devs wasting brainpower <strong>navigating inconsistency</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f373.png" alt="🍳" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Back to the Kitchen</h3>
<p>Imagine:</p>
<ul>
<li>
<p>Every time you cook, you spend 3 minutes looking for a pan.</p>
</li>
<li>
<p>You burn dishes because spices are mislabeled.</p>
</li>
<li>
<p>You break a plate trying to cram it into the wrong cabinet.</p>
</li>
</ul>
<p>Eventually, nobody wants to cook.<br />Not because they can’t.<br />But because <strong>the system stopped helping</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> In Practice</h3>
<p>Here’s what actually helps:</p>
<ul>
<li>
<p>Stop obsessing over formatting. Start enforcing structure.</p>
</li>
<li>
<p>Codify naming rules, error-handling patterns, return type expectations.</p>
</li>
<li>
<p>Maintain <strong>one golden file</strong> per feature type—let code teach code.</p>
</li>
<li>
<p>Use tools like Rector and PHPStan not just for correctness, but for <strong>design drift</strong>.</p>
</li>
</ul>
<p>Anyone can clean a file.<br />But only structure makes it stay clean the next day.</p>
<blockquote>
<p>Structured systems aren’t pretty.<br />They’re <strong>repeatable</strong>.</p>
</blockquote>
<hr />
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f501.png" alt="🔁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 3. Consistency as Workflow, Not Willpower</h2>
<p>Nobody wants to scrub a greasy pan.<br />But wiping the counter after slicing onions? Easy.<br />Tossing a sponge in the dishwasher? Automatic.<br />Taking out the trash because the bin is <em>right there</em>? Obvious.</p>
<p><strong>Clean kitchens stay clean not alone through motivation—<br />but through systems that make the right action frictionless.</strong></p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f916.png" alt="🤖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Stop Relying on Memory and Good Intentions</h3>
<p>Developers love to say:</p>
<blockquote>
<p>“Always write tests.”<br />“Stick to the architecture.”<br />“No more fat controllers.”</p>
</blockquote>
<p>And for a week, it works.<br />Until someone’s tired.<br />Or new.<br />Or didn’t know the rule existed.</p>
<p>Then entropy wins—because you bet the house on <strong>willpower</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f502.png" alt="🔂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Ritual Beats Resolution</h3>
<p>The teams that stay consistent aren’t more disciplined.<br />They’ve just made <strong>quality the path of least resistance</strong>.</p>
<p>They don’t debate style in every PR.<br />They don’t forget to test.<br />They don’t wonder where a new file belongs.</p>
<p>Why?</p>
<p>Because the <strong>workflow remembers for them</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Make Quality Automatic</h3>
<p>Good teams embed consistency into the process:</p>
<ul>
<li>
<p><strong>Pre-commit hooks</strong></p>
<blockquote>
<p>No format, no type safety, no commit. End of story.</p>
</blockquote>
</li>
<li>
<p><strong>CI pipelines that validate behavior, not just syntax</strong></p>
<ul>
<li>
<p>Static analysis checks</p>
</li>
<li>
<p>Mutation coverage checks</p>
</li>
<li>
<p>Architectural boundaries checks</p>
</li>
<li>
<p>Naming conventions, return types, dead code checks</p>
</li>
</ul>
</li>
<li>
<p><strong>Code generators and file stubs</strong></p>
<blockquote>
<p>Create a new controller? It already has the right layout.</p>
</blockquote>
</li>
<li>
<p><strong>“Golden” examples in-repo</strong></p>
<blockquote>
<p>Skip the 12-page style guide. Copy the cleanest module.</p>
</blockquote>
</li>
<li>
<p><strong>Micro-rituals in code review</strong></p>
<ul>
<li>
<p>PR checklist: “Did we leave this better than we found it?”</p>
</li>
<li>
<p>Review warm-ups: “What&#8217;s the pattern here?”</p>
</li>
</ul>
</li>
</ul>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f342.png" alt="🍂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> The Kitchen Analogy Again</h3>
<p>Want people to compost?<br />Don’t hide the bin in a closet.<br />Put a small, open one <strong>next to the cutting board</strong>.</p>
<p>Same principle in code:</p>
<blockquote>
<p>If you want consistency, design the <strong>workflow</strong><br />so that the right choice is the easiest one.</p>
</blockquote>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> In Practice</h3>
<p>Ask your team:</p>
<ul>
<li>
<p>What do we correct in every PR?</p>
</li>
<li>
<p>What decisions keep getting re-explained?</p>
</li>
<li>
<p>What slows us down the most often?</p>
</li>
</ul>
<p>Then <strong>build automation or scaffolding</strong> to solve <em>just that</em>.<br />Start with friction hotspots.</p>
<p>You’re not building bureaucracy.<br />You’re removing ambiguity.</p>
<blockquote>
<p>Every time the system answers a question,<br />that’s one less decision the developer has to make.</p>
</blockquote>
<hr />
<p>Consistency doesn’t come from preaching.<br />It comes from design.</p>
<p><strong>Design your workflow to default to quality.</strong><br />Then watch the team rise to meet it.</p>
<hr />
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3d7.png" alt="🏗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 4. Design for the Future, Not the Fix</h2>
<p>There’s a kitchen that looks spotless—today.<br />But the trash can is too far from the prep station.<br />The knives are in the same drawer as the ladles.<br />There’s no counter near the stove.</p>
<p>Cooking technically works.<br />But every step is awkward. Every movement inefficient.<br />Eventually, people stop using it—not because it’s messy, but because it’s <strong>exhausting</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f1.png" alt="🧱" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Codebases Rot the Same Way</h3>
<p>They don’t collapse from mess.<br />They degrade from <strong>accumulated friction</strong>:</p>
<ul>
<li>
<p>Logic split between controller, service, and a random helper.</p>
</li>
<li>
<p>Naming that hides purpose (<code>ServiceHandler</code>, <code>ThingManager</code>).</p>
</li>
<li>
<p>Features wedged into whatever file felt “close enough.”</p>
</li>
</ul>
<p>You can still add features.<br />You can still ship.</p>
<p>But every change feels like surgery—because <strong>the architecture doesn’t support the work</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4d0.png" alt="📐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Good Architecture Is Predictable</h3>
<p>A good system isn’t one where code just works.<br />It’s one where <strong>new code fits</strong>.</p>
<p>If you can’t tell where the next feature goes,<br />you don’t have architecture—you have coincidence.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Architecture = Consistency at Scale</h3>
<p>At the local level, consistency is about naming and formatting.<br />At the system level, it’s about <strong>boundaries and repeatability</strong>:</p>
<ul>
<li>
<p>Controllers control. Services do business logic. </p>
</li>
<li>
<p>Every feature follows the same shape.</p>
</li>
<li>
<p>Domain logic lives with the domain—not scattered across folders.</p>
</li>
<li>
<p>Folder structure maps to business concerns, not technical artifacts.</p>
</li>
</ul>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> What This Looks Like in Practice</h3>
<ul>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e9.png" alt="🧩" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Folders map to domains, not tech types</strong></p>
<ul>
<li>
<p><code>Billing/Invoices/MarkAsPaid.php</code></p>
</li>
<li>
<p>Not <code>Services/InvoiceService.php</code></p>
</li>
</ul>
</li>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f1.png" alt="🧱" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Vertical slices over horizontal layers</strong></p>
<ul>
<li>
<p>Group by feature, not file type.</p>
</li>
</ul>
</li>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Structure reveals design decisions</strong></p>
<ul>
<li>
<p>Your DDD shouldn’t live in a Confluence page.</p>
</li>
</ul>
</li>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>No catch-all files</strong></p>
<ul>
<li>
<p>If you have <code>Helper.php</code>, you’ve already lost the thread.</p>
</li>
</ul>
</li>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f501.png" alt="🔁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>One way to do a thing</strong></p>
<ul>
<li>
<p>Commands look like commands. Events look like events.</p>
</li>
<li>
<p>Failures throw exceptions. No silent <code>null</code>.</p>
</li>
</ul>
</li>
</ul>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f32a.png" alt="🌪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Most Systems Drift by Default</h3>
<p>Architecture rarely dies from bad decisions.<br />It dies from <strong>unopposed ones</strong>:</p>
<ul>
<li>
<p>A shortcut nobody reverts.</p>
</li>
<li>
<p>A pattern nobody questions.</p>
</li>
<li>
<p>A new dev copying a bad file because “that’s how it was done.”</p>
</li>
</ul>
<p>If nothing enforces the rules, there <em>are</em> no rules.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f510.png" alt="🔐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Architecture Is Operational Psychology</h3>
<p>It should tell your team:</p>
<ul>
<li>
<p>Where things go</p>
</li>
<li>
<p>What “right” looks like</p>
</li>
<li>
<p>How to move safely and fast</p>
</li>
</ul>
<p>If it doesn’t, your devs will guess.<br />And every guess will pull your system further apart.</p>
<hr />
<blockquote>
<p>Design not for what’s urgent.<br />Design for what’s needed.</p>
</blockquote>
<p>Make your architecture answer questions before they’re asked.<br />Make it obvious where new work belongs.</p>
<p>If you don’t, the next “fix” will be a wedge.<br />And ten wedges later, you’re back in kitchen hell.</p>
<hr />
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f54a.png" alt="🕊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 5. Consistency Isn’t Control. It’s Clarity.</h2>
<blockquote>
<p>“Don’t tell me how to code.”</p>
</blockquote>
<p>We’ve all heard it.<br />Some of us have said it.</p>
<p>Because too often, consistency feels like <strong>micromanagement</strong>—<br />Like senior devs enforcing their quirks instead of team standards.</p>
<p>But that’s the wrong frame.</p>
<p>Real consistency isn’t about control.<br />It’s about <strong>removing guesswork</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ed.png" alt="🧭" class="wp-smiley" style="height: 1em; max-height: 1em;" /> The Right Kind of Freedom</h3>
<p>In a well-designed kitchen:</p>
<ul>
<li>
<p>You don’t need to ask where the knife goes.</p>
</li>
<li>
<p>You don’t need a manual to find the trash.</p>
</li>
<li>
<p>You just move—freely, fluidly, confidently.</p>
</li>
</ul>
<p>That’s not restriction. That’s <strong>clarity</strong>.</p>
<p>And clarity is what brings developers into a productive flow.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Predictability = Velocity</h3>
<p>When a developer opens a new module and can instantly tell:</p>
<ul>
<li>
<p>Where logic lives</p>
</li>
<li>
<p>How errors are handled</p>
</li>
<li>
<p>What a test should look like</p>
</li>
</ul>
<p>They’re not slowed down.<br />They’re <strong>unlocked</strong>.</p>
<p>No waiting on context.<br />No decoding inconsistent patterns.</p>
<p>Just building, fast—and safely.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> What Consistency Really Gives You</h3>
<ul>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Clarity</strong> → Fewer decisions, fewer mistakes</p>
</li>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Momentum</strong> → No mental pauses to decipher structure</p>
</li>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Autonomy</strong> → New devs can own changes without fear</p>
</li>
<li>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f91d.png" alt="🤝" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Trust</strong> → Reviews shift from “What is this?” to “How well does it solve the problem?”</p>
</li>
</ul>
<p>This isn’t about obedience.<br />It’s about <strong>shared expectations</strong>.</p>
<p>The structure does the explaining.<br />The docs just reinforce the why.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e8.png" alt="🧨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> The Wrong Kind of Freedom Slows Teams Down</h3>
<p>“Just do what you think is best” sounds supportive.<br />But it opens the door to chaos:</p>
<ul>
<li>
<p>Someone rewrites a module in a new paradigm.</p>
</li>
<li>
<p>Another adds raw SQL into a system using Doctrine.</p>
</li>
<li>
<p>A test is written in a completely different pattern.</p>
</li>
</ul>
<p>Now everyone is “free”—and everyone is <strong>misaligned</strong>.</p>
<p>Velocity drops.<br />Reviews turn into rework.<br />Nobody trusts anything.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Teams Scale on Predictability, Not Talent</h3>
<p>The best teams aren’t made of superstars.<br />They’re made of <strong>people who can move independently and still produce code that fits together</strong>.</p>
<p>That only works when the system defines consistency <strong>as clarity</strong>, not constraint.</p>
<hr />
<blockquote>
<p>Clarity makes creativity possible.<br />Predictability enables flow.<br />Shared structure builds trust.</p>
</blockquote>
<p>That’s what real consistency gives you.</p>
<p>Not control—<strong>coherence</strong>.</p>
<hr />
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f9.png" alt="🧹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Conclusion – Make Order the Default</h2>
<p>Kitchens don’t stay clean because someone yells.<br />They stay clean because the <strong>system makes care easy</strong>:</p>
<ul>
<li>
<p>The trash is close.</p>
</li>
<li>
<p>The knives are where you expect.</p>
</li>
<li>
<p>The dishwasher has a rhythm.</p>
</li>
</ul>
<p>No micromanagement.<br />No friction.<br />Just <strong>design that encourages discipline</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9d1-200d-1f4bb.png" alt="🧑‍💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Codebases Work the Same Way</h3>
<p>You don’t need perfect code.<br />You need a foundation that:</p>
<ul>
<li>
<p>Makes the right thing obvious</p>
</li>
<li>
<p>Makes the wrong thing feel weird</p>
</li>
<li>
<p>Makes improvement the <strong>path of least resistance</strong></p>
</li>
</ul>
<blockquote>
<p>Mess invites mess.<br />But more importantly: <strong>order invites order</strong>.</p>
</blockquote>
<p>When that order exists:</p>
<ul>
<li>
<p>Developers contribute with confidence</p>
</li>
<li>
<p>Refactors happen in flow</p>
</li>
<li>
<p>New features <strong>fit in</strong> like they belonged from day one</p>
</li>
</ul>
<p>Not because your team is better.<br />But because your <strong>system is smarter</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> What You Can Do Today</h3>
<p> </p>
<blockquote>
<p><strong>Start small. But start with purpose.</strong></p>
</blockquote>
<ul>
<li>
<p>Touch a file? Leave it cleaner than you found it.</p>
</li>
<li>
<p>Write a new service? Copy the <strong>best one</strong>—your template of excellence—not the most recent hack.</p>
</li>
<li>
<p>Add a pre-commit hook that blocks <strong>architectural drift</strong>, not just formatting violations.</p>
</li>
<li>
<p>Pick one “golden” module. Let it define what “done right” looks like.</p>
</li>
</ul>
<p>Then build forward from that standard—<strong>consistently</strong>.</p>
<ul>
<li>
<p>Turn your golden module into a scaffold.</p>
</li>
<li>
<p>Generate code that already follows the rules.</p>
</li>
<li>
<p>Automate structure, not just syntax.</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="language-bash">make create:datatable InvoiceTable
</code></pre>
<p>Now every new DataTable starts clean, typed, and consistent—before anyone touches a line.</p>
<blockquote>
<p>That’s how you scale quality.<br />Not by working harder. But by <strong>making the right thing the easiest thing</strong>.</p>
</blockquote>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fwhy-codebases-rot-like-kitchens-and-how-to-stop-it%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhy-codebases-rot-like-kitchens-and-how-to-stop-it&amp;action_name=Why+Codebases+Rot+Like+Kitchens+%28and+How+to+Stop+It%29&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/05/why-codebases-rot-like-kitchens-and-how-to-stop-it/?pk_campaign=feed&amp;pk_kwd=why-codebases-rot-like-kitchens-and-how-to-stop-it/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7002</post-id>	</item>
		<item>
		<title>The Inner Code Plumber</title>
		<link>http://suckup.de/2025/05/the-inner-code-plumber/?pk_campaign=feed&amp;pk_kwd=the-inner-code-plumber&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=the-inner-code-plumber</link>
					<comments>http://suckup.de/2025/05/the-inner-code-plumber/?pk_campaign=feed&amp;pk_kwd=the-inner-code-plumber#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Thu, 01 May 2025 12:55:54 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6993</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/05/the-inner-code-plumber/?pk_campaign=feed&#038;pk_kwd=the-inner-code-plumber">The Inner Code Plumber</a></p>
<p>How Adaptive Systemic Intuition Lets You See Maintainability Before It Breaks You open a PHP file. No red flags. No screaming errors. The CI was green. Static analysis reports nothing, “all good.” But something feels off. -> And there it is—that tight feeling in your gut. Not panic. Not certainty. Just a whisper: “This will &#8230; <a href="http://suckup.de/2025/05/the-inner-code-plumber/?pk_campaign=feed&#038;pk_kwd=the-inner-code-plumber" class="more-link">Continue reading <span class="screen-reader-text">The Inner Code Plumber</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fthe-inner-code-plumber%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dthe-inner-code-plumber&amp;action_name=The+Inner+Code+Plumber&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/05/the-inner-code-plumber/?pk_campaign=feed&#038;pk_kwd=the-inner-code-plumber">The Inner Code Plumber</a></p>

<blockquote>How Adaptive Systemic Intuition Lets You See Maintainability Before It Breaks</blockquote>



<p>You open a PHP file. No red flags. No screaming errors. The CI was green. Static analysis reports nothing, “all good.” But something feels off.</p>



<ul class="wp-block-list">
<li>The methods are over-explained and under-meaningful.</li>
</ul>



<ul class="wp-block-list">
<li>The logic is layered like geological sediment.</li>
</ul>



<ul class="wp-block-list">
<li>The file smells like tech debt, even if the tools won’t say so.</li>
</ul>



<p>-> And there it is—that tight feeling in your gut.</p>



<p>Not panic. Not certainty. Just a whisper: “This will come back to bite us.”</p>



<p>That feeling isn’t mysticism. It’s not arrogance. It’s not just your “senior dev sixth sense.”</p>



<p>It’s something deeper—something more universal. Your experience is surfacing as Adaptive Systemic Intuition.</p>



<p>Just like a seasoned plumber can walk into a building and know, from the creaks and bends of the pipes, that trouble’s coming—even if everything flows for now—your brain is surfacing thousands of hours of coding, debugging, and review into a silent warning.</p>



<p>This post isn’t about patterns like SOLID or DRY.</p>



<ul class="wp-block-list">
<li>The pattern behind those coding patterns.</li>
</ul>



<ul class="wp-block-list">
<li>The one you feel before you can explain.</li>
</ul>



<ul class="wp-block-list">
<li>The one that lets you see maintainability before a single bug is reported.</li>
</ul>



<ul class="wp-block-list">
<li>This is the abstract pattern. And it lives in you.</li>
</ul>



<p>-> Let’s dig it up, name it, and sharpen it.</p>



<h2 class="wp-block-heading">1. Code Through the Lens of &#8220;Why,&#8221; Not Just &#8220;How&#8221;</h2>



<p>Fresh developers obsess over how.</p>



<ul class="wp-block-list">
<li>How to write the syntax.</li>
</ul>



<ul class="wp-block-list">
<li>How to pass the test.</li>
</ul>



<ul class="wp-block-list">
<li>How to make the thing work.</li>
</ul>



<p>But experienced developers? They ask why.</p>



<ul class="wp-block-list">
<li>Why does this code exist?</li>
</ul>



<ul class="wp-block-list">
<li>Why is it structured this way?</li>
</ul>



<ul class="wp-block-list">
<li>Why are we solving this problem now, and what will it look like later?</li>
</ul>



<p>It’s not about getting the function done. It’s about aligning the code with the context: the business goal, the system constraints, the team’s skill level, the organizational habits.</p>



<p>You’re not coding in a vacuum. You’re coding in an ecosystem.</p>



<p><strong>Plumber Thinking:</strong></p>



<p>You&#8217;ve already internalized this. In your code, structure reflects purpose.</p>



<p>When you clean up legacy code, you don’t just rewrite—you reflect: “What problem was this solving? Why this shape? Is that still true?”</p>



<p><strong>Plumber Analogy:</strong></p>



<p>A rookie plumber checks if the showerhead is clogged.</p>



<p>A seasoned plumber asks: “Is this the only tap with low pressure? What changed recently?”</p>



<p>Same situation—completely different insight.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;Simplicity in code isn&#8217;t about writing fewer lines; it&#8217;s about writing the clearest lines for the specific problem and its environment.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>Ask yourself: Why does this feature even exist?</li>



<li>Review code with this lens: Does this structure still match its purpose?</li>



<li>Refactor not because you can, but because the current shape no longer serves the system’s real needs.</li>
</ul>



<h2 class="wp-block-heading">2. Feel the Friction: Your Body Knows Bad Code</h2>



<p>You open a file.</p>



<p>Before reading a single line in detail—before reasoning, parsing, or even naming—the discomfort creeps in.</p>



<p>A sense of tension. A raised brow. A shift in posture.</p>



<p>You don’t have the error, but your body already knows: something&#8217;s off.</p>



<p>This isn’t new-age nonsense. It’s embodied cognition. Your thinking isn’t just in your head—it’s in your body.</p>



<ul class="wp-block-list">
<li>You gesture when explaining bugs.</li>
</ul>



<ul class="wp-block-list">
<li>You pace when searching for the right name.</li>
</ul>



<ul class="wp-block-list">
<li>You draw to reason through architecture.</li>
</ul>



<p>-> These aren’t quirks. They’re your body reasoning.</p>



<p><strong>Plumber Thinking:</strong></p>



<ul class="wp-block-list">
<li>You already use this intuitively.</li>
</ul>



<ul class="wp-block-list">
<li>You whiteboard before writing complex logic.</li>
</ul>



<ul class="wp-block-list">
<li>You pause when nested logic feels brittle—even before tests fail.</li>
</ul>



<ul class="wp-block-list">
<li>You’ve said it yourself: naming, structure, nesting—all send physical signals.</li>
</ul>



<p>-> Your gut? It’s hardware-accelerated static analysis.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>A good plumber doesn’t just look—they listen for vibration, feel for pressure, sense the strain in old joints.</p>



<p>Code is no different. You don’t just read it—you sense it.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;Often, the feeling that something is wrong precedes the logical explanation. Your body, tuned to patterns, senses dissonance before your mind catches up.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>Pay attention to physical signals: tight chest, hesitancy, frustration—these are pattern alerts.</li>



<li>If you can&#8217;t name the problem yet, don’t dismiss the feeling. Pause. Map it.</li>



<li>Sketch data flows before implementation. Where the drawing becomes messy, the code will too.</li>
</ul>



<h2 class="wp-block-heading">3. Debug in Your Head: Your Brain’s the Best Tool</h2>



<p>A bug shows up.</p>



<p>The junior instinct? Jump into the code. Drop in var_dump(), sprinkle logs like confetti, stare at traces.</p>



<p>The senior instinct?</p>



<p>Pause; Think; Mentally simulate;</p>



<p>They don’t open the IDE immediately—they open the model in their mind.</p>



<p>They replay the logic, walk the data, test their assumptions internally.</p>



<p>This isn’t laziness—it’s efficiency.</p>



<p>Debugging is about reconciling expectation vs. reality. Tools help, but mental simulation is where the real gap is closed.</p>



<p><strong></strong><strong>Plumber Thinking</strong>:</p>



<p>You don’t guess. You model.</p>



<p>When something breaks, your instinct isn’t to “try stuff”—it’s to ask: What’s the underlying assumption here?</p>



<p>You’ve trained yourself to see the root cause, not just the symptom.</p>



<p>You even help others find it by making them talk through their own code logic—a classic senior move.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>A customer says, “No hot water.”</p>



<p>The amateur checks the heater.</p>



<p>The master plumber?<br />“Does it happen with every tap?”<br />“When did this start?”<br />“Was there plumbing work recently?”<br />They construct a systemic model before touching a single tool.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;Every bug is a surprise—an error in your mental model. Fixing code is easy. Fixing the model? That’s where real debugging lives.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>When a bug appears, narrate what you expect should happen.</li>



<li>Walk the logic mentally before altering anything.</li>



<li>Ask others: “What do you think is happening, step by step?” Make the model visible.</li>
</ul>



<h2 class="wp-block-heading">4. Expect the Expected: Your Brain Predicts Code</h2>



<p>As you gain experience, something strange happens:</p>



<p>You start expecting code to behave a certain way—even before reading the details.</p>



<p>You see a method named getUserToken(), and your brain assumes:</p>



<ul class="wp-block-list">
<li>No side effects</li>



<li>Probably returns a string</li>



<li>Definitely doesn’t mutate state</li>
</ul>



<p>If it does mutate state or throw an exception—it feels wrong.</p>



<p>That feeling? It’s not being picky. It’s your brain’s predictive model raising a flag.</p>



<p>Your mind isn’t just parsing—it&#8217;s forecasting.</p>



<p>When the code breaks that forecast, your cognitive system yells: Prediction error detected.</p>



<p class="" data-start="122" data-end="230">Keep in mind how developers actually <em data-start="213" data-end="222">process</em> code:</p>
<ul data-start="231" data-end="442">
<li class="" data-start="231" data-end="296">
<p class="" data-start="233" data-end="296">Our <strong data-start="237" data-end="264">working memory is small</strong> and gets overwhelmed quickly.</p>
</li>
<li class="" data-start="297" data-end="442">
<p class="" data-start="299" data-end="442">Our <strong data-start="303" data-end="323">long-term memory</strong> excels at recognizing <strong data-start="346" data-end="381">well-named, consistent patterns</strong>—especially when they match previously learned mental models.</p>
</li>
</ul>
<p class="" data-start="444" data-end="799">That’s why <code data-start="455" data-end="492">fetchByNameOrThrowException(): User</code> and <code data-start="497" data-end="527">fetchByNameIfExists(): ?User</code> are vastly superior to <code data-start="551" data-end="573">fetchByName(): ?User</code>. They encode <em data-start="587" data-end="595">intent</em> directly into the name and return type. This isn’t nitpicking—it’s cognitive ergonomics. When naming clearly expresses behavior, you reduce cognitive load, prevent misreads, and accelerate understanding.</p>
<table>
<thead>
<tr>
<th><strong>Memory Type</strong></th>
<th><strong>Computer Analogy</strong></th>
<th><strong>Developer Brain Function</strong></th>
<th><strong>Coding Example</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Working Memory (WM)</strong></td>
<td>RAM / CPU Cache (Small, Fast, Volatile)</td>
<td>Active space for reasoning: tracking variables, current scope, flow. Limited (~4–7 chunks), disrupted easily.</td>
<td>Debugging a loop: <code>i = 0</code>, <code>item = user[0]</code>, tracking <code>state = processing</code>. Holding these while stepping through.</td>
</tr>
<tr>
<td><strong>Long-Term Memory (LTM)</strong></td>
<td>Hard Drive / Database (Vast, Fast-Indexed when chunked)</td>
<td>Stores learned patterns, idioms, APIs, naming conventions. Fast if knowledge is chunked (schema). Used for prediction.</td>
<td>Recognizing <code>getUserToken()</code> as: no side effects, returns string. Instantly guessing method purpose &amp; contract.</td>
</tr>
<tr>
<td><strong>Procedural Memory</strong></td>
<td>BIOS / Firmware / Muscle Memory</td>
<td>Automates repeatable behavior. IDE navigation, CLI fluency, common patterns. Invisible but critical for flow state.</td>
<td>Typing <code>function __construct(</code> without thinking. Instinctively spotting and refactoring a code smell.</td>
</tr>
</tbody>
</table>



<p><strong></strong><strong>Plumber Thinking</strong>:</p>



<p>You’ve written consistently predictable code for years—typed, immutable, clean.</p>



<p>You’ve trained your brain to recognize rhythm, detect side effects, and enforce mental contracts.</p>



<p>You’ve said it yourself: “Naming, types, structure—they’re not just syntax, they’re signals.”</p>



<p>And when that signal’s broken? You feel it immediately—even if the CI doesn’t.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>A plumber sees a pipe coupling that’s slightly misaligned.</p>



<p>No leak—yet. But something about the tension, the angle, the material… they know.</p>



<p>“That’s going to burst under pressure.”</p>



<p>Their prediction engine fires before failure.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>“Well-written code teaches your brain what to expect. Violating those expectations isn’t clever—it’s cognitive sabotage.”</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>When writing code, ask: What would another dev reasonably expect this to do?</li>



<li>When reviewing code, note every “surprise.” Why was it surprising?</li>



<li>Before running a method, predict: What will it return? What will it change? Then verify.</li>
</ul>



<h2 class="wp-block-heading">5. See the Shape: Visual Cues in Code</h2>



<p>Before your eyes process names or logic, they notice shape. I already wrote a blog post about it 5 years ago: <a href="https://suckup.de/2020/01/do-not-fear-the-white-space-in-your-code/">Do Not Fear The White Space in your Code &#8211; SUCKUP.de</a></p>



<p>Indentation. Whitespace. Block structure. Line rhythm.</p>



<p>You scan a file and just feel overwhelmed—or calm—before you’ve even read a single line.</p>



<p>That’s not a visual aesthetic thing. It’s a cognitive load thing.</p>



<p>When code looks chaotic, your brain assumes it is chaotic.</p>



<p>When it’s cleanly structured? Your mind can glide through it, predict it, trust it.</p>



<p>You’re not just reading lines. You’re navigating a landscape.</p>



<p>And cluttered terrain slows thinking.</p>



<p><strong></strong><strong>Plumber Thinking</strong>:</p>



<p>You’ve long preached visual clarity.</p>



<p>Your spacing, your grouping, your naming conventions—they’re designed for legibility, not minimalism.</p>



<p>You know that white space is a cognitive tool, not wasted real estate.</p>



<p>You’ve even pointed out how nesting alone can induce bugs—because our brains lose scope perception when structure collapses.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>Imagine opening a cabinet under a sink.</p>



<p>In one house, the pipes are clean, labeled, evenly spaced.</p>



<p>In another, they’re twisted, duct-taped, looping behind the drywall.</p>



<p>You already know which one will leak.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;Visually well-structured code isn’t pretty—it’s predictable. And predictable structure reduces mental strain.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>Don’t just reformat for style—reformat for flow. Group related logic. Use white space meaningfully.</li>



<li>When reading legacy code, pause before diving in. Let your eyes scan shape. Does it suggest complexity?</li>



<li>Reformat deeply nested code just to feel its structure—see how much simpler it becomes.</li>
</ul>



<h2 class="wp-block-heading">6. Narrate the Flow: Sharing Your Mental Model</h2>



<p>Experienced developers don’t just refactor silently. They narrate.</p>



<p>“I’m splitting this out because the logic forks too early.”<br />“I renamed this to make its responsibility explicit.”<br />“This service is the real boundary—we need to show that.”</p>



<p>They aren’t just explaining code. They’re revealing the mental model that shaped it.</p>



<p>Code is communication. And communication isn’t just what you write—it’s what others understand.</p>



<p>If they can’t follow your thinking, your code is a liability—no matter how clever it is.</p>



<p>Naming, abstraction, comments—these aren’t documentation. They’re narrative tools. They encode the architecture in other people’s minds.</p>



<p><strong></strong><strong>Plumber Thinking</strong>:</p>



<p>You’ve internalized this.</p>



<p>When you restructure legacy code, you don’t just fix it—you expose its intent.</p>



<p>You use naming, typing, and PHPDoc to express meaning with precision.</p>



<p>You’ve said clearly: “Readable code tells a story. It has to be deletable and understandable—or it doesn’t belong.”</p>



<p>You narrate for the future reader—often yourself.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>A plumber explains a reroute not with schematics, but clarity:</p>



<p>“We added a shutoff here so you can isolate the leak without cutting the entire house.”</p>



<p>The client gets it.</p>



<p>The next plumber gets it.</p>



<p>The design becomes shared knowledge.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;Readable code isn’t just syntactically correct—it’s semantically shared. It transmits the original model without distortion.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>During code reviews, ask: Can I explain why this exists, not just how it works?</li>



<li>Use naming to encode roles and relationships, not just behavior.</li>



<li>Use lightweight comments to narrate intent—why this path was chosen.</li>
</ul>



<h2 class="wp-block-heading">7. Tools Are Great, But Your Brain’s the Boss</h2>



<p>Linters. Static analyzers. Formatters. AI pair programmers.</p>



<p>They’re everywhere—and yes, they’re useful.</p>



<p>But don’t confuse assistance with authority.</p>



<p>A tool can tell you that a method is too long.</p>



<ul class="wp-block-list">
<li>It can’t tell you whether it’s cohesive.</li>
</ul>



<ul class="wp-block-list">
<li>It can flag a missing type.</li>
</ul>



<ul class="wp-block-list">
<li>It can’t sense that the naming is misleading, or that the abstraction is rotting.</li>
</ul>



<p>-> Your intuition? It gets there before the warning light comes on.</p>



<p>The danger isn’t using tools—it’s outsourcing your judgment to them.</p>



<p>Take PHPStan’s classic warning:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>“Return type ‘User|null’ might be null here.”</em></p>
</blockquote>



<p>Most developers see that and rush to “fix” it.<br />By fix, they usually mean: add a <code>null</code> check, throw an exception, or change the type hint to <code>?User</code>.</p>



<p>But that’s not a fix—it’s a reflex.</p>



<p>What you should ask is:</p>



<ul class="wp-block-list">
<li><em>Why is <code>null</code> a possible return in the first place?</em></li>



<li><em>Does this function really model optionality—or are we just afraid of declaring intent?</em></li>



<li><em>Was this ever meant to fail silently? Or did we just avoid thinking about the default case?</em></li>
</ul>



<p>Here’s the brutal truth:<br />If the domain logic doesn’t expect a missing user, then returning <code>?User</code> is a <em>design error</em>—not a typing issue.<br />It misleads every caller into treating the result as optional when it’s not.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Tools report symptoms. It&#8217;s your job to diagnose the cause.</p>
</blockquote>



<p>So no—you don’t just slap on a <code>null</code> check.<br />You stop and rethink the contract:<br />Should this be <code>fetchUserOrFail(int $id): User</code>?<br />Or <code>findUserIfExists(int $id): ?User</code>—with the <code>?User</code> explicitly declaring <em>safe</em> optionality?</p>



<p>Because every <code>?T</code> is a semantic signal. If the meaning behind it is unclear or inconsistent, you’re not writing safe code—you’re writing ambiguous code that <em>compiles</em>.</p>



<p><strong></strong><strong>Plumber Thinking</strong>:</p>



<p>You’ve automated everything that matters: PHPStan, Rector, PHP-CS-Fixer.</p>



<p>But you’ve also said clearly: “They catch noise. I care about signal.”</p>



<p>You still scan for intention, context, and design cohesion.</p>



<p>You don’t accept autofixes blindly—you ask, “Would I have made this change? Does this align with the system’s needs?”</p>



<p>Your gut is the boss. The tool is the assistant.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>A plumber might use a pressure gauge, but they&#8217;ll still touch the pipe.</p>



<p>They&#8217;ll still listen for the high-pitched whine.</p>



<p>They’ll still trust the feel of a bad valve—even when the sensor says “normal.”</p>



<p>Why? Because machines don’t have experience.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;You can’t automate what you don’t understand. Tools amplify wisdom—but they can’t manufacture it.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>Before running a tool, assess the code yourself. What feels off? What seems brittle?</li>



<li>When a tool suggests a change, ask why. Would you make it manually?</li>



<li>Build your own internal checklist. Use tools to confirm—not define—your decisions.</li>
</ul>



<h2 class="wp-block-heading">8. Reflect to Learn: Making Experience Stick</h2>



<ul class="wp-block-list">
<li>Writing code isn’t enough. Fixing bugs isn’t enough.</li>
</ul>



<ul class="wp-block-list">
<li>Even surviving legacy systems isn’t enough.</li>
</ul>



<ul class="wp-block-list">
<li>Reflection is where experience becomes intuition.</li>
</ul>



<p>-> When something breaks—don’t just patch it.</p>



<p>Ask: Why did I expect it to work?</p>



<p>What assumption failed? What context changed?</p>



<p>That’s the real learning.</p>



<p>Every prediction failure is an opportunity to sharpen your internal model. Without reflection, you’re just firefighting. With it, you’re upgrading your mental OS.</p>



<p><strong></strong><strong>Plumber Thinking</strong>:</p>



<p>You reflect by default.</p>



<p>Your retrospective discipline, your journaling of code decisions, your constant search for why something broke—that’s not routine. That’s professional cognition in motion.</p>



<p>You don’t just fix problems—you extract principles from them.</p>



<p>You’ve even asked yourself: &#8220;What would have prevented this mess five years ago?&#8221;</p>



<p>That’s elite-level introspection.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>The apprentice replaces a faulty valve.</p>



<p>The veteran asks:</p>



<p>“Why does this kind of valve always fail in this setup?”<br />“What can I do to make the next failure impossible?”</p>
<p>They’re not just fixing—they’re building resilience into their understanding.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;Experience becomes expertise when filtered through reflection. Without that, you’re just aging, not learning.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>After every tricky bug, write down the mistake in your mental model, not just the fix.</li>



<li>Use postmortems as a thinking tool, not a blame ritual.</li>



<li>When reading legacy code, ask: Why did they do it this way? What were the constraints then?</li>
</ul>



<h2 class="wp-block-heading">9. Principles Are Guides, Not Gospel</h2>



<p>We love our principles.<br />SRP. DRY. KISS. YAGNI. SOLID.</p>



<p>They’re powerful. They’re useful. They’re even beautiful—when applied wisely.</p>



<p>But here’s the uncomfortable truth:<br />They’re not laws. They’re heuristics.</p>



<p>Applied blindly, they can create complexity instead of clarity. You’ve seen it: a jungle of micro-classes in the name of “SRP.”</p>



<ul class="wp-block-list">
<li>A twisted abstraction tree justified by “DRY.”</li>
</ul>



<ul class="wp-block-list">
<li>A thousand interfaces no one asked for—just to “follow OCP.”</li>
</ul>



<p>-> Principles must serve the code—not the other way around.</p>



<p><strong></strong><strong>Plumber Thinking</strong>:</p>



<p>You live this tension.</p>



<p>You respect principles, but you don’t worship them.</p>



<p>You’ve rejected unnecessary abstractions that only exist to check a box.</p>



<p>You’ve said it yourself: “Deletable code matters more than theoretical purity.”</p>



<p>Your approach to DRY is practical: reduce harmful duplication, not introduce brittle indirection.</p>



<p>You favor clean pragmatism over cargo-cult architecture.</p>



<p>You don’t just follow rules—you ask why the rule exists, and when it stops helping.</p>



<p><strong>Plumber Analogy:</strong></p>



<p>A textbook might say to use a certain type of pipe junction.</p>



<p>But the veteran plumber on-site knows the real-world pressure, the angles, the space.</p>



<p>He breaks the “rule”—and the system works better for it.</p>



<p>Why? Because he understands the principle behind the rule, not just the rule itself.</p>



<p><strong>Coding Wisdom:</strong></p>



<p>&#8220;True mastery is knowing when to bend the rules—without breaking the system.&#8221;</p>



<p><strong>Practice:</strong></p>



<ul class="wp-block-list">
<li>When applying a principle, ask: What problem is this solving here?</li>



<li>Audit patterns. If you’re layering abstractions “just because,” stop.</li>



<li>Teach juniors the context behind the principle—not just the acronym.</li>
</ul>



<h2 class="wp-block-heading">Final Thought: Trust Your Inner Code Plumber</h2>



<ul class="wp-block-list">
<li>You don’t need an error to know code is wrong.</li>
</ul>



<ul class="wp-block-list">
<li>You don’t need a profiler to sense a bottleneck.</li>
</ul>



<ul class="wp-block-list">
<li>You don’t need a tool to tell you a class is trying to do too much.</li>
</ul>



<p>-> That whisper in your gut? That unease in your posture?</p>



<p>That’s Adaptive Systemic Intuition.</p>



<p>It’s not mysticism. It’s the compound interest of years spent reading, breaking, fixing, refactoring, and thinking.</p>



<p>Like a master plumber who hears a hum and knows what’s about to rupture—</p>



<ul class="wp-block-list">
<li>you feel complexity before it becomes entropy.</li>
</ul>



<ul class="wp-block-list">
<li>you sense rigidity before maintainability collapses.</li>
</ul>



<p>-> And most importantly: you can train this.</p>



<ul class="wp-block-list">
<li>Every refactor.</li>
</ul>



<ul class="wp-block-list">
<li>Every naming battle.</li>
</ul>



<ul class="wp-block-list">
<li>Every painful legacy rescue mission.</li>
</ul>



<ul class="wp-block-list">
<li>Every “this feels wrong” moment that you chase down to root cause.</li>
</ul>



<p>-> They all sharpen the pattern behind the patterns.</p>



<p><strong>Call to Action: Trust—and Hone—Your Gut</strong></p>



<p>Next time you open a file and it just feels “off,” do this:</p>



<ul class="wp-block-list">
<li>Pause. Listen to the discomfort. Don’t ignore it.</li>



<li>Narrate. Try explaining why it feels wrong. Is it naming? Flow? Entanglement?</li>



<li>Mentally simulate. Imagine a small change—does it cascade dangerously?</li>



<li>Reflect. Think about other systems that failed for the same reasons.</li>



<li>Use tools, but interpret their output through your experience.</li>



<li>Talk it out. Share your gut feeling with another dev—see if it resonates.</li>



<li>Iterate. Turn every failure into pattern recognition. Make it systemic.</li>
</ul>



<p>&#8220;Great code isn’t just functional. It feels right to work with.&#8221;</p>



<p>That feeling? That’s your internal plumber doing their job.</p>



<p>Let them work.</p>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fthe-inner-code-plumber%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dthe-inner-code-plumber&amp;action_name=The+Inner+Code+Plumber&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/05/the-inner-code-plumber/?pk_campaign=feed&amp;pk_kwd=the-inner-code-plumber/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6993</post-id>	</item>
		<item>
		<title>The PHPDoc Guide (2025 Edition)</title>
		<link>http://suckup.de/2025/05/the-phpdoc-guide-2025-edition/?pk_campaign=feed&amp;pk_kwd=the-phpdoc-guide-2025-edition&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=the-phpdoc-guide-2025-edition</link>
					<comments>http://suckup.de/2025/05/the-phpdoc-guide-2025-edition/?pk_campaign=feed&amp;pk_kwd=the-phpdoc-guide-2025-edition#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Thu, 01 May 2025 00:31:56 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6975</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/05/the-phpdoc-guide-2025-edition/?pk_campaign=feed&#038;pk_kwd=the-phpdoc-guide-2025-edition">The PHPDoc Guide (2025 Edition)</a></p>
<p>String-based pseudo-types Numeric &#38; bounded pseudo-types Arrays, lists, and shapes Object &#38; class-based types Callable types Generics with @template, @extends, @implements Constant values and enum simulations Conditional logic Pass-by-reference &#38; @param-out False positive suppression Best practices Cheatsheet   You can’t trust a string. Or an array. Or half the type declarations you see in legacy &#8230; <a href="http://suckup.de/2025/05/the-phpdoc-guide-2025-edition/?pk_campaign=feed&#038;pk_kwd=the-phpdoc-guide-2025-edition" class="more-link">Continue reading <span class="screen-reader-text">The PHPDoc Guide (2025 Edition)</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fthe-phpdoc-guide-2025-edition%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dthe-phpdoc-guide-2025-edition&amp;action_name=The+PHPDoc+Guide+%282025+Edition%29&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/05/the-phpdoc-guide-2025-edition/?pk_campaign=feed&#038;pk_kwd=the-phpdoc-guide-2025-edition">The PHPDoc Guide (2025 Edition)</a></p>

<ol>
<li>
<p><a href="#headline1">String-based pseudo-types</a></p>
</li>
<li>
<p><a href="#headline2">Numeric &amp; bounded pseudo-types</a></p>
</li>
<li>
<p><a href="#headline3">Arrays, lists, and shapes</a></p>
</li>
<li>
<p><a href="#headline4">Object &amp; class-based types</a></p>
</li>
<li>
<p><a href="#headline5new">Callable types</a></p>
</li>
<li>
<p><a href="#headline5">Generics with @template, @extends, @implements</a></p>
</li>
<li>
<p><a href="#headline6">Constant values and enum simulations</a></p>
</li>
<li>
<p><a href="#headline7">Conditional logic</a></p>
</li>
<li>
<p><a href="#headline8">Pass-by-reference &amp; <code>@param-out</code></a></p>
</li>
<li>
<p><a href="#headline9">False positive suppression</a></p>
</li>
<li>
<p><a href="#headline10">Best practices</a></p>
</li>
<li>
<p><a href="#headline11">Cheatsheet</a></p>
</li>
</ol>
<hr />
<p> </p>
<blockquote>
<p>You can’t trust a string. Or an array. Or half the type declarations you see in legacy PHP codebases.</p>
</blockquote>
<p>And that’s not PHP’s fault. It’s yours—if you’re still writing function signatures like this:</p>
<pre><code class="language-php">function sendData(array $data): bool
</code></pre>
<p>This tells us nothing.<br />Not what’s in <code>$data</code>, not if keys are optional, not what the return <code>bool</code> even means.</p>
<p>PHPStan fixes this. <strong>With PHPDocs. </strong>Not for decoration. Not for old-school docblocks. But as <strong>strict, analyzable type contracts </strong>— guardrails for real-world codebases.</p>
<p>If you&#8217;re serious about:</p>
<ul>
<li>
<p>Catching logic errors before runtime</p>
</li>
<li>
<p>Documenting your code <strong>without duplicating logic</strong></p>
</li>
<li>
<p>Scaling PHP safely <strong>without turning everything into a typed mess</strong></p>
</li>
</ul>
<p>Then this guide is for you.</p>
<hr />
<p>We’ll walk through real-world PHPStan PHPDoc patterns—from pseudo-types and generics to conditional logic and type-safe constants. All based on <a href="https://phpstan.org/writing-php-code/phpdoc-types" target="_blank" rel="noopener"><strong>PHPStan</strong></a>, tested in real-world projects, and packed with <strong>concrete examples</strong> and <strong>copy-paste snippets</strong>.</p>
<p>No fluff. Just clean, pragmatic PHPDoc annotations that make your code safer and more readable. The best part? <strong>PhpStorm</strong> supports nearly everything we’re doing here out of the box — so code completion improves, and your overall DX gets a serious upgrade.</p>
<blockquote>
<p>Let’s upgrade your PHPDocs from “comments” to <strong>contracts</strong>.</p>
</blockquote>
<hr />
<h2><strong>Background: Why PHPDocs Matter More Than Ever</strong></h2>
<hr />
<p>PHP has come a long way since the wild west of <code>PHP 5.x</code>.</p>
<p>Today we’ve got:</p>
<p><strong data-start="251" data-end="258">8.0</strong> with union types and constructor property promotion, &#8230;<br data-start="310" data-end="313" /><strong data-start="315" data-end="322">8.1</strong> with enums and readonly properties, &#8230;<br data-start="357" data-end="360" /><strong data-start="362" data-end="369">8.2</strong> with readonly classes and DNF types, &#8230;<br data-start="405" data-end="408" /><strong data-start="410" data-end="417">8.3</strong> with typed class constants and <code data-start="449" data-end="463">#[\Override], ...</code><br data-start="463" data-end="466" /><strong data-start="468" data-end="475">8.4</strong> with property hooks and asymmetric visibility, &#8230;</p>
<p>So… why bother with PHPDocs at all?</p>
<hr />
<h3><strong>What Native Types Still Can’t Do</strong></h3>
<p>Native PHP types help—but <strong>they stop at the surface</strong>.</p>
<table>
<thead>
<tr>
<th>Native Type</th>
<th>Can Do</th>
<th>Can’t Do</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>string</code></td>
<td>Ensure value is a string</td>
<td>Can’t check if empty, numeric, constant</td>
</tr>
<tr>
<td><code>int</code></td>
<td>Enforce integer input</td>
<td>Can’t limit to &gt; 0 or within bounds</td>
</tr>
<tr>
<td><code>array</code></td>
<td>Accept arrays</td>
<td>Can’t validate keys, shape, or index types</td>
</tr>
<tr>
<td><code>object</code></td>
<td>Accept objects</td>
<td>No info about which class, structure, or generics</td>
</tr>
<tr>
<td><code>bool</code></td>
<td>Boolean logic</td>
<td>Can’t express &#8220;this is only true on success&#8221;</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>That’s Where PHPStan Comes In</strong></h3>
<p>PHPStan treats your PHPDocs like a type system:</p>
<ul>
<li>
<p>Refines <strong>scalar types</strong> (<code>non-empty-string</code>, <code>positive-int</code>, <code>numeric-string</code>)</p>
</li>
<li>
<p>Models <strong>structured arrays</strong> (<code>array{key1: T, key2?: T}</code>)</p>
</li>
<li>
<p>Adds <strong>generics</strong> (<code>@template T</code>, <code>Collection&lt;T&gt;</code>)</p>
</li>
<li>
<p>Enforces <strong>contracts and conditionals</strong> (<code>@assert</code>, <code>@return (T is Foo ? Bar : Baz)</code>)</p>
</li>
<li>
<p>Tracks <strong>pass-by-reference mutations</strong> (<code>@param-out</code>)</p>
</li>
<li>
<p>Restricts <strong>literal values</strong> (<code>'asc'|'desc'</code>, <code>Class::CONST_*</code>, enums)</p>
</li>
</ul>
<p>This gives you <strong>defensive typing</strong> for a dynamic language.</p>
<hr />
<h2><strong><a id="headline1"></a>1. String-Based Pseudo-Types</strong></h2>
<p><em>Refine what “string” actually means</em></p>
<hr />
<p>In PHP, <code>string</code> is a blunt instrument. It could mean:</p>
<ul>
<li>
<p><code>"admin"</code> – a valid username</p>
</li>
<li>
<p><code>""</code> – an empty input nobody should see</p>
</li>
<li>
<p><code>"123"</code> – a number pretending to be a string</p>
</li>
<li>
<p><code>"SELECT * FROM users WHERE user_id = " . $id</code> – a dangerous SQL statement</p>
</li>
</ul>
<p>PHPStan sharpens this instrument with <strong>string pseudo-types</strong> that define <strong>intent, constraints, and trust boundaries</strong>.</p>
<hr />
<h3><strong>Overview: String-Based Pseudo-Types</strong></h3>
<table style="width: 100%; height: 388px;">
<thead>
<tr style="height: 58px;">
<th style="height: 58px;">PHPStan Type</th>
<th style="height: 58px;">Description</th>
<th style="height: 58px;">Native Equivalent</th>
</tr>
</thead>
<tbody>
<tr style="height: 36px;">
<td style="height: 36px;"><code>string</code></td>
<td style="height: 36px;">Any string, including <code>''</code></td>
<td style="height: 36px;">string</td>
</tr>
<tr style="height: 59px;">
<td style="height: 59px;"><code>non-empty-string</code></td>
<td style="height: 59px;">String that cannot be <code>''</code></td>
<td style="height: 59px;">string</td>
</tr>
<tr style="height: 59px;">
<td style="height: 59px;"><code>numeric-string</code></td>
<td style="height: 59px;">String that is guaranteed to represent a number (<code>"123.45"</code>)</td>
<td style="height: 59px;">string</td>
</tr>
<tr style="height: 58px;">
<td style="height: 58px;"><code>literal-string</code></td>
<td style="height: 58px;">A string known at compile-time (e.g. hardcoded, not user input)</td>
<td style="height: 58px;">string</td>
</tr>
<tr style="height: 59px;">
<td style="height: 59px;"><code>callable-string</code></td>
<td style="height: 59px;">A string name of a globally callable function</td>
<td style="height: 59px;">string</td>
</tr>
<tr style="height: 59px;">
<td style="height: 59px;"><code>class-string&lt;T&gt;</code></td>
<td style="height: 59px;">String that is a fully-qualified class name (optionally of type T)</td>
<td style="height: 59px;">string</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Real-World Examples</strong></h3>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>non-empty-string</code></h4>
<p>Guarantees a string is never empty:</p>
<p><a href="https://phpstan.org/r/bcd0b64f-0c72-4cd8-b078-c20bc2f509e0">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param non-empty-string $username
 */
function setUsername(string $username): void {
    // Safe, PHPStan guarantees it's not ''
    saveToDatabase($username);
}

setUsername('alice'); // OK
setUsername(''); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>numeric-string</code></h4>
<p>Used when string inputs must represent numbers (e.g., form inputs):</p>
<p><a href="https://phpstan.org/r/f3baac09-c27e-49bb-a793-89a12c910a81">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param numeric-string $amount
 */
function convertToCents(string $amount): int {
    return (int)((float) $amount * 100);
}

convertToCents("19.95"); // OK
convertToCents("abc"); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>literal-string</code></h4>
<p>Guards against injection vulnerabilities in SQL or dynamic calls:</p>
<p><a href="https://phpstan.org/r/26796473-6479-4233-84ed-89f2582fbeac">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param literal-string $sqlQuery
 */
function runQuery(string $sqlQuery): void {
    DB::raw($sqlQuery); // Only compile-time constants allowed
}

runQuery("SELECT * FROM users"); // OK
runQuery($_GET['query']); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>callable-string</code></h4>
<p>Ensures string names reference valid callable functions:</p>
<p><a href="https://phpstan.org/r/d6f9f389-c7c1-4b23-816a-81e7dba19099">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param callable-string $callback
 */
function invoke(string $callback): void {
    $callback(); // Safe: PHPStan checks it's actually callable
}

invoke('trim'); // OK
invoke('undefinedFunction'); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>class-string&lt;T&gt;</code></h4>
<p>Used in factories or DI containers:</p>
<p><a href="https://phpstan.org/r/2849754d-3bbf-496a-bad3-72726d065a9d">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @template T of LoggerInterface
 * @param class-string&lt;T&gt; $class
 * @return T
 */
function createLogger(string $class): object {
    return new $class(); // Safe and strongly typed
}

createLogger(FileLogger::class); // OK
createLogger(DateTime::class); // PHPStan error: not a LoggerInterface
</code></pre>
<hr />
<h3><strong>Out-of-the-Box Use Case: Constants-as-Strings</strong></h3>
<p>Use <code>literal-string</code> when defining keys for array-based configuration:</p>
<p><a href="https://phpstan.org/r/405f2650-0bd4-4a55-bb44-1dd5eba79972">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param (literal-string&amp;'database_host') $configKey
 */
function getConfig(string $configKey): mixed {
    return $GLOBALS['config'][$configKey] ?? null;
}

getConfig('database_host'); // OK
getConfig($userInput); // PHPStan error
</code></pre>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p><code>non-empty-string</code> kills edge-case bugs.</p>
</li>
<li>
<p><code>literal-string</code> hardens systems against injections.</p>
</li>
<li>
<p><code>callable-string</code> and <code>class-string&lt;T&gt;</code> enable safe dynamic resolution.</p>
</li>
<li>
<p>Always prefer these over plain <code>string</code> when handling user input, SQL, config keys, or dynamic execution.</p>
</li>
</ul>
<hr />
<h2><strong><a id="headline2"></a>2. Numeric &amp; Range-Based Pseudo-Types</strong></h2>
<p><em>Precision where <code>int</code> and <code>float</code> fall short</em></p>
<hr />
<p>A parameter like <code>int $page</code> tells you nothing about valid input. Is <code>0</code> okay? What about <code>-1</code>? Or <code>999999</code>? That’s not type safety—it’s type ambiguity.</p>
<p>PHPStan’s numeric pseudo-types <strong>embed actual constraints</strong> in the signature. Let’s make your numbers behave.</p>
<hr />
<h3><strong>Overview: Numeric Pseudo-Types</strong></h3>
<table>
<thead>
<tr>
<th>PHPStan Type</th>
<th>Description</th>
<th>Native Equivalent</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>positive-int</code></td>
<td>Integer &gt; 0</td>
<td>int</td>
</tr>
<tr>
<td><code>negative-int</code></td>
<td>Integer &lt; 0</td>
<td>int</td>
</tr>
<tr>
<td><code>non-negative-int</code></td>
<td>Integer ≥ 0 (0, 1, &#8230;)</td>
<td>int</td>
</tr>
<tr>
<td><code>non-positive-int</code></td>
<td>Integer ≤ 0 (0, -1, &#8230;)</td>
<td>int</td>
</tr>
<tr>
<td><code>int&lt;min, max&gt;</code></td>
<td>Integer within specified range (inclusive)</td>
<td>int</td>
</tr>
<tr>
<td><code>numeric</code></td>
<td>int, float, or numeric-string</td>
<td>mixed</td>
</tr>
<tr>
<td><code>float</code></td>
<td>Any float</td>
<td>float</td>
</tr>
</tbody>
</table>
<blockquote>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2139.png" alt="ℹ" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Note:</strong> PHPStan <strong>does not</strong> currently support <code>float&lt;min, max&gt;</code> // <a href="https://github.com/phpstan/phpstan/issues/6963">Add range for float · Issue #6963 · phpstan/phpstan</a></p>
</blockquote>
<hr />
<h3><strong>Real-World Examples</strong></h3>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>positive-int</code></h4>
<p>Ensure ID-like values are never 0 or negative:</p>
<p><a href="https://phpstan.org/r/f10eb3a8-e983-4449-ac88-cb3657927c97">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param positive-int $userId
 */
function getUser(int $userId): User {
    return User::find($userId);
}

getUser(42); // OK
getUser(0); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>non-negative-int</code></h4>
<p>Zero is allowed, useful for offsets and indexes:</p>
<p><a href="https://phpstan.org/r/feb77b18-19bf-48dd-bccd-77115637f120">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param non-negative-int $offset
 */
function paginate(int $offset, int $limit = 10): array {
    return getRows($offset, $limit);
}

paginate(0); // OK
paginate(-5); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>int&lt;1, 10&gt;</code></h4>
<p>Constrain arbitrary ranges—perfect for ratings or percent caps:</p>
<p><a href="https://phpstan.org/r/433f9bd2-f395-4c2e-81d5-74b38fcea09a">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param int&lt;1, 10&gt; $rating
 */
function setUserRating(int $rating): void {
    // Only 1–10 allowed
}<br /><br />
setUserRating(10); // OK 
setUserRating(20); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>negative-int</code></h4>
<p>Useful for things like accounting deltas:</p>
<p><a href="https://phpstan.org/r/b5b6f3f0-f818-4fbc-9ce2-ce648d5187e6">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param negative-int $debt
 */
function recordDebt(int $debt): void {
    // Only negative values allowed
}

recordDebt(-100); // OK
recordDebt(0); // PHPStan error
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>numeric</code></h4>
<p>Accept int, float, or numeric-string – great for dynamic APIs:</p>
<p><a href="https://phpstan.org/r/ed5374c7-da38-48ae-82dc-df870059835a">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param numeric $value
 */
function normalize($value): float {
    return (float) $value;
}

normalize("5.4"); // OK
normalize(3); // OK
normalize("not a number"); // PHPStan error
</code></pre>
<hr />
<h3><strong>Out-of-the-Box Use Case: Domain Constraints via Aliases</strong></h3>
<p>Combine <code>@phpstan-type</code> with range types to <strong>centralize</strong> constraints:</p>
<p><a href="https://phpstan.org/r/6cb054d6-5976-4379-a39a-244695ca0668">Playground | PHPStan</a></p>
<pre><code class="language-php">/** @phpstan-type Rating int&lt;1, 5&gt; */

/**
 * @param Rating $stars
 */
function rate(int $stars): void {
    // Only 1–5 allowed
}
</code></pre>
<p>Avoids hardcoding ranges across your codebase + PhpStorm version &gt;= 2025.1 has support for it.</p>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p>Native <code>int</code> and <code>float</code> don’t carry domain meaning—these do.</p>
</li>
<li>
<p>Use <code>int&lt;min,max&gt;</code> for bounded values. Be explicit.</p>
</li>
<li>
<p>Prefer <code>numeric</code> over <code>mixed</code> for conversion-safe values.</p>
</li>
<li>
<p>Enforce constraints without runtime guards—<strong>fail at analysis time</strong>.</p>
</li>
</ul>
<hr />
<h2><strong><a id="headline3"></a>3. Array &amp; List-Based Pseudo-Types</strong></h2>
<p><em>Because <code>array</code> is a wildcard, not a type.</em></p>
<hr />
<p>Saying <code>array $data</code> is like saying “vehicle” when you mean “electric scooter with one broken brake.” Arrays in PHP are:</p>
<ul>
<li>
<p>numerically indexed or associative,</p>
</li>
<li>
<p>empty or structured,</p>
</li>
<li>
<p>sometimes lists, sometimes maps—and usually misunderstood.</p>
</li>
</ul>
<p>PHPStan gives you the tools to <strong>lock this chaos down</strong>.</p>
<hr />
<h3><strong>Overview: Array Pseudo-Types</strong></h3>
<table>
<thead>
<tr>
<th>PHPStan Type</th>
<th>Description</th>
<th>Native PHP Equivalent</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>array</code></td>
<td>Anything that’s an array—uselessly vague</td>
<td>array</td>
</tr>
<tr>
<td><code>list&lt;T&gt;</code></td>
<td>Indexed from 0, consecutive integers, all values of T</td>
<td>array</td>
</tr>
<tr>
<td><code>non-empty-list&lt;T&gt;</code></td>
<td>Same as <code>list&lt;T&gt;</code>, but with at least one element</td>
<td>array</td>
</tr>
<tr>
<td><code>array&lt;TKey, TValue&gt;</code></td>
<td>Associative array with defined key/value types</td>
<td>array</td>
</tr>
<tr>
<td><code>non-empty-array&lt;TKey, V&gt;</code></td>
<td>Like above, but must have at least one key-value pair</td>
<td>array</td>
</tr>
<tr>
<td><code>array{key1: T1, key2?: T2}</code></td>
<td>Structured array with required and optional keys</td>
<td>array</td>
</tr>
<tr>
<td><code>array-key</code></td>
<td>Either <code>int</code> or <code>string</code>—valid PHP array keys only</td>
<td>int|string</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Examples by Use Case</strong></h3>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>list&lt;int&gt;</code></h4>
<p>Use when you need guaranteed 0-indexed values:</p>
<p><a href="https://phpstan.org/r/d8c78e2d-77c7-418e-99e9-a986784507d7">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @return list&lt;int&gt;
 */
function getIds(): array {
    return [1, 2, 3]; // PHPStan ensures keys are 0,1,2,...
}
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>non-empty-list&lt;string&gt;</code></h4>
<p>Use for arguments that must not be empty:</p>
<p><a href="https://phpstan.org/r/8b608500-778a-4bbe-a67d-02f5707c8715">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param non-empty-list&lt;string&gt; $emails
 */
function notify(array $emails): void {
    foreach ($emails as $email) {
        mail($email, 'Hello!');
    }
}
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>array&lt;string, User&gt;</code></h4>
<p>Classic associative map:</p>
<p><a href="https://phpstan.org/r/f3e52528-3dfd-41c7-a5c9-422bb564dad6">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @return array&lt;string, User&gt;
 */
function getUserMap(): array {
    return ['admin' =&gt; new User(), 'guest' =&gt; new User()];
}
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>array{status: bool, message: string}</code></h4>
<p>Great for structured return types:</p>
<p><a href="https://phpstan.org/r/9c256e52-52ec-49bd-ad2a-bd8e6d9df2b6">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @return array{status: bool, message: string}
 */
function response(): array {
    return ['status' =&gt; true, 'message' =&gt; 'OK'];
}
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>array{ids: list&lt;int&gt;, error?: string}</code></h4>
<p>Mixed structure with optional keys:</p>
<p><a href="https://phpstan.org/r/824e3991-ab90-49d8-808f-5ce7fe06d74e">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @return array{ids: list&lt;int&gt;, error?: string}
 */
function fetch(): array {
    return ['ids' =&gt; [1, 2, 3]];
}
</code></pre>
<hr />
<h3><strong>Advanced Use Case: Refactor To Aliases</strong></h3>
<p>Avoid repeating complex shapes:</p>
<p><a href="https://phpstan.org/r/bb2411e6-d7da-4336-863a-84e752596323">Playground | PHPStan</a></p>
<pre><code class="language-php">/** @phpstan-type ApiResponse array{status: bool, message: string, data?: mixed} */

/**
 * @return ApiResponse
 */
function getJson(): array {
    return ['status' =&gt; true, 'message' =&gt; 'Success'];
}
</code></pre>
<hr />
<h3><strong>Use Table: When to Pick Which</strong></h3>
<table>
<thead>
<tr>
<th>Use Case</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>Indexed, all same type</td>
<td><code>list&lt;T&gt;</code></td>
</tr>
<tr>
<td>Must contain elements</td>
<td><code>non-empty-list&lt;T&gt;</code></td>
</tr>
<tr>
<td>Map with defined key type</td>
<td><code>array&lt;K, V&gt;</code></td>
</tr>
<tr>
<td>Structured data (like DTO)</td>
<td><code>array{...}</code></td>
</tr>
<tr>
<td>Optional shape fields</td>
<td><code>array{key?: T}</code></td>
</tr>
<tr>
<td>Dynamic lookup</td>
<td><code>array-key</code> for keys</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Pro Tip:</strong> If your <code>array{}</code> shape is reused or growing—<strong>stop.</strong></h3>
<p>Use a Value Object. It&#8217;s clearer, testable, and doesn’t break when you add <code>nullableTimestamp?</code>.</p>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p><code>array</code> is a <strong>type smell</strong>—replace it with something precise.</p>
</li>
<li>
<p>Use <code>list&lt;&gt;</code> when order and index matter. Use <code>array{}</code> for shape.</p>
</li>
<li>
<p>Use <code>@phpstan-type</code> to create <strong>aliases</strong> for shared structures.</p>
</li>
<li>
<p>Don’t let critical business structures live in vague <code>array&lt;string, mixed&gt;</code> land.</p>
</li>
<li>
<p>Once array shape gets complicated: make a DTO or value object. Don’t be clever. Be explicit.</p>
</li>
</ul>
<ul>
<li>
<p>Prefer <code>list&lt;T&gt;</code> over <code>T[]</code> when <strong>order and dense 0-based indexing</strong> matter.</p>
</li>
<li>
<p>Use e.g. <code>non-empty-list&lt;T&gt;</code> for enforced content.</p>
</li>
</ul>
<hr />
<h2><strong><a id="headline4"></a>4. Object &amp; Class-Based Pseudo-Types</strong></h2>
<p><em>Make your objects speak their real shape.</em></p>
<hr />
<p>PHP&#8217;s <code>object</code> type tells you nothing. PHPStan’s object pseudo-types tell you <em>everything</em>: where the object came from, how it&#8217;s called, what it returns, and what it’s allowed to be.</p>
<hr />
<h3><strong>Overview: Class &amp; Object Pseudo-Types</strong></h3>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
<th>Use Case</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>object</code></td>
<td>Any object—completely generic</td>
<td>Rare; dynamic APIs</td>
</tr>
<tr>
<td><code>ClassName</code></td>
<td>Exact class or subclass instance</td>
<td>95% of all real code</td>
</tr>
<tr>
<td><code>self</code></td>
<td>The class this is written in (not inheritable)</td>
<td>Static factory methods</td>
</tr>
<tr>
<td><code>$this</code></td>
<td>The current instance’s real type (used for method chaining)</td>
<td>Fluent interfaces, traits</td>
</tr>
<tr>
<td><code>static</code></td>
<td>The class called at runtime (supports late static binding)</td>
<td>Factories returning subclass instances</td>
</tr>
<tr>
<td><code>class-string</code></td>
<td>Any valid FQCN string (non-instantiable without context)</td>
<td>Reflection, service locators</td>
</tr>
<tr>
<td><code>class-string&lt;T&gt;</code></td>
<td>A string guaranteed to name a subclass of <code>T</code></td>
<td>Typed dynamic instantiation</td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Examples by Use Case</strong></h3>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>object</code></h4>
<p>Use <em>only</em> when you don’t care what it is (usually bad practice):</p>
<pre><code class="language-php">/**
 * @param object $instance
 */
function dumpObject(object $instance): void {
    var_dump($instance);
}
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>self</code></h4>
<p>Always returns the exact class it&#8217;s written in—<em>not</em> a child class:</p>
<pre><code class="language-php">class Factory {
    public static function make(): self {
        return new self(); // Always returns Factory
    }
}
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>$this</code></h4>
<p>Used for <strong>fluent interfaces</strong>—important in <strong>traits</strong> or base classes:</p>
<pre><code class="language-php">trait Loggable {
    /** @return $this */
    public function log(string $msg): self {
        echo "[LOG] $msg\n";
        return $this;
    }
}
</code></pre>
<p>Used in:</p>
<pre><code class="language-php">class Order { use Loggable; }
$order = (new Order())-&gt;log('Created')-&gt;log('Paid');
</code></pre>
<p>PHPStan/PhpStorm knows <code>log()</code> returns <code>Order</code>, not <code>Loggable</code>. Magic.</p>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>static</code></h4>
<p>Enables late static binding:</p>
<p><a href="https://phpstan.org/r/5f4f57bb-187e-4a1b-83a9-6907c97e33c6">Playground | PHPStan</a></p>
<pre><code class="language-php">class Repository {
    public static function new(): static {
        return new static(); // Might be a child class
    }
}

class UserRepository extends Repository {}
$userRepo = UserRepository::new(); // Returns UserRepository
</code></pre>
<hr />
<h4><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <code>class-string&lt;Foo&gt;</code></h4>
<p>Ties a string to a valid subclass of Foo—powerful for DI, factories, etc.</p>
<p><a href="https://phpstan.org/r/74cb1d11-0417-4da5-841a-5ad2211b46ae">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @template T of Service
 * @param class-string&lt;T&gt; $fqcn
 * @return T
 */
function resolve(string $fqcn): object {
    return new $fqcn();
}
</code></pre>
<p>Enforces constraints even when instantiating from strings.</p>
<hr />
<h3><strong>Use Table: Object Pseudo-Types</strong></h3>
<table>
<thead>
<tr>
<th>Use Case</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>Generic object input</td>
<td><code>object</code></td>
</tr>
<tr>
<td>Static factory (same class)</td>
<td><code>self</code></td>
</tr>
<tr>
<td>Chaining / trait methods</td>
<td><code>$this</code></td>
</tr>
<tr>
<td>Factory w/ LSB (return child)</td>
<td><code>static</code></td>
</tr>
<tr>
<td>Instantiating by string</td>
<td><code>class-string&lt;T&gt;</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p>Always use <code>$this</code> for chaining and traits.</p>
</li>
<li>
<p>Use <code>static</code> when returning child classes from base class factories.</p>
</li>
<li>
<p><code>class-string&lt;T&gt;</code> makes dynamic instantiation type-safe.</p>
</li>
<li>
<p>Avoid <code>object</code> unless you&#8217;re writing a serializer.</p>
</li>
</ul>
<hr />
<h2 data-sourcepos="650:1-650:38"><a id="headline5new"></a>5. Callable Types &amp; Signatures</h2>
<p data-sourcepos="652:1-652:347">The <code>callable</code> type in PHP is incredibly flexible, but historically it lacked type safety. It could be a function name string, an array <code>[object, 'methodName']</code>, an array <code>['ClassName', 'methodName']</code>, or a Closure. Just declaring a parameter as <code>callable</code> tells PHPStan (and you) almost nothing about what arguments it expects or what it returns.</p>
<p data-sourcepos="654:1-654:56">PHPStan lets you document the <em>signature</em> of a callable.</p>
<h3 data-sourcepos="656:1-656:35">Documenting Callable Signatures</h3>
<p data-sourcepos="658:1-658:53">The syntax for documenting a callable&#8217;s signature is:</p>
<div class="code-block ng-tns-c2500688458-372 ng-trigger ng-trigger-codeBlockRevealAnimation">
<div class="formatted-code-block-internal-container ng-tns-c2500688458-372">
<div class="animated-opacity ng-tns-c2500688458-372">
<pre class="ng-tns-c2500688458-372"><code class="code-container formatted ng-tns-c2500688458-372" role="text" data-test-id="code-content" data-sourcepos="660:1-662:49"><span class="hljs-keyword">callable</span>(ParamType1, ParamType2, ...): ReturnType
</code></pre>
</div>
</div>
</div>
<p data-sourcepos="664:1-664:72">This goes <em>inside</em> your <code>@param</code> or <code>@return</code> tag for the callable type.</p>
<ul data-sourcepos="666:3-670:0">
<li data-sourcepos="666:3-666:89">Specify the expected types of parameters within the parentheses, separated by commas.</li>
<li data-sourcepos="667:3-667:51">Specify the expected return type after a colon.</li>
<li data-sourcepos="668:3-668:76">Use <code>void</code> if the callable is not expected to return a meaningful value.</li>
<li data-sourcepos="669:3-670:0">Use <code>mixed</code> if the parameters or return type are truly unknown or can vary wildly (but try to be more specific!).</li>
</ul>
<h3 data-sourcepos="671:1-671:37">Examples of Documenting Callables</h3>
<p data-sourcepos="673:1-673:31"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Closure with simple types</strong></p>
<p data-sourcepos="673:1-673:31"><a href="https://phpstan.org/r/083ac843-5f9c-44f7-b4bf-47dfc38eaf09">Playground | PHPStan</a></p>
<div class="code-block ng-tns-c2500688458-373 ng-trigger ng-trigger-codeBlockRevealAnimation">
<div class="formatted-code-block-internal-container ng-tns-c2500688458-373">
<div class="animated-opacity ng-tns-c2500688458-373">
<pre class="ng-tns-c2500688458-373"><code class="code-container formatted ng-tns-c2500688458-373" role="text" data-test-id="code-content" data-sourcepos="675:1-686:91"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param</span> callable(int, string): bool $validator
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processData</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> <span class="hljs-variable">$validator</span></span>): <span class="hljs-title">void</span> </span>{
    <span class="hljs-variable">$result</span> = <span class="hljs-variable">$validator</span>(<span class="hljs-number">123</span>, <span class="hljs-string">'abc'</span>);
    <span class="hljs-comment">// PHPStan knows $result is bool here</span>
}

processData(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> <span class="hljs-variable">$a</span>, <span class="hljs-keyword">string</span> <span class="hljs-variable">$b</span></span>): <span class="hljs-title">bool</span> =&gt; <span class="hljs-title">is_numeric</span>(<span class="hljs-params"><span class="hljs-variable">$a</span></span>) &amp;&amp; <span class="hljs-title">is_string</span>(<span class="hljs-params"><span class="hljs-variable">$b</span></span>))</span>; <span class="hljs-comment">// OK</span>
processData(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-variable">$a</span>, <span class="hljs-keyword">int</span> <span class="hljs-variable">$b</span></span>): <span class="hljs-title">bool</span> =&gt; <span class="hljs-title">true</span>)</span>; <span class="hljs-comment">// PHPStan error: argument types mismatch</span>
</code></pre>
</div>
</div>
</div>
<p data-sourcepos="688:1-688:36"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Array callable (object method)</strong></p>
<p data-sourcepos="688:1-688:36"><a href="https://phpstan.org/r/df3a8b5b-7dcc-4e34-9662-3754b6815133">Playground | PHPStan</a></p>
<div class="code-block ng-tns-c2500688458-374 ng-trigger ng-trigger-codeBlockRevealAnimation">
<div class="formatted-code-block-internal-container ng-tns-c2500688458-374">
<div class="animated-opacity ng-tns-c2500688458-374">
<pre class="ng-tns-c2500688458-374"><code class="code-container formatted ng-tns-c2500688458-374" role="text" data-test-id="code-content" data-sourcepos="690:1-706:58"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Service</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handle</span>(<span class="hljs-params"><span class="hljs-keyword">float</span> <span class="hljs-variable">$value</span></span>): <span class="hljs-title">string</span> </span>{ <span class="hljs-keyword">return</span> (<span class="hljs-keyword">string</span>) <span class="hljs-variable">$value</span>; }
}

<span class="hljs-comment">/**
 * <span class="hljs-doctag">@param</span> callable(float): string $callback
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">execute</span>(<span class="hljs-params"><span class="hljs-keyword">callable</span> <span class="hljs-variable">$callback</span></span>): <span class="hljs-title">void</span> </span>{
    <span class="hljs-variable">$result</span> = <span class="hljs-variable">$callback</span>(<span class="hljs-number">1.23</span>);
    <span class="hljs-comment">// PHPStan knows $result is string here</span>
}

<span class="hljs-variable">$service</span> = <span class="hljs-keyword">new</span> Service();
execute([<span class="hljs-variable">$service</span>, <span class="hljs-string">'handle'</span>]); <span class="hljs-comment">// OK</span>
execute([<span class="hljs-variable">$service</span>, <span class="hljs-string">'nonExistentMethod'</span>]); <span class="hljs-comment">// PHPStan error</span></code></pre>
</div>
</div>
</div>
<p data-sourcepos="727:1-727:39"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>String callable (global function)</strong></p>
<p data-sourcepos="729:1-729:213">While <code>callable-string</code> ensures it&#8217;s a valid function name, using the signature syntax adds type safety for the call itself.</p>
<p data-sourcepos="729:1-729:213"><a href="https://phpstan.org/r/23bc11eb-826a-4bd4-b52a-275cefad918b">Playground | PHPStan</a></p>
<div class="code-block ng-tns-c2500688458-376 ng-trigger ng-trigger-codeBlockRevealAnimation">
<div class="formatted-code-block-internal-container ng-tns-c2500688458-376">
<div class="animated-opacity ng-tns-c2500688458-376">
<pre class="ng-tns-c2500688458-376"><code class="code-container formatted ng-tns-c2500688458-376" role="text" data-test-id="code-content" data-sourcepos="731:1-742:94"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param</span> callable(string): string $modifier
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cleanInput</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-variable">$input</span>, <span class="hljs-keyword">callable</span> <span class="hljs-variable">$modifier</span></span>): <span class="hljs-title">string</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-variable">$modifier</span>(<span class="hljs-variable">$input</span>);
    <span class="hljs-comment">// PHPStan knows the callable takes string and returns string</span>
}

cleanInput(<span class="hljs-string">" hello "</span>, <span class="hljs-string">'trim'</span>); <span class="hljs-comment">// OK</span>
cleanInput(<span class="hljs-string">" hello "</span>, <span class="hljs-string">'str_starts_with'</span>); <span class="hljs-comment">// PHPStan error: str_starts_with signature mismatch</span>
</code></pre>
</div>
</div>
</div>
<h3 data-sourcepos="744:1-744:17">Key Takeaways</h3>
<ul data-sourcepos="746:3-750:0">
<li data-sourcepos="746:3-746:62">Simply using <code>callable</code> is not enough for static analysis.</li>
<li data-sourcepos="747:3-747:102">Always document the expected <strong>signature</strong> of a callable using <code>callable(ParamTypes): ReturnType</code>.</li>
<li data-sourcepos="748:3-748:107">This provides type safety for the parameters passed <em>to</em> the callable and the value returned <em>from</em> it.</li>
</ul>
<hr />
<h2><strong><a id="headline5"></a>6. Generic Types with <code>@template</code>, <code>@extends</code>, <code>@implements</code></strong></h2>
<p><em>Static typing for dynamic collections. </em></p>
<hr />
<h3><strong>Overview: Generic Type Annotations</strong></h3>
<table>
<thead>
<tr>
<th>Annotation</th>
<th>Purpose</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@template T</code></td>
<td>Declares a generic placeholder</td>
<td>class Collection</td>
</tr>
<tr>
<td><code>@template T of Foo</code></td>
<td>Constrains T to Foo or subclass</td>
<td>interface Repository</td>
</tr>
<tr>
<td><code>@param T</code> / <code>@return T</code></td>
<td>Applies T in method context</td>
<td>function add(T $item): void</td>
</tr>
<tr>
<td><code>@extends Collection&lt;T&gt;</code></td>
<td>Specifies generic type when extending a class</td>
<td>class UserCollection extends…</td>
</tr>
<tr>
<td><code>@implements Repo&lt;T&gt;</code></td>
<td>Specifies concrete type in interface implementation</td>
<td>class UserRepo implements…</td>
</tr>
</tbody>
</table>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Generic Collection (Classic)</h3>
<p><a href="https://phpstan.org/r/14368c95-e76b-433c-9c04-1fe366758478">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @template T
 */
class Collection {
    /** @var list&lt;T&gt; */
    private array $items = [];

    /** @param T $item */
    public function add(mixed $item): void {
        $this-&gt;items[] = $item;
    }

    /** @return list&lt;T&gt; */
    public function all(): array {
        return $this-&gt;items;
    }
}</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> @extends: Narrow Generic Type in Child Class</h3>
<pre><code class="language-php">/**
 * @extends Collection&lt;User&gt;
 */
class UserCollection extends Collection {
    public function findByEmail(string $email): ?User {
        foreach ($this-&gt;all() as $user) {
            if ($user-&gt;email === $email) return $user;
        }
        return null;
    }
}
</code></pre>
<p>Now the collection is <em>locked</em> to <code>User</code>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> @implements: Interfaces with Generics</h3>
<p><a href="https://phpstan.org/r/97826b6f-d090-46cc-8151-9b9b17ddabca">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @template T of Model
 */
interface Repository {
    /** @return T|null */
    public function find(int $id): ?object;

    /** @param T $model */
    public function save(object $model): void;
}
</code></pre>
<p>Implement with:</p>
<pre><code class="language-php">/**
 * @implements Repository&lt;User&gt;
 */
class UserRepository implements Repository {
    public function find(int $id): ?User { /* ... */ }

    public function save(object $model): void {
        if (!$model instanceof User) {
            throw new InvalidArgumentException();
        }
    }
}
</code></pre>
<hr />
<h3><strong>Use Table: Generic Constructs</strong></h3>
<table>
<thead>
<tr>
<th>Use Case</th>
<th>Syntax</th>
</tr>
</thead>
<tbody>
<tr>
<td>Reusable logic w/ varying types</td>
<td><code>@template T</code></td>
</tr>
<tr>
<td>Type-safe item addition</td>
<td><code>@param T $item</code></td>
</tr>
<tr>
<td>Type-safe container extension</td>
<td><code>@extends Collection&lt;T&gt;</code></td>
</tr>
<tr>
<td>Typed interface implementation</td>
<td><code>@implements Repository&lt;T&gt;</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p>Use <code>@template T</code> for anything that should be reusable (collections, services, repositories).</p>
</li>
<li>
<p><code>@extends</code> and <code>@implements</code> lock in the concrete type—no ambiguity.</p>
</li>
<li>
<p>PHPStan validates T everywhere it&#8217;s used: arrays, returns, conditionals.</p>
</li>
<li>And you can combine this with other phpdocs like callables: <a href="https://phpstan.org/r/c1cb7840-d28c-4eef-8f85-f4ab7a1d13c1">Playground | PHPStan</a></li>
</ul>
<hr />
<h2><strong><a id="headline6"></a>7. Enum-Like Constraints with Constants and Literal Values</strong></h2>
<hr />
<h3><strong>Because magic strings are garbage fire waiting to happen.</strong></h3>
<p>Whether you&#8217;re representing statuses, directions, or modes—<strong>&#8220;freeform strings&#8221; are a playground for bugs</strong>. Typos go undetected. Invalid values sneak through. Conditional logic breaks silently.</p>
<p><strong>PHPStan gives us better options</strong>—even <strong>before PHP 8.1 enums</strong>.</p>
<hr />
<h3><strong>Overview: Enum-Like Type Constraints</strong></h3>
<table>
<thead>
<tr>
<th>Type Annotation</th>
<th>Description</th>
<th>Works With</th>
</tr>
</thead>
<tbody>
<tr>
<td>`&#8217;value1&#8242;</td>
<td>&#8216;value2&#8217;`</td>
<td>Specific literal values allowed</td>
</tr>
<tr>
<td><code>MyClass::CONST_*</code></td>
<td>Any constant with matching prefix from a class</td>
<td>All</td>
</tr>
<tr>
<td>`MyClass::CONST_A</td>
<td>CONST_B`</td>
<td>Specific constant values allowed</td>
</tr>
<tr>
<td><code>MyEnum</code></td>
<td>Accepts any case of a native PHP 8.1+ <code>enum</code></td>
<td>PHP 8.1+</td>
</tr>
<tr>
<td><code>MyEnum::MyCase</code></td>
<td>Specific enum case from PHP 8.1+ enum</td>
<td>PHP 8.1+</td>
</tr>
<tr>
<td><code>key-of&lt;array&gt;</code> / <code>value-of&lt;array&gt;</code></td>
<td>Restrict input to keys/values of a predefined array</td>
<td>All</td>
</tr>
</tbody>
</table>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Literal Union Types</strong></h3>
<p><a href="https://phpstan.org/r/2d915419-d22d-4c12-9caf-9cd888d4ba27">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param 'asc'|'desc' $direction
 */
function sortResults(string $direction): void {
    // PHPStan enforces exactly 'asc' or 'desc'
}

sortResults('asc');   // OK
sortResults('ASC');   // ERROR: Not lowercase
sortResults('up');    // ERROR
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Class Constants (Wildcard or Specific)</strong></h3>
<p><a href="https://phpstan.org/r/19d6f7be-b3b0-4609-a4ee-26cae346584d">Playground | PHPStan</a></p>
<pre><code class="language-php">class Status {
    public const NEW = 'new';
    public const ACTIVE = 'active';
    public const BLOCKED = 'blocked';
}

/**
 * @param Status::NEW|Status::BLOCKED $status
 */
function blockUser(string $status): void {
    // PHPStan enforces only these constants
}

blockUser(Status::BLOCKED);   // OK
blockUser('blocked');         // ERROR: Use the constant, not the string
</code></pre>
<p><strong>Or allow all constants matching a prefix:</strong></p>
<pre><code class="language-php">/**
 * @param Status::STATUS_* $status
 */
function updateStatus(string $status): void {}
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Native Enums (PHP 8.1+)</strong></h3>
<p><a href="https://phpstan.org/r/77b82f50-4733-4825-9ce0-750a879753bc">Playground | PHPStan</a></p>
<pre><code class="language-php">enum UserStatus: string {
    case ACTIVE = 'active';
    case BANNED = 'banned';
}

function setStatus(UserStatus $status): void {}

setStatus(UserStatus::ACTIVE);   // OK
setStatus('active');             // ERROR
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Array-Based Constraints (<code>key-of</code>, <code>value-of</code>)</strong></h3>
<p><a href="https://phpstan.org/r/676d13a5-a653-460d-a742-6ffcecf6fd16">Playground | PHPStan</a> (key-of)</p>
<p><a href="https://phpstan.org/r/e36a1d54-f6fe-43c6-9600-eed06cf4bddf">Playground | PHPStan</a> (value-of)</p>
<pre><code class="language-php">public const array ALLOWED_ROLES = ['admin' =&gt; 1, 'editor' =&gt; 2, 'viewer' =&gt; 3];

/**
 * @param key-of&lt;self::ALLOWED_ROLES&gt; $role
 */
public function assignRole(string $role): void {}

$foo-&gt;assignRole('editor');    // OK
$foo-&gt;assignRole('moderator'); // ERROR
</code></pre>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p>Don’t trust freeform values—<strong>constrain them</strong>.</p>
</li>
<li>
<p>Use <strong>literal strings or class constants</strong> to build pseudo-enums.</p>
</li>
<li>
<p>Use <strong>native PHP enums</strong> when available, especially in domain logic.</p>
</li>
<li>
<p>Use <code>key-of</code>, <code>value-of</code> to enforce consistency in maps.</p>
</li>
</ul>
<hr />
<h2><strong><a id="headline7"></a>8. Conditional Types &amp; Type Inference Logic</strong></h2>
<hr />
<h3><strong>Because sometimes your types depend on the situation.</strong></h3>
<p>Static typing gets tricky when return types or variable values depend on conditions—especially <strong>input parameters or validation results</strong>.</p>
<p><strong>PHPStan gives us smart annotations</strong> to express:</p>
<ul>
<li>
<p>Types that change depending on a condition (<code>@return ($flag is true ? A : B)</code>)</p>
</li>
<li>
<p>Variable type guarantees after a validation function (<code>@phpstan-assert-*</code>)</p>
</li>
<li>
<p>Smart refactoring of <code>isValid()</code> patterns with actual type info</p>
</li>
</ul>
<hr />
<h3><strong>Overview: Conditional Typing Patterns</strong></h3>
<table style="width: 100%; height: 330px;">
<thead>
<tr style="height: 36px;">
<th style="height: 36px;">Annotation</th>
<th style="height: 36px;">Purpose</th>
<th style="height: 36px;">Use Case Example</th>
</tr>
</thead>
<tbody>
<tr style="height: 59px;">
<td style="height: 59px;"><code>@return (cond ? T1 : T2)</code></td>
<td style="height: 59px;">Return type depends on a parameter value</td>
<td style="height: 59px;">Return string or array depending on <code>$asArray</code></td>
</tr>
<tr style="height: 59px;">
<td style="height: 59px;"><code>@phpstan-assert T $var</code></td>
<td style="height: 59px;">Guarantees <code>$var</code> is of type T after method call</td>
<td style="height: 59px;">assertNonEmpty($str) makes <code>$str</code> a <code>non-empty-string</code></td>
</tr>
<tr style="height: 59px;">
<td style="height: 59px;"><code>@phpstan-assert-if-true T $var</code></td>
<td style="height: 59px;">If method returns true, <code>$var</code> is of type T</td>
<td style="height: 59px;">isValidEmail($email) ensures <code>non-empty-string</code> if true</td>
</tr>
<tr style="height: 59px;">
<td style="height: 59px;"><code>@phpstan-assert-if-false T $var</code></td>
<td style="height: 59px;">If method returns false, <code>$var</code> is of type T</td>
<td style="height: 59px;">isEmpty($arr) =&gt; if false, it&#8217;s <code>non-empty-array</code></td>
</tr>
<tr style="height: 58px;">
<td style="height: 58px;"><code>T is ClassName</code></td>
<td style="height: 58px;">Conditional logic inside generics</td>
<td style="height: 58px;"><code>@return (T is User ? int : string)</code></td>
</tr>
</tbody>
</table>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Conditional Return Types Based on Flags</strong></h3>
<p><a href="https://phpstan.org/r/2354b8a0-216b-490f-8bdf-7596241ab0a0">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @return ($asJson is true ? string : array{name: string, age: int})
 */
function getUserData(bool $asJson): string|array {
    $data = ['name' =&gt; 'Alice', 'age' =&gt; 30];
    return $asJson ? json_encode($data, \JSON_THROW_ON_ERROR) : $data;
}

$data = getUserData(false);
// PHPStan: knows $data is array{name: string, age: int}

$json = getUserData(true);
// PHPStan: knows $json is string
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>@phpstan-assert-if-true</strong></h3>
<p><a href="https://phpstan.org/r/ea19c5a6-beb4-4082-8e7d-f55466762152">Playground | PHPStan</a></p>
<pre><code class="language-php">final class Validator {
    /**
     * @phpstan-assert-if-true non-empty-string $email
     */
    public static function isValidEmail(?string $email): bool {
        return is_string($email) &amp;&amp; $email !== '' &amp;&amp; str_contains($email, '@');
    }
}

$email = $_POST['email'] ?? null;

if (Validator::isValidEmail($email)) {
    // PHPStan knows $email is non-empty-string here
    echo strtoupper($email);
}
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>@phpstan-assert-if-false</strong></h3>
<p><a href="https://phpstan.org/r/f58e7fbd-bfa4-4c68-9e84-a7dad32e1098">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @phpstan-assert-if-false int&lt;min, 0&gt; $score
 */
function isPositive(int $score): bool {
    return $score &gt; 0;
}

$score = rand(-5, 5);

if (!isPositive($score)) {
    // PHPStan: $score is int&lt;min, 0&gt;
} else {
    // PHPStan: $score is int&lt;1, max&gt;
}
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Conditional Return Types in Generics</strong></h3>
<p><a href="https://phpstan.org/r/19ac7d70-e8bd-4e82-a54a-78d2f9290404">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @template T of int|string
 * @param T $input
 * @return (T is int ? string : int)
 */
function invertType(int|string $input): string|int {
    return is_int($input) ? (string)$input : (int)$input;
}

$val1 = invertType(42);     // string
$val2 = invertType('123');  // int
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>@phpstan-assert for Defensive Contracts</strong></h3>
<p><a href="https://phpstan.org/r/5c39293e-cc2f-4e35-907b-e48def3144bd">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @phpstan-assert non-empty-array&lt;string&gt; $items
 */
function assertHasItems(array $items): void {
    if (empty($items)) {
        throw new InvalidArgumentException("Must contain at least one item.");
    }
}
</code></pre>
<p>Use these to enforce contracts even if native PHP types can’t.</p>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p>Let your return types reflect real-world branching logic.</p>
</li>
<li>
<p>Use <code>@phpstan-assert-if-true</code> to encode validator results into type narrowing.</p>
</li>
<li>
<p>Use <code>@return (condition ? A : B)</code> to model toggle behavior safely.</p>
</li>
<li>
<p>Defensive types are better than defensive runtime checks—<strong>because they&#8217;re enforced before runtime.</strong></p>
</li>
</ul>
<hr />
<h2><strong><a id="headline8"></a>9. Pass-by-Reference Variables with <code>@param-out</code></strong></h2>
<hr />
<h3><strong>Stop guessing what happens to that &amp;$var.</strong></h3>
<p>PHP’s <code>&amp;$variable</code> allows <strong>mutation by reference</strong>—which is great for <strong>parsers, validators, or multi-output functions</strong>, but it kills static type analysis.</p>
<p>PHPStan solves this with <code>@param-out</code>: <strong>explicitly documenting the final type</strong> of a referenced variable after a function call.</p>
<p>Think of it as &#8220;the function <em>returns into</em> this variable&#8221;—and <strong>now PHPStan knows</strong> what to expect.</p>
<hr />
<h3><strong>Overview: <code>@param-out</code> Syntax</strong></h3>
<table>
<thead>
<tr>
<th>Annotation</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@param-out T $var</code></td>
<td>Describes the type <code>$var</code> will have after the function call finishes.</td>
</tr>
<tr>
<td><code>@param T $var</code></td>
<td>Still describes the type it must be at input, if not uninitialized.</td>
</tr>
</tbody>
</table>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Parsing Into a Variable</strong></h3>
<p><a href="https://phpstan.org/r/01e0ba13-bc5b-4d1f-8bc8-c307e2043e2f">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param string $input
 * @param-out int|null $parsed
 */
function parseInt(string $input, ?int &amp;$parsed): void {
    $parsed = filter_var($input, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
}
</code></pre>
<pre><code class="language-php">$raw = "42";
$result = null;

parseInt($raw, $result);

// PHPStan: $result is now int|null
if ($result !== null) {
    echo $result * 2;
}
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Assigning a Default String</strong></h3>
<p><a href="https://phpstan.org/r/0677f448-117d-4cfe-b824-62273cb6e708">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param-out non-empty-string $output
 */
function ensureValue(?string &amp;$output): void {
    if ($output === null || $output === '') {
        $output = 'default';
    }
}
</code></pre>
<pre><code class="language-php">$name = null;
ensureValue($name);

// PHPStan: $name is now non-empty-string
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Flagging Errors in Processing</strong></h3>
<p><a href="https://phpstan.org/r/3fedabe2-41bb-45fc-bbfd-dc919635433e">Playground | PHPStan</a></p>
<pre><code class="language-php">/**
 * @param CsvFile $csv
 * @param-out list&lt;string&gt; $errors
 */
function processCsv(CsvFile $csv, array &amp;$errors): bool {
    $errors = [];
    foreach ($csv-&gt;getRows() as $row) {
        if (!isValidRow($row)) {
            $errors[] = 'Invalid row: ' . json_encode($row);
        }
    }
    return empty($errors);
}
</code></pre>
<pre><code class="language-php">$errors = [];
$success = processCsv($file, $errors);

if (!$success) {
    foreach ($errors as $e) {
        echo $e;
    }
}
</code></pre>
<p>Now <code>$errors</code> is a <strong>guaranteed list of strings</strong>, only if the function sets it.</p>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p>Use <code>@param-out</code> whenever a <code>&amp;$var</code> is written to.</p>
</li>
<li>
<p>Combine with <code>@param</code> to describe both <em>input and output</em> intent.</p>
</li>
<li>
<p>Helps static analysis track types over mutation.</p>
</li>
<li>
<p>Prevents &#8220;guessing&#8221; about the variable&#8217;s final type in calling scope.</p>
</li>
</ul>
<hr />
<h2><strong><a id="headline9"></a>10. Suppressing False Positives with <code>@phpstan-ignore-*</code></strong></h2>
<hr />
<h3><strong>Sometimes static analysis gets it wrong. That’s OK—</strong> but make it <strong>surgical</strong>, not sloppy.</h3>
<p>PHPStan is powerful, but not omniscient. In complex, dynamic, or legacy-heavy codebases, it might raise <strong>false positives</strong>—errors that <em>you</em> know are safe but the tool can’t fully reason about.</p>
<p>Don’t disable entire rules. Don’t drop your level.<br />Use <code>@phpstan-ignore-*</code> annotations <strong>surgically, with precision</strong>.</p>
<hr />
<h3><strong>Overview: Suppression Annotations</strong></h3>
<table>
<thead>
<tr>
<th>Annotation</th>
<th>Scope</th>
<th>Best Use Case</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@phpstan-ignore-next-line</code></td>
<td>Next line only (<em>please use the <code>Identifier</code> stuff not this</em>)</td>
<td>Dynamic access, legacy code edge cases</td>
</tr>
<tr>
<td><code>@phpstan-ignore-line</code></td>
<td>Inline on same line (<em>please use the <code>Identifier</code> stuff not this</em>)</td>
<td>Dynamic properties/methods, chained expressions</td>
</tr>
<tr>
<td><code>@phpstan-ignore-error Identifier</code></td>
<td>Specific error type only</td>
<td>Narrow suppression while keeping strict checks</td>
</tr>
<tr>
<td><code>parameters &gt; ignoreErrors:</code> (neon)</td>
<td>Global suppression config</td>
<td>Vendor code or unavoidable project-wide issues</td>
</tr>
</tbody>
</table>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Ignoring the Next Line</strong></h3>
<pre><code class="language-php">/** @phpstan-ignore-next-line */
echo $legacyObject-&gt;$dynamicProperty;
</code></pre>
<p>Useful when <code>$dynamicProperty</code> is <strong>validated externally</strong>, but PHPStan can’t infer that.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Inline Suppression</strong></h3>
<pre><code class="language-php">$val = $legacyObject-&gt;$property; /** @phpstan-ignore-line */
</code></pre>
<p>Keep suppression right next to the usage, especially helpful for one-liners.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Targeting Specific Errors</strong></h3>
<pre><code class="language-php">/** @phpstan-ignore-error function.alreadyNarrowedType (your comment here) */
if (is_string($value) &amp;&amp; strlen($value) &gt; 5) {
    echo $value;
}
</code></pre>
<p>This suppresses only the “already narrowed” warning, keeping everything else active.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Global Project Suppression (<code>phpstan.neon</code>)</strong></h3>
<pre><code class="language-neon">parameters:
    ignoreErrors:
        - '#Call to undefined method LegacyClass::doMagic#'
        - 
            message: '#Access to an undefined property#'
            path: src/LegacyStuff/*.php
</code></pre>
<p>Use this only for vendor or legacy glue code. <strong>Never in new code.</strong></p>
<hr />
<h3><strong>Best Practices for Ignoring</strong></h3>
<table>
<thead>
<tr>
<th>Rule</th>
<th>Why</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Always comment</strong></td>
<td>Explain <em>why</em> the ignore is needed.</td>
</tr>
<tr>
<td><strong>Suppress specific errors, not broad ones</strong></td>
<td>Use <code>@phpstan-ignore-error</code>, not <code>ignore-next-line</code> if possible.</td>
</tr>
<tr>
<td><strong>Refactor &gt; Ignore</strong></td>
<td>Most false positives come from bad typing. Improve types if you can.</td>
</tr>
<tr>
<td><strong>Audit periodically</strong></td>
<td>Old ignores may hide real problems after refactors.</td>
</tr>
</tbody>
</table>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Don’t Do This</h3>
<pre><code class="language-php">/** @phpstan-ignore-next-line */
doSomethingRisky(); // No explanation, no control
</code></pre>
<p>Or worse:</p>
<pre><code class="language-neon">parameters:
    level: 0
</code></pre>
<p>You’ve just turned off the fire alarm and set your desk on fire, a simple way of starting is the baseline feature where you can just ignore old errors: <a href="https://phpstan.org/user-guide/baseline">The Baseline | PHPStan</a></p>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p><strong>Only ignore what you <em>must</em>.</strong> Don&#8217;t make it a habit.</p>
</li>
<li>
<p>Prefer <strong>precise, contextual suppression</strong> (<code>-error</code>, <code>-next-line</code>) over global.</p>
</li>
<li>
<p>Always add a <strong>human-readable comment</strong> for future devs.</p>
</li>
<li>
<p>Refactor the real problem if PHPStan is right.</p>
</li>
</ul>
<hr />
<h2><strong><a id="headline10"></a>11. Best Practices for PHPStan PHPDocs</strong></h2>
<hr />
<h3><strong>Make your types honest. Make your docs readable. Make your tools useful.</strong></h3>
<p>PHPStan doesn’t care how pretty your code looks—it cares if the types match, if edge cases are covered, and if your docs are aligned with reality. Writing good PHPDocs isn’t about verbosity. It’s about <strong>clarity, precision, and maintainability</strong>.</p>
<hr />
<h3><strong>PHPDoc Hygiene Checklist</strong></h3>
<table style="width: 100%;">
<thead>
<tr>
<th style="width: 52.4638%;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Do This</th>
<th style="width: 47.3913%;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Instead Of This</th>
</tr>
</thead>
<tbody>
<tr>
<td style="width: 52.4638%;">Use PHP native types wherever possible</td>
<td style="width: 47.3913%;">Duplicating native types in <code>@param</code> tags</td>
</tr>
<tr>
<td style="width: 52.4638%;">Add <strong>constraints</strong> with pseudo-types</td>
<td style="width: 47.3913%;">Vague types like <code>array</code> or <code>mixed</code></td>
</tr>
<tr>
<td style="width: 52.4638%;">Use <strong>shapes and lists</strong> (<code>array{}</code> / <code>list&lt;&gt;</code>)</td>
<td style="width: 47.3913%;">Indexed arrays with <code>array&lt;int,type&gt;</code> (unless needed)</td>
</tr>
<tr>
<td style="width: 52.4638%;">Prefer <code>@phpstan-type</code> for reuse or DTO of the type is complex</td>
<td style="width: 47.3913%;">Copy-pasting complex types across files</td>
</tr>
<tr>
<td style="width: 52.4638%;">Keep docs in sync with code</td>
<td style="width: 47.3913%;">Letting docs rot after refactors</td>
</tr>
<tr>
<td style="width: 52.4638%;">Add purpose-driven descriptions</td>
<td style="width: 47.3913%;">Empty <code>@param</code> tags with no context</td>
</tr>
</tbody>
</table>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Use Native Types First, PHPDoc Second</h3>
<pre><code class="language-php">// &#x274c; Redundant
/**
 * @param int $id
 */
function getUser(int $id): User {}

// &#x2705; Clean
function getUser(int $id): User {}

// &#x2705; All-In (it depends)<br />/**
 * @param UserId $id Use the Value-Object to fetch the User.
 */
function getUser(UserId $id): User {}
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Add Value with PHPStan Types</h3>
<pre><code class="language-php">// &#x2705; Enforce constraints
/**
 * @param positive-int $userId
 */
function getUserById(int $userId): User {}
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Prefer <code>array{}</code> Over Raw <code>array</code></h3>
<pre><code class="language-php">// &#x274c; Too generic
function getConfig(): array {}

// &#x2705; Self-documenting and type-safe
/**
 * @return array{host: string, port: int}
 */
function getConfig(): array {}
</code></pre>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Use <code>list&lt;T&gt;</code> or <code>non-empty-list&lt;T&gt;</code></h3>
<pre><code class="language-php">/**
 * @return non-empty-list&lt;User&gt;
 */
function getActiveUsers(): array {}
</code></pre>
<p>No more bugs from assuming the first item exists.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Reuse with <code>@phpstan-type</code></h3>
<pre><code class="language-php">/**
 * @phpstan-type UserData array{
 *   id: int,
 *   name: non-empty-string,
 *   email: string
 * }
 */
</code></pre>
<p>Then:</p>
<pre><code class="language-php">/**
 * @return UserData
 */
public function getUserData(): array {}
</code></pre>
<p>Update once. Used often. But once again, if you need this everywhere, please create a DTO class for it. :)</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Generics with <code>@template</code></h3>
<pre><code class="language-php">/**
 * @template T
 * @param T $value
 * @return T
 */
function identity($value) { return $value; }
</code></pre>
<p>Now that’s a real generic—PHPStan can track the type through usage.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Descriptions Are Not Dead</h3>
<pre><code class="language-php">/**
 * Fetches total including tax.
 *
 * @param list&lt;Item&gt; $items Items in the cart.
 * @param positive-int $vat VAT rate in percent (e.g. 19).
 * @return float Total price incl. tax.
 */
function calculateTotal(array $items, int $vat): float {}
</code></pre>
<p>You’re writing code for humans <em>and</em> tools. Don’t forget the humans + you can use html (lists, string, &#8230;) here.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Suppress Only When Necessary</h3>
<pre><code class="language-php">// We’re dealing with dynamic properties from legacy __get
/** @phpstan-ignore-next-line */
echo $legacyObject-&gt;$name;
</code></pre>
<p>But don’t make this a crutch. Fix types instead.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Keep Docs in Sync</h3>
<p>When you rename a parameter, update the PHPDoc.<br />When you change the return type, fix the annotation.<br />Outdated docs are <strong>worse than none at all</strong>.</p>
<hr />
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Consider a DTO or Value Object</h3>
<pre><code class="language-php">// &#x274c; This is too much for an array shape
/**
 * @return array{
 *   user: array{id: int, name: string},
 *   metadata: array{roles: list&lt;string&gt;, active: bool},
 *   settings?: array&lt;string, mixed&gt;
 * }
 */
</code></pre>
<p>Just… stop. Use a DTO. Your future self thanks you.</p>
<hr />
<h3><strong>Key Takeaways</strong></h3>
<ul>
<li>
<p>Don’t document what PHP already knows.</p>
</li>
<li>
<p>Document what PHP can’t express.</p>
</li>
<li>
<p>Use PHPStan’s extensions to document intent, not just shape.</p>
</li>
<li>
<p>Reuse types. Describe constraints. Avoid magic.</p>
</li>
</ul>
<hr />
<h2><strong><a id="headline11"></a>12. Cheatsheet &amp; Final Summary</strong></h2>
<hr />
<p>Let’s wrap this beast up the way it deserves: with a <strong>clear cheatsheet</strong> of everything PHPStan&#8217;s extended PHPDoc syntax gives you—and how to <strong>actually use it in production</strong>.</p>
<p>This isn’t theoretical. It’s not for linting your hobby script. This is how <strong>real teams keep real codebases from turning into type-anarchist dumpster fires</strong>.</p>
<hr />
<h3><strong>Cheatsheet: PHPStan PHPDoc Types by Category</strong></h3>
<h4><strong>Scalar &amp; Refined Pseudo-Types</strong></h4>
<table>
<thead>
<tr>
<th>Type</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>non-empty-string</code></td>
<td>String that&#8217;s never <code>''</code></td>
</tr>
<tr>
<td><code>numeric-string</code></td>
<td>String that parses to number (<code>"123"</code>, <code>"1.5"</code>)</td>
</tr>
<tr>
<td><code>literal-string</code></td>
<td>String known at compile time</td>
</tr>
<tr>
<td><code>positive-int</code></td>
<td>Integer &gt; 0</td>
</tr>
<tr>
<td><code>non-negative-int</code></td>
<td>Integer &gt;= 0</td>
</tr>
<tr>
<td><code>negative-int</code></td>
<td>Integer &lt; 0</td>
</tr>
<tr>
<td><code>non-positive-int</code></td>
<td>Integer &lt;= 0</td>
</tr>
<tr>
<td><code>int&lt;min, max&gt;</code></td>
<td>Integer between <code>min</code> and <code>max</code> (inclusive)</td>
</tr>
<tr>
<td><code>class-string&lt;T&gt;</code></td>
<td>Fully qualified class name (subtype of <code>T</code>)</td>
</tr>
<tr>
<td><code>callable-string</code></td>
<td>String name of a global callable</td>
</tr>
</tbody>
</table>
<hr />
<h4><strong>Array &amp; List Types</strong></h4>
<table style="width: 100%; height: 288px;">
<thead>
<tr style="height: 36px;">
<th style="height: 36px;">Type</th>
<th style="height: 36px;">Meaning</th>
</tr>
</thead>
<tbody>
<tr style="height: 36px;">
<td style="height: 36px;"><code>array&lt;TKey, TValue&gt;</code></td>
<td style="height: 36px;">Associative array</td>
</tr>
<tr style="height: 36px;">
<td style="height: 36px;"><code>non-empty-array&lt;TKey, TValue&gt;</code></td>
<td style="height: 36px;">Associative array with at least one element</td>
</tr>
<tr style="height: 36px;">
<td style="height: 36px;"><code>list&lt;T&gt;</code></td>
<td style="height: 36px;">0-based sequential array (indexed)</td>
</tr>
<tr style="height: 36px;">
<td style="height: 36px;"><code>non-empty-list&lt;T&gt;</code></td>
<td style="height: 36px;"><code>list&lt;T&gt;</code> with at least one element</td>
</tr>
<tr style="height: 36px;">
<td style="height: 36px;"><code>array{key: T, ...}</code></td>
<td style="height: 36px;">Structured array with required keys</td>
</tr>
<tr style="height: 36px;">
<td style="height: 36px;"><code>array{key?: T}</code></td>
<td style="height: 36px;">Structured array with optional keys</td>
</tr>
<tr style="height: 36px;">
<td style="height: 36px;"><code>array-key</code></td>
<td style="height: 36px;">`int</td>
</tr>
</tbody>
</table>
<hr />
<h4><strong>Object, Class</strong></h4>
<table>
<thead>
<tr>
<th>Type</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>object</code></td>
<td>Any object</td>
</tr>
<tr>
<td><code>self</code></td>
<td>Current class (not child)</td>
</tr>
<tr>
<td><code>$this</code></td>
<td>Instance of calling class</td>
</tr>
<tr>
<td><code>static</code></td>
<td>Late static binding return</td>
</tr>
<tr>
<td><code>class-string&lt;T&gt;</code></td>
<td>String that must be a subtype of <code>T</code></td>
</tr>
</tbody>
</table>
<hr />
<h4>Callable</h4>
<table>
<thead>
<tr>
<th>Syntax</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>callable</code></td>
<td>Any valid PHP callable (closure, string, array callback)</td>
</tr>
<tr>
<td><code>callable(): void</code></td>
<td>A callable that takes no parameters and returns nothing</td>
</tr>
<tr>
<td><code>callable(int): bool</code></td>
<td>A callable that takes an <code>int</code> and returns a <code>bool</code></td>
</tr>
<tr>
<td><code>callable(string, T): T</code></td>
<td>Generic callable with multiple parameters and return type</td>
</tr>
<tr>
<td><code>Closure(T): R</code></td>
<td>Closure with generic parameter and return type</td>
</tr>
<tr>
<td><code>callable-string</code></td>
<td>String name of a globally callable function</td>
</tr>
</tbody>
</table>
<h4><strong>Generics</strong></h4>
<table>
<thead>
<tr>
<th>Annotation</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@template T</code></td>
<td>Declare a type variable <code>T</code></td>
</tr>
<tr>
<td><code>@template T of Foo</code></td>
<td>Restrict <code>T</code> to be subtype of <code>Foo</code></td>
</tr>
<tr>
<td><code>@param T $value</code></td>
<td>Use generic <code>T</code> for parameter</td>
</tr>
<tr>
<td><code>@return T</code></td>
<td>Return generic type <code>T</code></td>
</tr>
<tr>
<td><code>@var T[] / list&lt;T&gt;</code></td>
<td>Typed container</td>
</tr>
<tr>
<td><code>@extends Base&lt;T&gt;</code></td>
<td>Specify type <code>T</code> when extending base class</td>
</tr>
<tr>
<td><code>@implements Interface&lt;T&gt;</code></td>
<td>Specify type <code>T</code> for implementation</td>
</tr>
</tbody>
</table>
<hr />
<h4><strong>Structured Data &amp; Reusability</strong></h4>
<table>
<thead>
<tr>
<th>Syntax</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@phpstan-type Alias = Type</code></td>
<td>Type alias for complex types</td>
</tr>
<tr>
<td><code>@phpstan-import-type</code></td>
<td>Import alias from another scope/class</td>
</tr>
</tbody>
</table>
<hr />
<h4><strong>Constant &amp; Enum-Like Constraints</strong></h4>
<table>
<thead>
<tr>
<th>Syntax</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>'foo'|'bar'</code></td>
<td>Specific literal values allowed</td>
</tr>
<tr>
<td><code>MyClass::CONST_*</code></td>
<td>All constants matching prefix in a class</td>
</tr>
<tr>
<td><code>MyClass::CONST_A | MyClass::CONST_B</code></td>
<td>Specific constant values allowed</td>
</tr>
<tr>
<td><code>MyEnum::MyCase</code> (PHP 8.1+)</td>
<td>Specific native Enum case</td>
</tr>
<tr>
<td><code>key-of&lt;array&gt;</code> / <code>value-of&lt;array&gt;</code></td>
<td>Constrain to keys/values of a known constant array</td>
</tr>
</tbody>
</table>
<hr />
<h4><strong>Type Assertions &amp; Conditional Logic</strong></h4>
<table>
<thead>
<tr>
<th>Annotation</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@phpstan-assert T $var</code></td>
<td>Assert <code>$var</code> is type <code>T</code> after call</td>
</tr>
<tr>
<td><code>@phpstan-assert-if-true T $var</code></td>
<td>If function returns true, <code>$var</code> is <code>T</code></td>
</tr>
<tr>
<td><code>@phpstan-assert-if-false T $var</code></td>
<td>If function returns false, <code>$var</code> is <code>T</code></td>
</tr>
<tr>
<td><code>@return (cond ? T1 : T2)</code></td>
<td>Conditional return type</td>
</tr>
</tbody>
</table>
<hr />
<h4><strong>By-Reference Output Tracking</strong></h4>
<table>
<thead>
<tr>
<th>Annotation</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@param-out T $var</code></td>
<td><code>$var</code> will be of type <code>T</code> after the function</td>
</tr>
</tbody>
</table>
<hr />
<h4><strong>Suppression &amp; Exceptions</strong></h4>
<table>
<thead>
<tr>
<th>Annotation</th>
<th>Use Case</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>@phpstan-ignore-next-line</code></td>
<td>Ignore all errors on the next line</td>
</tr>
<tr>
<td><code>@phpstan-ignore-line</code></td>
<td>Ignore errors inline</td>
</tr>
<tr>
<td><code>@phpstan-ignore-error error-id</code></td>
<td>Ignore specific error on current block</td>
</tr>
</tbody>
</table>
<hr />
<h2><strong>Final Thoughts</strong></h2>
<ul>
<li>
<p>Treat PHPDocs as <strong>contracts</strong>, not comments.</p>
</li>
<li>
<p>Don’t use <code>array</code> when you mean <code>non-empty-list&lt;literal-string&gt;</code>—<strong>be precise</strong>.</p>
</li>
<li>
<p>Refactor array shapes into DTOs when they get hairy.</p>
</li>
<li>
<p>Use <code>@phpstan-type</code>, <code>@template</code>, <code>@assert</code>, and <code>@param-out</code> to document behavior that PHP syntax alone can’t express.</p>
</li>
<li>
<p>Rely on <strong>tools, not convention</strong>. Let PHPStan hold the line.</p>
</li>
</ul>
<p> </p>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F05%2Fthe-phpdoc-guide-2025-edition%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dthe-phpdoc-guide-2025-edition&amp;action_name=The+PHPDoc+Guide+%282025+Edition%29&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/05/the-phpdoc-guide-2025-edition/?pk_campaign=feed&amp;pk_kwd=the-phpdoc-guide-2025-edition/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6975</post-id>	</item>
		<item>
		<title>SOLID Principles: From Paw Patrol to the Neighborhood</title>
		<link>http://suckup.de/2025/01/solid-principles-from-paw-patrol-to-linux-penguin/?pk_campaign=feed&amp;pk_kwd=solid-principles-from-paw-patrol-to-linux-penguin&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=solid-principles-from-paw-patrol-to-linux-penguin</link>
					<comments>http://suckup.de/2025/01/solid-principles-from-paw-patrol-to-linux-penguin/?pk_campaign=feed&amp;pk_kwd=solid-principles-from-paw-patrol-to-linux-penguin#comments</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Fri, 31 Jan 2025 01:27:19 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6962</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/01/solid-principles-from-paw-patrol-to-linux-penguin/?pk_campaign=feed&#038;pk_kwd=solid-principles-from-paw-patrol-to-linux-penguin">SOLID Principles: From Paw Patrol to the Neighborhood</a></p>
<p>– A Senior Developer’s Pragmatic Guide   The SOLID principles are essential guidelines for writing clean, maintainable, and scalable software. While many developers can recite them, real-world applications often struggle with their correct implementation. Understanding SOLID is not just about memorizing definitions; it&#8217;s about knowing when and how to apply them effectively. Sometimes, following the rules strictly &#8230; <a href="http://suckup.de/2025/01/solid-principles-from-paw-patrol-to-linux-penguin/?pk_campaign=feed&#038;pk_kwd=solid-principles-from-paw-patrol-to-linux-penguin" class="more-link">Continue reading <span class="screen-reader-text">SOLID Principles: From Paw Patrol to the Neighborhood</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fsolid-principles-from-paw-patrol-to-linux-penguin%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dsolid-principles-from-paw-patrol-to-linux-penguin&amp;action_name=SOLID+Principles%3A+From+Paw+Patrol+to+the+Neighborhood&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/01/solid-principles-from-paw-patrol-to-linux-penguin/?pk_campaign=feed&#038;pk_kwd=solid-principles-from-paw-patrol-to-linux-penguin">SOLID Principles: From Paw Patrol to the Neighborhood</a></p>

<div class="ptr--ptr">
<div class="ptr--box">
<div class="ptr--content">
<div class="ptr--icon"><span style="color: revert; font-size: 29px; font-weight: bold;">– A Senior Developer’s Pragmatic Guide</span></div>
<div> </div>
</div>
</div>
</div>
<div id="page-content" class="wrapper articles articles-edit articletag-programming articletag-softwaredevelopment articletag-php articletag-coding articleuser-30309" data-current-page="articles-edit">
<div id="page-content-inner" data-internal-nav="true"><main id="main-content" style="box-sizing: border-box; display: block; scroll-margin-top: var(--header-height);" data-article="{&quot;id&quot;:2251171,&quot;title&quot;:&quot;SOLID Principles: From Paw Patrol to Linux Penguins&quot;,&quot;updated_at&quot;:&quot;2025-01-31T01:15:12.418Z&quot;,&quot;main_image&quot;:&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/miv9sfnjmal186rt9rvg.png&quot;,&quot;published&quot;:false,&quot;published_at&quot;:null,&quot;body_markdown&quot;:&quot;---\ntitle: SOLID Principles: From Paw Patrol to Linux Penguins\npublished: false\ndescription: A Senior Developer’s Pragmatic Guide about SOLID principles \ntags: #programming #softwaredevelopment #php #coding\ncover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/miv9sfnjmal186rt9rvg.png\n# Use a ratio of 100:42 for best results.\n# published_at: 2025-01-31 01:12 +0000\n---\n\n## – A Senior Developer’s Pragmatic Guide\n\nThe **SOLID** principles are essential guidelines for writing clean, maintainable, and scalable software. While many developers can recite them, real-world applications often struggle with their correct implementation.\n\nUnderstanding SOLID is not just about memorizing definitions; it's about knowing when and how to apply them effectively. Sometimes, following the rules strictly can lead to unnecessary complexity, while a pragmatic approach ensures maintainability without over-engineering.\n\nIn this guide, we will break down each principle with practical **PHP examples**, **Paw Patrol analogies** for clarity, and **trade-offs** to consider. By the end, you’ll have a solid understanding of how these principles work together and when it's okay to bend them for the greater good.\n\n---\n\n## &#x1f3e1; The \&quot;Front Garden\&quot; \u0026 \&quot;Neighborhood\&quot; Metaphor: Why Naming Principles Matter\n\nImagine you don’t even know what “neighbor” or “front garden” means. Someone tries to explain that you shouldn’t walk through someone else’s garden, so they define these terms and create a rule. But that rule would be rigid and limiting.\n\nInstead, we define a broad principle that covers many similar scenarios, giving it a name so others immediately understand what we mean. This flexibility allows us to apply it beyond just neighbors and gardens while recognizing exceptions—like if the garden is yours or there’s an emergency.\n\n### How This Relates to SOLID\nSimilarly, SOLID is a set of abstract principles that define boundaries in object-oriented code. By naming these boundaries (SRP, OCP, LSP, ISP, DIP), we gain:\n\n1&#x20e3; **Efficient Communication** – We can say, “We’re violating OCP,” instead of explaining, “We keep re-editing stable code to add new features.”\n\n2&#x20e3; **Unified Understanding** – Whether human developers or AI-powered coding assistants, everyone recognizes the same underlying problem without a lengthy breakdown.\n\n3&#x20e3; **Flexible Exceptions** – Sometimes, crossing that fence is practical (if it’s your own “garden”) or necessary (in an emergency).\n\nKnowing these principles allows developers to make **intentional trade-offs**, rather than blindly applying or ignoring them.\n\n---\n\n## &#x1f9e0; How to Apply SOLID Without Over-Engineering\n\n### 1&#x20e3; Apply SOLID as Needed, Not as a Dogma\n- If a class is simple \u0026 works, don’t force an interface just to follow DIP.\n- If a method is naturally cohesive, don’t split it just to follow SRP.\n- If an interface is only used once, don’t extract it just for ISP.\n- **Code should be SOLID but also simple.**\n\n### 2&#x20e3; Focus on Refactoring, Not Preemptive Complexity\n- Refactor SOLID in steps **when a problem arises**.\n- Don’t create an abstraction until **you actually need it**.\n\n### 3&#x20e3; Use the 80/20 Rule\n- **80%** of your code should be pragmatic and **only 20%** should be deeply abstracted for maintainability.\n\n&#x1f4a1; **Example:**\n- An **order processing system** needs flexibility (**high SOLID compliance**).\n- A **CLI script that runs once a year**? No need for extreme abstractions.\n\n### 4&#x20e3; Know When to Break the Rules (Intentionally)\n- It’s okay to **violate SRP** if it keeps your code readable and practical.\n- Sometimes **direct dependencies (instead of DIP)** make sense for small projects.\n- Some classes might benefit from breaking **OCP** if modifying them improves clarity.\n\nBy the end of this guide, you’ll **not only understand SOLID** but also **when to apply it pragmatically**—allowing your architecture to evolve gracefully without unnecessary complexity.\n\n---\n\n## Single Responsibility Principle (SRP)\n\n![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlby1sbe8xgmna1tazv0.png)\n(source: https://trekhleb.dev/blog/2017/solid-principles-around-you/)\n\n### &#x1f4da; Academic Definition \n\u003e \&quot;A class should have only one reason to change.\&quot;\n\u003e — Robert C. Martin (Uncle Bob)\n\n### &#x1f3af; Our Definition \nA class should only do **one thing well** and not be responsible for multiple unrelated concerns.\n\n### &#x1f9d1;&#x200d;&#x1f4bb; Simple Definition \nEach class should **focus on a single task** or responsibility. If a class has multiple reasons to change, it likely violates SRP.\n\n---\n\n### &#x1f43e; Paw Patrol Analogy \nThink of **Paw Patrol**:\n- **Chase** handles police duties &#x1f693;\n- **Marshall** fights fires &#x1f692;\n- **Skye** flies helicopters &#x1f681;\n\nImagine if Skye had to drive the police car and fight fires too—it would be **chaotic**! The same applies to software: one class should not do **everything**.\n\n---\n\n### &#x1f9e0; Key Learnings \n1&#x20e3; **Identify \&quot;Axes of Change\&quot;** → If multiple teams request changes to the same class for different reasons, it's violating SRP.\n2&#x20e3; **Avoid \&quot;God Classes\&quot;** → Large classes handling everything lead to **maintenance nightmares**.\n3&#x20e3; **Encapsulation \u0026 Separation** → Keep concerns **independent** to improve testability and flexibility.\n4&#x20e3; **Avoid Premature Splitting** → If a class is small and cohesive, don't split it **just because**—follow **YAGNI** (You Ain't Gonna Need It).\n\n---\n\n### Simple Example (Violating SRP)\n#### Bad Example &#x1f6a8;: Too Many Responsibilities\n&#96;&#96;&#96;php\nclass ProfileManager {\n    public function authenticateUser(string $username, string $password): bool {\n        // Auth logic here\n    }\n    public function showUserProfile(string $username): UserProfile {\n        // Display user profile logic\n    }\n    public function updateUserProfile(string $username, array $data): UserProfile {\n        // Update logic\n    }\n    public function setUserPermissions(string $username, array $permissions): void {\n        // Set permissions logic\n    }\n}\n&#96;&#96;&#96;\n&#x1f534; **Why is this bad?**\n- Mixed responsibilities: Authentication, Profile Display, Profile Update, and Permissions **should not** be in one class. \n\n**Scenario**:  \n- HR wants new fields for user profiles.  \n- IT wants multi-factor authentication.  \n\nBoth modifications collide in a single class.\n\n&#x2705; **Fixed Version**\n&#96;&#96;&#96;php\nclass AuthenticationService {\n    public function authenticateUser(string $username, string $password): bool {\n        // Authentication logic\n    }\n}\n\nclass UserProfileService {\n    public function showUserProfile(string $username): UserProfile {\n        // Fetch user profile\n    }\n    public function updateUserProfile(string $username, array $data): UserProfile {\n        // Update user profile\n    }\n}\n\nclass PermissionService {\n    public function setUserPermissions(string $username, array $permissions): void {\n        // Set user permissions\n    }\n}\n&#96;&#96;&#96;\n&#x2705; **Now, each class has only one responsibility!** \n\nAnd each domain can now evolves independently, so this is often not just a technical decision, but also an organizational one.\n\n---\n\n### &#x1f6d2; E-Commerce Example \nImagine an **OrderProcessor** handling:\n- Payment processing\n- Shipping details\n- Generating invoices\n\n&#x1f6a8; **Bad Example**\n&#96;&#96;&#96;php\nclass OrderProcessor {\n    public function processPayment(PaymentDetails $payment): bool { /* Payment logic */ }\n    public function generateInvoice(Order $order): Invoice { /* Invoice logic */ }\n    public function arrangeShipping(Order $order): void { /* Shipping logic */ }\n}\n&#96;&#96;&#96;\n&#x1f534; **Why is this bad?**\n- If shipping logic changes, you need to modify OrderProcessor.\n- If invoicing logic changes, same problem!\n\n&#x2705; **Fixed Version**\n&#96;&#96;&#96;php\nclass PaymentService {\n    public function processPayment(PaymentDetails $payment): bool { /* Payment logic */ }\n}\n\nclass InvoiceService {\n    public function generateInvoice(Order $order): Invoice { /* Invoice logic */ }\n}\n\nclass ShippingService {\n    public function arrangeShipping(Order $order): void { /* Shipping logic */ }\n}\n&#96;&#96;&#96;\n&#x2705; **Each service has one responsibility!**\n\n---\n\n### &#x1f4cc; Advanced Insights &#x1f680;\n- **Cohesion vs. Fragmentation** → Don't split classes **too much**. Keep things **cohesive**.\n- **Testability** → Small, single-responsibility classes are easier to **unit test**.\n- **Microservices \u0026 Modular Design** → SRP is key in both microservices and modular monoliths.\n- **Database Layer** → If you see **fat repositories**, it might be a sign of SRP violation.\n\n---\n\n### &#x2696; Trade-offs \n&#x2705; **Pros:**\n- Easier maintenance\n- Better testability\n- More flexibility for future changes\n\n&#x274c; **Cons:**\n- Can introduce **too many** small classes if overused\n- Might feel like \&quot;over-engineering\&quot; for small projects\n\n---\n\n### &#x1f4a1; Developer Hints \n&#x2705; **Ask yourself:** \&quot;Does this class have more than one reason to change?\&quot; If yes → **SRP violation!**\n&#x2705; **Refactor when needed** → If a class is too big, break it **only when necessary**.\n&#x2705; **Think in modules** → Group related logic in separate **services**.\n\n---\n\n### &#x1f3c1; Conclusion\nThe **Single Responsibility Principle** is a fundamental but often misused principle. It's about **finding the right balance** between **cohesion** and **separation**. When applied correctly, it leads to **more maintainable**, **testable**, and **scalable** software.\n\nThe key takeaway? **SRP is not about splitting everything—it’s about ensuring a class has a single, well-defined purpose!** &#x1f680;\n\n---\n\n## Open-Closed Principle (OCP)\n\n![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dapoj2x076c0yq7dy1o4.png)\n(source: https://trekhleb.dev/blog/2017/solid-principles-around-you/)\n\n### &#x1f4da; Academic Definition \n\&quot;Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.\&quot; — Bertrand Meyer\n\n### &#x1f3af; Our Definition \nYour code should be designed in a way that allows adding new features **without modifying** the existing, stable code.\n\n### &#x1f4dd; Simple Definition \nInstead of changing old code every time a new feature is needed, structure your code so that you can extend it **without altering** what already works.\n\n### &#x1f43e; Paw Patrol Analogy \nWhen **Everest** joined the Paw Patrol for snow rescues &#x1f3d4;, none of the existing pups needed modification. The team was **extended**, not changed.\n\nLikewise, **new features** should be added as **extensions**, not by modifying existing code.\n\n### &#x1f9e0; Key Learnings \n1&#x20e3; **Open for Extension** – Your code should be designed in a way that allows you to add new functionality without touching the existing logic.\n2&#x20e3; **Closed for Modification** – Existing code should remain unchanged to prevent introducing new bugs.\n3&#x20e3; **Use Abstraction** – Utilize interfaces, abstract classes, or dependency injection to allow new behavior without modifying core logic.\n\n---\n\n### Common Mistake Example &#x274c;\n&#96;&#96;&#96;php\nclass AreaCalculator {\n    public function calculateTotalArea(array $shapes): float {\n        $totalArea = 0;\n        foreach ($shapes as $shape) {\n            if ($shape instanceof Circle) {\n                $totalArea += pi() * $shape-\u003eradius ** 2;\n            } elseif ($shape instanceof Square) {\n                $totalArea += $shape-\u003esideLength ** 2;\n            }\n        }\n        return $totalArea;\n    }\n}\n&#96;&#96;&#96;\n&#x1f6a8; **Problem:** Every time a new shape (e.g., &#96;Triangle&#96;) is introduced, this class needs modification, violating OCP.\n\n---\n\n### The Fix &#x2705;\n#### Using the Strategy Pattern\n&#96;&#96;&#96;php\ninterface Shape {\n    public function calculateArea(): float;\n}\n\nclass Circle implements Shape {\n    public function __construct(private float $radius) {}\n    public function calculateArea(): float {\n        return pi() * $this-\u003eradius ** 2;\n    }\n}\n\nclass Square implements Shape {\n    public function __construct(private float $sideLength) {}\n    public function calculateArea(): float {\n        return $this-\u003esideLength ** 2;\n    }\n}\n\nclass AreaCalculator {\n    public function calculateTotalArea(array $shapes): float {\n        return array_sum(array_map(\n            fn(Shape $shape) =\u003e $shape-\u003ecalculateArea(),\n            $shapes\n        ));\n    }\n}\n&#96;&#96;&#96;\n#### Why is this better?\n&#x2705; **Open for Extension** – New shapes (e.g., &#96;Triangle&#96;) can be added without modifying &#96;AreaCalculator&#96;.\n&#x2705; **Closed for Modification** – The core logic stays unchanged.\n&#x2705; **Encapsulated Behavior** – Each shape class is responsible for its own area calculation.\n\n---\n\n### &#x1f6d2; E-Commerce Example \nImagine a payment system where different payment methods need to be supported:\n\n#### Bad Example &#x1f6a8;\n&#96;&#96;&#96;php\nclass PaymentProcessor {\n    public function processPayment(string $type, float $amount) {\n        if ($type === 'credit_card') {\n            // Process credit card\n        } elseif ($type === 'paypal') {\n            // Process PayPal\n        }\n    }\n}\n&#96;&#96;&#96;\n&#x1f6a8; **Problem:** Every time a new payment method is added, the class needs modification.\n\n#### Fixed Example &#x2705;\n&#96;&#96;&#96;php\ninterface PaymentMethod {\n    public function process(float $amount): void;\n}\n\nclass CreditCardPayment implements PaymentMethod {\n    public function process(float $amount): void {\n        // Process credit card\n    }\n}\n\nclass PayPalPayment implements PaymentMethod {\n    public function process(float $amount): void {\n        // Process PayPal\n    }\n}\n\nclass PaymentProcessor {\n    public function __construct(private PaymentMethod $paymentMethod) {}\n    public function process(float $amount): void {\n        $this-\u003epaymentMethod-\u003eprocess($amount);\n    }\n}\n&#96;&#96;&#96;\n#### Benefits &#x1f680;\n&#x2705; Easily extendable – Add new payment methods without modifying existing code.\n&#x2705; Reduces risk – Core payment logic remains untouched.\n&#x2705; Improves readability – No complex &#96;if&#96; conditions.\n\n---\n\n### &#x1f4cc; Advanced Insights &#x1f680;\n- **Design Patterns**: The **Strategy Pattern** is often used to implement OCP.\n- **Framework Best Practices**: Laravel and Symfony implement OCP through middleware and service providers.\n- **OCP and Testing**: Easier to unit test since components are loosely coupled.\n\n### &#x2696; Trade-offs \n&#x2705; **Pros:**\n- **Flexibility** – OCP reduces modification risks in stable code.\n- **Test Stability** – Existing functionality remains unchanged.\n\n&#x274c; **Cons:**\n- **More Abstraction** – Using interfaces and dependency injection adds more classes.\n- **Overhead** – If the system will never change, adding interfaces might be unnecessary.\n- **YAGNI (You Aren’t Gonna Need It)** – Don’t over-engineer if new features are unlikely.\n\n### &#x1f4a1; Developer Hints \n&#x2705; Use **interfaces and abstract classes** to define extension points.\n&#x274c; Avoid **modifying stable, tested classes** unless absolutely necessary.\n&#x2705; Think **long-term scalability** before choosing rigid, hard-coded implementations.\n&#x274c; If a pattern **adds complexity but solves no problem**, you may not need it.\n\n---\n\n### &#x1f3c1; Conclusion \nA well-designed system should be adaptable to **future needs** without forcing developers to modify **working, tested code**. By leveraging **polymorphism, interfaces, and design patterns**, we achieve flexibility while maintaining stability. &#x1f680;\n\n---\n\n## Liskov Substitution Principle (LSP) - \&quot;Keep Your Promises\&quot;\n\n![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fw8atfuyc7tmyc0vvwz.png)\n(source: https://trekhleb.dev/blog/2017/solid-principles-around-you/)\n\n### &#x1f4da; Academic Definition \n\u003e **Objects in a program should be replaceable with instances of their subtypes without altering the correctness of the program.**\n\n### &#x1f3af; Our Definition \nIf a class (child) extends another class (parent), it should behave in a way that doesn’t break expectations set by the parent class. Any subclass should be usable in place of its superclass without unexpected behavior.\n\n### &#x1f4dd; Simple Definition \nA subclass should respect the promises made by its parent class. If you replace the parent class with a subclass, everything should still work correctly.\n\n---\n\n### &#x1f43e; Paw Patrol Analogy: The Special Snowplow Problem\nImagine the Paw Patrol vehicles. Each pup has their own special ride, but all of them **must be drivable**.\n\nNow imagine if Everest’s snowplow **couldn’t drive on roads** because it was only built for ice. If a mission required her to drive on a normal road, the system would break because her vehicle doesn’t meet the basic expectation of “being able to drive.”\n\nThat’s an LSP violation—her vehicle is a “subclass” of the general \&quot;Paw Patrol Vehicle,\&quot; but it doesn’t fully substitute for it in every situation.\n\n---\n\n### &#x1f9e0; Key Learnings \n1. **Child classes must respect the contract of their parent classes.**\n2. **Avoid violating expectations**—subclasses must behave consistently with their base class.\n3. **If a subclass has to override too much behavior**, it might not truly be a subtype and could indicate a bad inheritance choice.\n4. **LSP helps keep code predictable**—it prevents unexpected failures when replacing a base class with a subclass.\n\n---\n\n### Bad Example &#x1f6a8;: Violating LSP in PHP\n\n&#96;&#96;&#96;php\nclass Bird {\n    public function fly(): string {\n        return \&quot;I am flying!\&quot;;\n    }\n}\n\nclass Penguin extends Bird {\n    public function fly(): string {\n        throw new Exception(\&quot;I can't fly!\&quot;);\n    }\n}\n\nfunction makeBirdFly(Bird $bird) {\n    return $bird-\u003efly();\n}\n\n$penguin = new Penguin();\necho makeBirdFly($penguin); // &#x274c; Breaks expectation!\n&#96;&#96;&#96;\n\n&#x1f534; **Issue:** &#96;Penguin&#96; extends &#96;Bird&#96;, but it breaks the expectation that all birds can fly.\n\n---\n\n### &#x2705; Fixed Example: Using Interfaces to Respect LSP\n&#96;&#96;&#96;php\ninterface Bird {\n    public function eat(): string;\n}\n\ninterface FlyingBird extends Bird {\n    public function fly(): string;\n}\n\nclass Sparrow implements FlyingBird {\n    public function eat(): string {\n        return \&quot;I eat seeds.\&quot;;\n    }\n    public function fly(): string {\n        return \&quot;I can fly!\&quot;;\n    }\n}\n\nclass Penguin implements Bird {\n    public function eat(): string {\n        return \&quot;I eat fish.\&quot;;\n    }\n}\n\nfunction observeBird(Bird $bird) {\n    return $bird-\u003eeat();\n}\n\n$sparrow = new Sparrow();\n$penguin = new Penguin();\n\necho observeBird($sparrow); // &#x2705; Works fine!\necho observeBird($penguin); // &#x2705; Works fine!\n&#96;&#96;&#96;\n\n&#x1f7e2; **Fix:** Instead of forcing all birds to be able to fly, we separate \&quot;flying\&quot; behavior into a different interface. This way, penguins don’t have to pretend they can fly.\n\n---\n\n### &#x1f6d2; E-Commerce Example: The Free Shipping Issue\n#### Bad Example &#x1f6a8;: Breaking the Parent Contract\nImagine an order system where &#96;StandardOrder&#96; has a method &#96;getShippingCost()&#96;. A developer extends it for &#96;FreeShippingOrder&#96; but violates expectations:\n\n&#96;&#96;&#96;php\nclass StandardOrder {\n    public function getShippingCost(): float {\n        return 5.99;\n    }\n}\n\nclass FreeShippingOrder extends StandardOrder {\n    public function getShippingCost(): float {\n        throw new Exception(\&quot;This order has free shipping!\&quot;);\n    }\n}\n\nfunction processOrder(StandardOrder $order) {\n    return \&quot;Shipping Cost: \&quot; . $order-\u003egetShippingCost();\n}\n\n$order = new FreeShippingOrder();\necho processOrder($order); // &#x274c; Unexpected exception!\n&#96;&#96;&#96;\n\n&#x1f534; **Issue:** &#96;FreeShippingOrder&#96; breaks the contract by throwing an exception instead of returning a valid shipping cost.\n\n#### &#x2705; Fixed Example: Using a Different Approach\n&#96;&#96;&#96;php\ninterface Order {\n    public function getShippingCost(): float;\n}\n\nclass StandardOrder implements Order {\n    public function getShippingCost(): float {\n        return 5.99;\n    }\n}\n\nclass FreeShippingOrder implements Order {\n    public function getShippingCost(): float {\n        return 0.00;\n    }\n}\n\nfunction processOrder(Order $order) {\n    return \&quot;Shipping Cost: \&quot; . $order-\u003egetShippingCost();\n}\n\n$order = new FreeShippingOrder();\necho processOrder($order); // &#x2705; Outputs \&quot;Shipping Cost: 0.00\&quot;\n&#96;&#96;&#96;\n\n&#x1f7e2; **Fix:** Instead of forcing &#96;FreeShippingOrder&#96; to inherit from &#96;StandardOrder&#96;, we use an &#96;Order&#96; interface, ensuring all orders can return a shipping cost without surprises.\n\n---\n\n### &#x1f4cc; Advanced Insights &#x1f680;\n1. **LSP helps prevent bad inheritance hierarchies.** If you constantly override parent methods in a subclass, consider **composition** over inheritance.\n2. **Use Interfaces to enforce behavior contracts**—avoid forcing all child classes into behaviors they don’t support.\n3. **LSP violations often indicate design flaws.** If your subclass keeps breaking expectations, your class hierarchy may be wrong.\n4. **Invariance vs Covariance vs Contravariance:** Be mindful of how method parameters and return types evolve in subclasses.\n\n---\n\n### &#x2696; Trade-offs \n| &#x2705; **Pros** | &#x274c; **Cons** |\n|------------|------------|\n| Ensures subclasses don’t break existing code | May lead to extra abstraction layers |\n| Helps catch bad inheritance early | Too many interfaces can lead to complexity |\n| Makes extending systems easier | Sometimes inheritance is still the simpler choice |\n\n---\n\n### &#x1f4a1; Developer Hints \n&#x2705; **DO:** Use LSP to validate your class hierarchies—if a subclass must override too many methods, it’s likely a bad fit.\n\n&#x274c; **DON’T:** Inherit from a class just to \&quot;reuse\&quot; some methods—if the behaviors aren’t consistent, prefer composition.\n\n&#x2705; **DO:** Use interfaces and careful method contracts to ensure subclasses behave as expected.\n\n&#x274c; **DON’T:** Assume that \&quot;all X should do Y\&quot;—if exceptions exist, rethink your hierarchy.\n\n---\n\n### &#x1f3c1; Conclusion\nLiskov Substitution Principle ensures that subclasses can always stand in for their parent class **without surprises**. It’s one of the most overlooked SOLID principles but arguably one of the most important for keeping systems **extendable and predictable**.\n\nUse LSP to validate your class hierarchies. If your subclass **breaks expected behavior**, it's a sign you might need **a different inheritance model or composition instead**. Keep your promises, and your codebase will stay clean and maintainable!\n\n---\n\n## Interface Segregation Principle (ISP)\n\n![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2agpndrjv1t864f2lhjh.png)\n(source: https://trekhleb.dev/blog/2017/solid-principles-around-you/)\n\n### &#x1f4da; Academic Definition \n\u003e \&quot;Clients should not be forced to depend on methods they do not use.\&quot;\n\n### &#x1f3af; Our Definition \nInterfaces should be focused and granular, ensuring that implementing classes only need to adhere to methods that are relevant to them. This prevents classes from being bloated with unnecessary dependencies and improves code maintainability.\n\n### &#x1f4dd; Simple Definition \nDon't force a class to implement methods it doesn’t need.\n\n### &#x1f43e; Paw Patrol Analogy \nImagine all Paw Patrol pups had to follow the same \&quot;Rescue Operations\&quot; interface. That would mean Skye (the helicopter pup) would have to implement \&quot;Water Cannon Operation\&quot; even though she has no water cannons! Instead, it's better to have separate interfaces: one for fire rescue (Marshall) and one for aerial rescue (Skye). This ensures that each pup only implements the operations they actually perform.\n\n---\n\n### &#x1f9e0; Key Learnings \n&#x2705; Interfaces should be **focused** and **cohesive**—not overloaded with unrelated methods.\n&#x2705; Use **multiple small interfaces** instead of **one large interface**.\n&#x2705; Helps avoid unnecessary dependencies and improves modularity.\n&#x2705; Reduces the likelihood of implementing empty or throwaway methods.\n&#x2705; Works well with **Dependency Inversion Principle (DIP)** by defining specific contract expectations.\n\n---\n\n### &#x1f4cc; Advanced Insights &#x1f680;\n- **Granular Interfaces → Better Code Maintainability**: By keeping interfaces small, you prevent a ripple effect of unnecessary method changes in unrelated classes.\n- **Avoid Interface Pollution**: Large interfaces force implementing classes to define methods they don’t use, leading to bad design and unnecessary complexity.\n- **Natural Extension of SRP**: ISP is like SRP but at the interface level—ensuring each interface has a single, clear responsibility.\n- **Refactoring Legacy Code**: If you have bloated interfaces, split them into **cohesive, role-based interfaces**.\n- **Multiple Implementations**: You can mix and match smaller interfaces in various ways without forcing unrelated methods onto a class.\n\n---\n\n### Bad Example &#x1f6a8;: Bloated Interface\n&#96;&#96;&#96;php\ninterface Worker {\n    public function work(): void;\n    public function eat(): void;\n    public function sleep(): void;\n}\n\nclass Robot implements Worker {\n    public function work(): void {\n        echo \&quot;I am working!\&quot;;\n    }\n    public function eat(): void {\n        throw new Exception(\&quot;Robots don't eat!\&quot;);\n    }\n    public function sleep(): void {\n        throw new Exception(\&quot;Robots don't sleep!\&quot;);\n    }\n}\n&#96;&#96;&#96;\n&#x1f6a8; **Problem:** The &#96;Worker&#96; interface forces &#96;Robot&#96; to implement &#96;eat()&#96; and &#96;sleep()&#96;, which don’t make sense.\n\n---\n\n### Good Example: Segregated Interfaces &#x2705;\n&#96;&#96;&#96;php\ninterface Workable {\n    public function work(): void;\n}\n\ninterface HumanNeeds {\n    public function eat(): void;\n    public function sleep(): void;\n}\n\nclass Robot implements Workable {\n    public function work(): void {\n        echo \&quot;I am working!\&quot;;\n    }\n}\n\nclass HumanWorker implements Workable, HumanNeeds {\n    public function work(): void {\n        echo \&quot;Working hard!\&quot;;\n    }\n    public function eat(): void {\n        echo \&quot;Eating lunch.\&quot;;\n    }\n    public function sleep(): void {\n        echo \&quot;Going to sleep.\&quot;;\n    }\n}\n&#96;&#96;&#96;\n&#x2705; **Now each class only implements the methods it actually needs!**\n\n---\n\n### &#x1f6d2; E-Commerce Example \nImagine you have a large &#96;PaymentProcessor&#96; interface that forces all payment gateways (PayPal, Stripe, Bitcoin) to implement methods like &#96;refund()&#96; and &#96;chargeBack()&#96;, even if some gateways don’t support chargebacks.\n\n#### Bad Example &#x1f6a8;: Bloated Interface  \n&#96;&#96;&#96;php\ninterface PaymentProcessor {\n    public function processPayment(float $amount): void;\n    public function refund(float $amount): void;\n    public function chargeBack(float $amount): void;\n}\n\nclass BitcoinProcessor implements PaymentProcessor {\n    public function processPayment(float $amount): void {\n        echo \&quot;Processing Bitcoin payment.\&quot;;\n    }\n    public function refund(float $amount): void {\n        throw new Exception(\&quot;Bitcoin transactions are irreversible!\&quot;);\n    }\n    public function chargeBack(float $amount): void {\n        throw new Exception(\&quot;Bitcoin has no chargebacks!\&quot;);\n    }\n}\n&#96;&#96;&#96;\n&#x274c; **Problem:** Bitcoin does not support refunds or chargebacks, yet it’s forced to implement these methods.\n\n#### Segregated Interfaces (Good Example) &#x2705;\n&#96;&#96;&#96;php\ninterface PaymentProcessor {\n    public function processPayment(float $amount): void;\n}\n\ninterface Refundable {\n    public function refund(float $amount): void;\n}\n\ninterface Chargebackable {\n    public function chargeBack(float $amount): void;\n}\n\nclass BitcoinProcessor implements PaymentProcessor {\n    public function processPayment(float $amount): void {\n        echo \&quot;Processing Bitcoin payment.\&quot;;\n    }\n}\n\nclass CreditCardProcessor implements PaymentProcessor, Refundable, Chargebackable {\n    public function processPayment(float $amount): void {\n        echo \&quot;Processing Credit Card payment.\&quot;;\n    }\n    public function refund(float $amount): void {\n        echo \&quot;Processing refund.\&quot;;\n    }\n    public function chargeBack(float $amount): void {\n        echo \&quot;Processing chargeback.\&quot;;\n    }\n}\n&#96;&#96;&#96;\n&#x2705; **Now, Bitcoin only implements &#96;PaymentProcessor&#96;, and Credit Card processors can add &#96;Refundable&#96; and &#96;Chargebackable&#96;.**\n\n---\n\n### &#x2696; Trade-offs \n&#x2705; **Pros:**\n- Prevents unnecessary dependencies.\n- Improves readability and maintainability.\n- Easier to refactor without breaking implementations.\n- Better aligns with the **Single Responsibility Principle (SRP)**.\n\n&#x274c; **Cons:**\n- Can lead to **too many** small interfaces.\n- Requires **careful naming** to keep interfaces meaningful.\n- Might **increase boilerplate** in some cases.\n\n---\n\n### &#x1f4a1; Developer Hints \n&#x2705; **Split interfaces when:**\n- A class is implementing empty methods.\n- A class throws exceptions for methods it doesn’t support.\n- A method is only used in **some** implementations but not others.\n\n&#x2705; **Keep interfaces meaningful:**\n- Don't over-fragment interfaces into tiny, meaningless pieces.\n- A good rule: If **two implementations always share the same methods**, keep them together.\n\n&#x2705; **Use with Dependency Injection:**\n- Granular interfaces make **Dependency Injection (DI)** much cleaner.\n\n---\n\n### &#x1f3c1; Conclusion\nInterface Segregation ensures that interfaces stay clean and meaningful. Instead of bloated, one-size-fits-all contracts, ISP encourages **focused, role-specific interfaces** that keep classes lean and purposeful. By following ISP, you create software that is **modular, easy to extend, and avoids unnecessary coupling**.\n\nBy embracing ISP, your codebase stays **flexible, maintainable, and scalable**—just like a well-organized Paw Patrol team! &#x1f680;&#x1f436;\n\n---\n\n## Dependency Inversion Principle (DIP)\n\n![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ad1eyh2ilp1exhm9p31d.png)\n(source: https://trekhleb.dev/blog/2017/solid-principles-around-you/)\n\n### &#x1f4da; Academic Definition \n\u003e **High-level modules should not depend on low-level modules. Both should depend on abstractions.**\n\u003e\n\u003e **Abstractions should not depend on details. Details should depend on abstractions.**\n\n### &#x1f3af; Our Definition \nDIP ensures that **core logic (high-level modules)** does not directly depend on **specific implementations (low-level modules)**. Instead, both depend on a common **interface or abstraction**.\n\n### &#x1f4dd; Simple Definition\nInstead of hardcoding dependencies, rely on **interfaces** or **dependency injection** to allow for easier maintenance, testing, and swapping implementations.\n\n### &#x1f43e; Paw Patrol Analogy \nImagine **Ryder**, the leader of Paw Patrol, who needs a pup for a rescue mission. Instead of calling **Chase** directly, he calls for a \&quot;Police Pup.\&quot; This allows **Chase** to respond, but if another police dog joins the team, he can step in without changing Ryder’s commands.\n\nBy coding to an **abstraction (\&quot;Police Pup\&quot;)** instead of a **concrete implementation (\&quot;Chase\&quot;)**, Ryder ensures flexibility.\n\n---\n\n### &#x1f9e0; Key Learnings \n1&#x20e3; **High-Level Modules (Core Logic) Should Not Depend on Low-Level Modules (Implementations)**  \n   - Example: An &#96;OrderService&#96; should not directly depend on &#96;MySQLDatabase&#96; but instead on &#96;DatabaseInterface&#96;.\n\n2&#x20e3; **Abstractions Should Not Depend on Details**  \n   - The interface should define behavior, not implementation details.\n\n3&#x20e3; **Use Dependency Injection for Flexibility**  \n   - Instead of creating objects inside a class (&#96;new MySQLDatabase()&#96;), pass them as dependencies (&#96;DatabaseInterface $db&#96;).\n\n4&#x20e3; **Promotes Testing and Maintainability**  \n   - Easily mock dependencies in unit tests by swapping implementations.\n\n---\n\n### Simple Example (Violating DIP)\n#### Bad Example &#x1f6a8;: Hardcoded Dependency\n&#96;&#96;&#96;php\nclass MySQLDatabase {\n    public function getUser(int $id): string {\n        return \&quot;User data from MySQL\&quot;;\n    }\n}\n\nclass UserService {\n    private MySQLDatabase $database;\n    \n    public function __construct() {\n        $this-\u003edatabase = new MySQLDatabase();\n    }\n    \n    public function getUser(int $id): string {\n        return $this-\u003edatabase-\u003egetUser($id);\n    }\n}\n&#96;&#96;&#96;\n&#x1f4a5; **Problem:** If we switch to &#96;PostgreSQLDatabase&#96;, we must modify &#96;UserService&#96;, violating DIP.\n\n---\n\n### The Fix: Applying DIP\n#### &#x2705; Good Example: Using an Interface\n&#96;&#96;&#96;php\ninterface DatabaseInterface {\n    public function getUser(int $id): string;\n}\n\nclass MySQLDatabase implements DatabaseInterface {\n    public function getUser(int $id): string {\n        return \&quot;User data from MySQL\&quot;;\n    }\n}\n\nclass PostgreSQLDatabase implements DatabaseInterface {\n    public function getUser(int $id): string {\n        return \&quot;User data from PostgreSQL\&quot;;\n    }\n}\n\nclass UserService {\n    private DatabaseInterface $database;\n    \n    public function __construct(DatabaseInterface $database) {\n        $this-\u003edatabase = $database;\n    }\n    \n    public function getUser(int $id): string {\n        return $this-\u003edatabase-\u003egetUser($id);\n    }\n}\n\n// Usage\n$service = new UserService(new MySQLDatabase());\n$service = new UserService(new PostgreSQLDatabase());\n&#96;&#96;&#96;\n&#x2705; **Now &#96;UserService&#96; does not depend on a specific database but on &#96;DatabaseInterface&#96;**, making it flexible.\n\n---\n\n### &#x1f6d2; E-Commerce Example \n#### Bad Example &#x1f6a8;: Hardcoded Payment Processor\n&#96;&#96;&#96;php\nclass PaymentService {\n    private StripePaymentProcessor $processor;\n    \n    public function __construct() {\n        $this-\u003eprocessor = new StripePaymentProcessor();\n    }\n    \n    public function processPayment(float $amount) {\n        return $this-\u003eprocessor-\u003epay($amount);\n    }\n}\n&#96;&#96;&#96;\n&#x1f4a5; **Issue:** Tied to Stripe; hard to replace with PayPal.\n\n#### &#x2705; Good Example (DIP with Interfaces)\n&#96;&#96;&#96;php\ninterface PaymentProcessor {\n    public function pay(float $amount): bool;\n}\n\nclass StripePaymentProcessor implements PaymentProcessor {\n    public function pay(float $amount): bool {\n        return true; // Process payment via Stripe\n    }\n}\n\nclass PayPalPaymentProcessor implements PaymentProcessor {\n    public function pay(float $amount): bool {\n        return true; // Process payment via PayPal\n    }\n}\n\nclass PaymentService {\n    private PaymentProcessor $processor;\n    \n    public function __construct(PaymentProcessor $processor) {\n        $this-\u003eprocessor = $processor;\n    }\n    \n    public function processPayment(float $amount) {\n        return $this-\u003eprocessor-\u003epay($amount);\n    }\n}\n\n// Usage\n$paymentService = new PaymentService(new StripePaymentProcessor());\n$paymentService = new PaymentService(new PayPalPaymentProcessor());\n&#96;&#96;&#96;\n&#x2705; Now the service works with **any** payment processor.\n\n---\n\n### &#x1f4cc; Advanced Insights &#x1f680;\n&#x2705; **IoC Containers (Dependency Injection Containers)**  \nModern frameworks (Laravel, Symfony) use IoC containers to **bind interfaces to implementations**, automating dependency resolution.\n&#96;&#96;&#96;php\n$container-\u003ebind(PaymentProcessor::class, StripePaymentProcessor::class);\n$paymentService = $container-\u003emake(PaymentService::class);\n&#96;&#96;&#96;\n\n&#x2705; **Easier Unit Testing**  \nBy injecting dependencies, you can mock them in tests:\n&#96;&#96;&#96;php\n$mockProcessor = $this-\u003ecreateMock(PaymentProcessor::class);\n$mockProcessor-\u003emethod('pay')-\u003ewillReturn(true);\n$service = new PaymentService($mockProcessor);\n$this-\u003eassertTrue($service-\u003eprocessPayment(100));\n&#96;&#96;&#96;\n\n---\n\n### &#x2696; Trade-offs \n1&#x20e3; **Over-Abstraction**: Too many interfaces can complicate simple cases.\n2&#x20e3; **Initial Setup Overhead**: More upfront work vs. hardcoding dependencies.\n3&#x20e3; **Not Always Needed**: Small scripts may not benefit from DIP.\n4&#x20e3; **Performance**: Extra layers add slight performance costs.\n\n---\n\n### &#x1f4a1; Developer Hints \n&#x1f680; **Use interfaces when multiple implementations are possible.**\n&#x1f6e0; **If a dependency rarely changes, DIP might be unnecessary overhead.**\n&#x1f504; **Combine with IoC containers for better dependency management.**\n\n---\n\n### &#x1f3c1; Conclusion\nDIP helps create flexible, scalable, and testable code. While overusing it can lead to unnecessary complexity, applying it where appropriate **ensures long-term maintainability and adaptability**.\n\n---\n\n**Learnings and Findings from the Blog Post**\n\n---\n\n## **The Essence of SOLID Beyond Textbook Definitions**\n\nWe have consistently moved beyond simply memorizing the SOLID principles. Instead, we have deeply examined their real-world applications, trade-offs, and potential misuses. The key insight is that SOLID is not a rigid framework but a set of guiding principles that, when applied pragmatically, result in **maintainable, flexible, and understandable** software.\n\n### **What We Learned:**\n1&#x20e3; SOLID **is a means, not an end**—it should improve software, not be followed blindly.\n2&#x20e3; Principles should **evolve naturally** with software needs rather than being enforced prematurely.\n3&#x20e3; **Balance is key**: applying SOLID too rigidly can introduce unnecessary complexity, while ignoring it leads to unmanageable abstractions.\n4&#x20e3; Naming and categorization of abstract concepts help communicate intent and keep teams aligned.\n\n---\n\n### &#x1f504; **SOLID Principles Recap**\nEach principle is a tool to write better, maintainable, and scalable software. While following them strictly isn’t always necessary, understanding them deeply allows you to make informed trade-offs when designing software.\n\n#### 1&#x20e3; **Single Responsibility Principle** (SRP)\n&#x1f4cc; **Rule**: A class should only have one reason to change.\n&#x2705; **Benefit**: Reduces complexity and improves maintainability.\n&#x26a0; **Pitfall**: Over-applying SRP can create too many small classes.\n\n#### 2&#x20e3; **Open-Closed Principle** (OCP)\n&#x1f4cc; **Rule**: Code should be open for extension but closed for modification.\n&#x2705; **Benefit**: Prevents modifying stable, tested code when adding new features.\n&#x26a0; **Pitfall**: Over-abstraction can make code difficult to understand.\n\n#### 3&#x20e3; **Liskov Substitution Principle** (LSP)\n&#x1f4cc; **Rule**: Subtypes must be substitutable for their base types.\n&#x2705; **Benefit**: Ensures a predictable, bug-free inheritance structure.\n&#x26a0; **Pitfall**: Violations often happen when child classes break parent contracts.\n\n#### 4&#x20e3; **Interface Segregation Principle** (ISP)\n&#x1f4cc; **Rule**: No class should be forced to depend on methods it does not use.\n&#x2705; **Benefit**: Creates leaner, more reusable interfaces.\n&#x26a0; **Pitfall**: Too many interfaces can create confusion or interface bloat.\n\n#### 5&#x20e3; **Dependency Inversion Principle** (DIP)\n&#x1f4cc; **Rule**: Depend on abstractions, not concrete implementations.\n&#x2705; **Benefit**: Encourages decoupled, flexible, and testable code.\n&#x26a0; **Pitfall**: Overuse can lead to too many indirections, making debugging harder.\n\n---\n\n## **Abstractions: When to Generalize and When to Copy-Paste**\n\n![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ldgeihlz2loa3hbsx9if.png)\n(source: https://www.reddit.com/r/Design/comments/6qh8ni/the_abstractometer/)\n\nThe Abstract-o-Meter reminds us that effective software design lies in finding the balance between clarity and usability. Every abstraction should:\n* Hide unnecessary details, making systems easier to understand.\n* Preserve essential clarity, ensuring they remain relevant to the real-world domain.\n\nWhether you’re designing a small utility class or architecting a large-scale system, always aim for the heart in the middle of the Abstract-o-Meter. This is the area where your abstractions remain meaningful, useful and maintainable, and only then will other developers actually use them.\n\nOne of the most significant learning is about **the right time to introduce abstractions** versus when copy-pasting is actually preferable. The classic fear of duplication (\&quot;DRY principle\&quot;) must be balanced with **avoiding premature abstractions** that introduce unnecessary coupling and complexity.\n\n### **Key Takeaways:**\n1&#x20e3; **Duplication is often cheaper** than the wrong abstraction.\n2&#x20e3; Generalization should be based on **real-world observed repetition**, not speculative future needs.\n3&#x20e3; Over-abstraction leads to **hard-to-read, bloated code** where understanding business rules requires digging through multiple indirections.\n4&#x20e3; High **cohesion and minimal dependencies** should be prioritized when designing abstractions.\n\n#### **Pragmatic Rule of Thumb:**\n- First occurrence? **Write it.**\n- Second occurrence? **Copy it.**\n- Third occurrence? **Consider abstraction—but validate first.**\n\n---\n\n## **Naming and Conceptual Thinking: The \&quot;Front Garden\&quot; and \&quot;Neighborhood\&quot; Metaphors**\n\nWe explored how defining abstract **conceptual names** improves communication. The **Front Garden** and **Neighborhood** analogy illustrated the power of naming in programming and software architecture:\n- By naming **broad categories of problems**, we create **reusable mental models** that allow easier discussions.\n- Instead of explaining every case separately, we can **define an abstract concept** (like \&quot;OCP Violation\&quot; or \&quot;Front Garden Boundary\&quot;) and use it as shorthand.\n- **Rules should be flexible principles**, not rigid constraints—much like in software, where strict application of SOLID without context leads to over-engineering.\n\n---\n\n## **The \&quot;SOLID but Practical\&quot; Mindset: Knowing When to Bend the Rules**\n\nThroughout our discussions, a recurring theme was **pragmatism over dogma**. Many developers apply SOLID too rigidly, causing unnecessary complexity. The real mastery lies in knowing when to **intentionally** bend or break the rules **for the right reasons**.\n\n### **Key Lessons:**\n- **SRP (Single Responsibility Principle)**: Some responsibilities can be combined if they always change together.\n- **OCP (Open-Closed Principle)**: Sometimes modifying a class is more maintainable than excessive abstractions.\n- **LSP (Liskov Substitution Principle)**: If a subclass needs excessive modifications, reconsider the inheritance structure.\n- **ISP (Interface Segregation Principle)**: Avoid creating too many interfaces that fragment business logic.\n- **DIP (Dependency Inversion Principle)**: Use abstractions but avoid forcing yourself to abstract every dependency.\n\n---\n\n## **Final Thought: The \&quot;Future-Proof\&quot; Developer Mindset**\n\n- **Principles exist to serve the software, not the other way around.**\n- **Code should evolve naturally**, following real needs instead of speculative complexity.\n- **Naming is critical**, not just for variables but for abstract concepts that help us discuss software design effectively.\n- **Abstractions are a tool**, not a requirement—sometimes, copy-pasting is the best decision.\n- **Balance pragmatism with best practices**, and don’t fear breaking SOLID rules **if it makes the code better**.\n\nBy combining **deep technical knowledge** with **practical experience**, we can write software that is both maintainable and efficient—without falling into the traps of over-engineering or unnecessary complexity. Happy coding!\n\n\n\n\n&quot;,&quot;organization_id&quot;:null,&quot;canonical_url&quot;:null,&quot;cached_tag_list&quot;:&quot;programming, softwaredevelopment, php, coding&quot;,&quot;series&quot;:null,&quot;all_series&quot;:[]}" data-organizations="[]" data-version="v1" data-site-logo="&lt;a href=&quot;/&quot; class=&quot;site-logo&quot; aria-label=&quot;DEV Community Home&quot;&gt;
    &lt;img class=&quot;site-logo__img&quot;
         src=&quot;https://media2.dev.to/dynamic/image/quality=100/https://dev-to-uploads.s3.amazonaws.com/uploads/logos/resized_logo_UQww2soKuUsjaOGNB38o.png&quot;
         style=&quot;aspect-ratio: 10 / 8&quot;
         alt=&quot;DEV Community&quot;&gt;
&lt;/a&gt;
" data-cover-image-height="420" data-cover-image-crop="crop" data-scheduling-enabled="true"><form id="article-form" class="crayons-article-form" aria-label="Edit post">
<div class="crayons-article-form__content crayons-card">
<article class="crayons-article">
<div class="crayons-article__main">
<div class="crayons-article__body text-styles">
<p>The <strong>SOLID</strong> principles are essential guidelines for writing clean, maintainable, and scalable software. While many developers can recite them, real-world applications often struggle with their correct implementation.</p>
<p>Understanding SOLID is not just about memorizing definitions; it&#8217;s about knowing when and how to apply them effectively. Sometimes, following the rules strictly can lead to unnecessary complexity, while a pragmatic approach ensures maintainability without over-engineering.</p>
<p>In this guide, we will break down each principle with practical <strong>PHP examples</strong>, <strong>Paw Patrol analogies</strong> for clarity, and <strong>trade-offs</strong> to consider. By the end, you’ll have a solid understanding of how these principles work together and when it&#8217;s okay to bend them for the greater good.</p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#the-front-garden-amp-neighborhood-metaphor-why-naming-principles-matter" name="the-front-garden-amp-neighborhood-metaphor-why-naming-principles-matter"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3e1.png" alt="🏡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> The &#8220;Front Garden&#8221; &amp; &#8220;Neighborhood&#8221; Metaphor: Why Naming Principles Matter</h2>
<p>Imagine you don’t even know what “neighbor” or “front garden” means. Someone tries to explain that you shouldn’t walk through someone else’s garden, so they define these terms and create a rule. But that rule would be rigid and limiting.</p>
<p>Instead, we define a broad principle that covers many similar scenarios, giving it a name so others immediately understand what we mean. This flexibility allows us to apply it beyond just neighbors and gardens while recognizing exceptions—like if the garden is yours or there’s an emergency.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#how-this-relates-to-solid" name="how-this-relates-to-solid"></a>How This Relates to SOLID</h3>
<p>Similarly, SOLID is a set of abstract principles that define boundaries in object-oriented code. By naming these boundaries (SRP, OCP, LSP, ISP, DIP), we gain:</p>
<p>1&#x20e3; <strong>Efficient Communication</strong> – We can say, “We’re violating OCP,” instead of explaining, “We keep re-editing stable code to add new features.”</p>
<p>2&#x20e3; <strong>Unified Understanding</strong> – Whether human developers or AI-powered coding assistants, everyone recognizes the same underlying problem without a lengthy breakdown.</p>
<p>3&#x20e3; <strong>Flexible Exceptions</strong> – Sometimes, crossing that fence is practical (if it’s your own “garden”) or necessary (in an emergency).</p>
<p>Knowing these principles allows developers to make <strong>intentional trade-offs</strong>, rather than blindly applying or ignoring them.</p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#how-to-apply-solid-without-overengineering" name="how-to-apply-solid-without-overengineering"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> How to Apply SOLID Without Over-Engineering</h2>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#apply-solid-as-needed-not-as-a-dogma" name="apply-solid-as-needed-not-as-a-dogma"></a>1&#x20e3; Apply SOLID as Needed, Not as a Dogma</h3>
<ul>
<li>If a class is simple &amp; works, don’t force an interface just to follow DIP.</li>
<li>If a method is naturally cohesive, don’t split it just to follow SRP.</li>
<li>If an interface is only used once, don’t extract it just for ISP.</li>
<li><strong>Code should be SOLID but also simple.</strong></li>
</ul>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#focus-on-refactoring-not-preemptive-complexity" name="focus-on-refactoring-not-preemptive-complexity"></a>2&#x20e3; Focus on Refactoring, Not Preemptive Complexity</h3>
<ul>
<li>Refactor SOLID in steps <strong>when a problem arises</strong>.</li>
<li>Don’t create an abstraction until <strong>you actually need it</strong>.</li>
</ul>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#use-the-8020-rule" name="use-the-8020-rule"></a>3&#x20e3; Use the 80/20 Rule</h3>
<ul>
<li><strong>80%</strong> of your code should be pragmatic and <strong>only 20%</strong> should be deeply abstracted for maintainability.</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Example:</strong></p>
<ul>
<li>An <strong>order processing system</strong> needs flexibility (<strong>high SOLID compliance</strong>).</li>
<li>A <strong>CLI script that runs once a year</strong>? No need for extreme abstractions.</li>
</ul>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#know-when-to-break-the-rules-intentionally" name="know-when-to-break-the-rules-intentionally"></a>4&#x20e3; Know When to Break the Rules (Intentionally)</h3>
<ul>
<li>It’s okay to <strong>violate SRP</strong> if it keeps your code readable and practical.</li>
<li>Sometimes <strong>direct dependencies (instead of DIP)</strong> make sense for small projects.</li>
<li>Some classes might benefit from breaking <strong>OCP</strong> if modifying them improves clarity.</li>
</ul>
<p>By the end of this guide, you’ll <strong>not only understand SOLID</strong> but also <strong>when to apply it pragmatically</strong>—allowing your architecture to evolve gracefully without unnecessary complexity.</p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#single-responsibility-principle-srp" name="single-responsibility-principle-srp"></a>Single Responsibility Principle (SRP)</h2>
<p><a class="article-body-image-wrapper" href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlby1sbe8xgmna1tazv0.png"><img decoding="async" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlby1sbe8xgmna1tazv0.png" alt="Image description" /></a><br />(source: <a href="https://trekhleb.dev/blog/2017/solid-principles-around-you/" target="_blank" rel="noopener noreferrer">https://trekhleb.dev/blog/2017/solid-principles-around-you/</a>)</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#academic-definition" name="academic-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Academic Definition</h3>
<blockquote>
<p>&#8220;A class should have only one reason to change.&#8221;<br />— Robert C. Martin (Uncle Bob)</p>
</blockquote>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#our-definition" name="our-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Our Definition</h3>
<p>A class should only do <strong>one thing well</strong> and not be responsible for multiple unrelated concerns.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#simple-definition" name="simple-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9d1-200d-1f4bb.png" alt="🧑‍💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Simple Definition</h3>
<p>Each class should <strong>focus on a single task</strong> or responsibility. If a class has multiple reasons to change, it likely violates SRP.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#paw-patrol-analogy" name="paw-patrol-analogy"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f43e.png" alt="🐾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Paw Patrol Analogy</h3>
<p>Think of <strong>Paw Patrol</strong>:</p>
<ul>
<li><strong>Chase</strong> handles police duties <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f693.png" alt="🚓" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
<li><strong>Marshall</strong> fights fires <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f692.png" alt="🚒" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
<li><strong>Skye</strong> flies helicopters <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f681.png" alt="🚁" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
</ul>
<p>Imagine if Skye had to drive the police car and fight fires too—it would be <strong>chaotic</strong>! The same applies to software: one class should not do <strong>everything</strong>.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#key-learnings" name="key-learnings"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Key Learnings</h3>
<p>1&#x20e3; <strong>Identify &#8220;Axes of Change&#8221;</strong> → If multiple teams request changes to the same class for different reasons, it&#8217;s violating SRP.<br />2&#x20e3; <strong>Avoid &#8220;God Classes&#8221;</strong> → Large classes handling everything lead to <strong>maintenance nightmares</strong>.<br />3&#x20e3; <strong>Encapsulation &amp; Separation</strong> → Keep concerns <strong>independent</strong> to improve testability and flexibility.<br />4&#x20e3; <strong>Avoid Premature Splitting</strong> → If a class is small and cohesive, don&#8217;t split it <strong>just because</strong>—follow <strong>YAGNI</strong> (You Ain&#8217;t Gonna Need It).</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#simple-example-violating-srp" name="simple-example-violating-srp"></a>Simple Example (Violating SRP)</h3>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example-too-many-responsibilities" name="bad-example-too-many-responsibilities"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" />: Too Many Responsibilities</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">ProfileManager</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">authenticateUser</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">,</span> <span class="kt">string</span> <span class="nv">$password</span><span class="p">):</span> <span class="kt">bool</span> <span class="p">{</span>
        <span class="c1">// Auth logic here</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">showUserProfile</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">):</span> <span class="kt">UserProfile</span> <span class="p">{</span>
        <span class="c1">// Display user profile logic</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">updateUserProfile</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">,</span> <span class="kt">array</span> <span class="nv">$data</span><span class="p">):</span> <span class="kt">UserProfile</span> <span class="p">{</span>
        <span class="c1">// Update logic</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">setUserPermissions</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">,</span> <span class="kt">array</span> <span class="nv">$permissions</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="c1">// Set permissions logic</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f534.png" alt="🔴" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Why is this bad?</strong></p>
<ul>
<li>Mixed responsibilities: Authentication, Profile Display, Profile Update, and Permissions <strong>should not</strong> be in one class.</li>
</ul>
<p><strong>Scenario</strong>:</p>
<ul>
<li>HR wants new fields for user profiles.</li>
<li>IT wants multi-factor authentication.</li>
</ul>
<p>Both modifications collide in a single class.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fixed Version</strong></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">AuthenticationService</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">authenticateUser</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">,</span> <span class="kt">string</span> <span class="nv">$password</span><span class="p">):</span> <span class="kt">bool</span> <span class="p">{</span>
        <span class="c1">// Authentication logic</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">UserProfileService</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">showUserProfile</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">):</span> <span class="kt">UserProfile</span> <span class="p">{</span>
        <span class="c1">// Fetch user profile</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">updateUserProfile</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">,</span> <span class="kt">array</span> <span class="nv">$data</span><span class="p">):</span> <span class="kt">UserProfile</span> <span class="p">{</span>
        <span class="c1">// Update user profile</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">PermissionService</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">setUserPermissions</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$username</span><span class="p">,</span> <span class="kt">array</span> <span class="nv">$permissions</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="c1">// Set user permissions</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Now, each class has only one responsibility!</strong></p>
<p>And each domain can now evolves independently, so this is often not just a technical decision, but also an organizational one.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#ecommerce-example" name="ecommerce-example"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6d2.png" alt="🛒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> E-Commerce Example</h3>
<p>Imagine an <strong>OrderProcessor</strong> handling:</p>
<ul>
<li>Payment processing</li>
<li>Shipping details</li>
<li>Generating invoices</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Bad Example</strong></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">OrderProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">PaymentDetails</span> <span class="nv">$payment</span><span class="p">):</span> <span class="kt">bool</span> <span class="p">{</span> <span class="cm">/* Payment logic */</span> <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">generateInvoice</span><span class="p">(</span><span class="kt">Order</span> <span class="nv">$order</span><span class="p">):</span> <span class="kt">Invoice</span> <span class="p">{</span> <span class="cm">/* Invoice logic */</span> <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">arrangeShipping</span><span class="p">(</span><span class="kt">Order</span> <span class="nv">$order</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span> <span class="cm">/* Shipping logic */</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f534.png" alt="🔴" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Why is this bad?</strong></p>
<ul>
<li>If shipping logic changes, you need to modify OrderProcessor.</li>
<li>If invoicing logic changes, same problem!</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fixed Version</strong></p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">PaymentService</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">PaymentDetails</span> <span class="nv">$payment</span><span class="p">):</span> <span class="kt">bool</span> <span class="p">{</span> <span class="cm">/* Payment logic */</span> <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">InvoiceService</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">generateInvoice</span><span class="p">(</span><span class="kt">Order</span> <span class="nv">$order</span><span class="p">):</span> <span class="kt">Invoice</span> <span class="p">{</span> <span class="cm">/* Invoice logic */</span> <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">ShippingService</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">arrangeShipping</span><span class="p">(</span><span class="kt">Order</span> <span class="nv">$order</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span> <span class="cm">/* Shipping logic */</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Each service has one responsibility!</strong></p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#advanced-insights" name="advanced-insights"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Advanced Insights <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<ul>
<li><strong>Cohesion vs. Fragmentation</strong> → Don&#8217;t split classes <strong>too much</strong>. Keep things <strong>cohesive</strong>.</li>
<li><strong>Testability</strong> → Small, single-responsibility classes are easier to <strong>unit test</strong>.</li>
<li><strong>Microservices &amp; Modular Design</strong> → SRP is key in both microservices and modular monoliths.</li>
<li><strong>Database Layer</strong> → If you see <strong>fat repositories</strong>, it might be a sign of SRP violation.</li>
</ul>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#tradeoffs" name="tradeoffs"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2696.png" alt="⚖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Trade-offs</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pros:</strong></p>
<ul>
<li>Easier maintenance</li>
<li>Better testability</li>
<li>More flexibility for future changes</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Cons:</strong></p>
<ul>
<li>Can introduce <strong>too many</strong> small classes if overused</li>
<li>Might feel like &#8220;over-engineering&#8221; for small projects</li>
</ul>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#developer-hints" name="developer-hints"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Developer Hints</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Ask yourself:</strong> &#8220;Does this class have more than one reason to change?&#8221; If yes → <strong>SRP violation!</strong><br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Refactor when needed</strong> → If a class is too big, break it <strong>only when necessary</strong>.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Think in modules</strong> → Group related logic in separate <strong>services</strong>.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#conclusion" name="conclusion"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3c1.png" alt="🏁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Conclusion</h3>
<p>The <strong>Single Responsibility Principle</strong> is a fundamental but often misused principle. It&#8217;s about <strong>finding the right balance</strong> between <strong>cohesion</strong> and <strong>separation</strong>. When applied correctly, it leads to <strong>more maintainable</strong>, <strong>testable</strong>, and <strong>scalable</strong> software.</p>
<p>The key takeaway? <strong>SRP is not about splitting everything—it’s about ensuring a class has a single, well-defined purpose!</strong> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#openclosed-principle-ocp" name="openclosed-principle-ocp"></a>Open-Closed Principle (OCP)</h2>
<p><a class="article-body-image-wrapper" href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdapoj2x076c0yq7dy1o4.png"><img decoding="async" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdapoj2x076c0yq7dy1o4.png" alt="Image description" /></a><br />(source: <a href="https://trekhleb.dev/blog/2017/solid-principles-around-you/" target="_blank" rel="noopener noreferrer">https://trekhleb.dev/blog/2017/solid-principles-around-you/</a>)</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#academic-definition" name="academic-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Academic Definition</h3>
<p>&#8220;Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.&#8221; — Bertrand Meyer</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#our-definition" name="our-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Our Definition</h3>
<p>Your code should be designed in a way that allows adding new features <strong>without modifying</strong> the existing, stable code.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#simple-definition" name="simple-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4dd.png" alt="📝" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Simple Definition</h3>
<p>Instead of changing old code every time a new feature is needed, structure your code so that you can extend it <strong>without altering</strong> what already works.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#paw-patrol-analogy" name="paw-patrol-analogy"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f43e.png" alt="🐾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Paw Patrol Analogy</h3>
<p>When <strong>Everest</strong> joined the Paw Patrol for snow rescues <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3d4.png" alt="🏔" class="wp-smiley" style="height: 1em; max-height: 1em;" />, none of the existing pups needed modification. The team was <strong>extended</strong>, not changed.</p>
<p>Likewise, <strong>new features</strong> should be added as <strong>extensions</strong>, not by modifying existing code.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#key-learnings" name="key-learnings"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Key Learnings</h3>
<p>1&#x20e3; <strong>Open for Extension</strong> – Your code should be designed in a way that allows you to add new functionality without touching the existing logic.<br />2&#x20e3; <strong>Closed for Modification</strong> – Existing code should remain unchanged to prevent introducing new bugs.<br />3&#x20e3; <strong>Use Abstraction</strong> – Utilize interfaces, abstract classes, or dependency injection to allow new behavior without modifying core logic.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#common-mistake-example" name="common-mistake-example"></a>Common Mistake Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">AreaCalculator</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">calculateTotalArea</span><span class="p">(</span><span class="kt">array</span> <span class="nv">$shapes</span><span class="p">):</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="nv">$totalArea</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">foreach</span> <span class="p">(</span><span class="nv">$shapes</span> <span class="k">as</span> <span class="nv">$shape</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="nv">$shape</span> <span class="k">instanceof</span> <span class="nc">Circle</span><span class="p">)</span> <span class="p">{</span>
                <span class="nv">$totalArea</span> <span class="o">+=</span> <span class="nb">pi</span><span class="p">()</span> <span class="o">*</span> <span class="nv">$shape</span><span class="o">-&gt;</span><span class="n">radius</span> <span class="o">**</span> <span class="mi">2</span><span class="p">;</span>
            <span class="p">}</span> <span class="k">elseif</span> <span class="p">(</span><span class="nv">$shape</span> <span class="k">instanceof</span> <span class="nc">Square</span><span class="p">)</span> <span class="p">{</span>
                <span class="nv">$totalArea</span> <span class="o">+=</span> <span class="nv">$shape</span><span class="o">-&gt;</span><span class="n">sideLength</span> <span class="o">**</span> <span class="mi">2</span><span class="p">;</span>
            <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="nv">$totalArea</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Problem:</strong> Every time a new shape (e.g., <code>Triangle</code>) is introduced, this class needs modification, violating OCP.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#the-fix" name="the-fix"></a>The Fix <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#using-the-strategy-pattern" name="using-the-strategy-pattern"></a>Using the Strategy Pattern</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">Shape</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">calculateArea</span><span class="p">():</span> <span class="kt">float</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Circle</span> <span class="kd">implements</span> <span class="nc">Shape</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="k">private</span> <span class="kt">float</span> <span class="nv">$radius</span><span class="p">)</span> <span class="p">{}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">calculateArea</span><span class="p">():</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nb">pi</span><span class="p">()</span> <span class="o">*</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">radius</span> <span class="o">**</span> <span class="mi">2</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Square</span> <span class="kd">implements</span> <span class="nc">Shape</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="k">private</span> <span class="kt">float</span> <span class="nv">$sideLength</span><span class="p">)</span> <span class="p">{}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">calculateArea</span><span class="p">():</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">sideLength</span> <span class="o">**</span> <span class="mi">2</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">AreaCalculator</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">calculateTotalArea</span><span class="p">(</span><span class="kt">array</span> <span class="nv">$shapes</span><span class="p">):</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nb">array_sum</span><span class="p">(</span><span class="nb">array_map</span><span class="p">(</span>
            <span class="k">fn</span><span class="p">(</span><span class="kt">Shape</span> <span class="nv">$shape</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nv">$shape</span><span class="o">-&gt;</span><span class="nf">calculateArea</span><span class="p">(),</span>
            <span class="nv">$shapes</span>
        <span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#why-is-this-better" name="why-is-this-better"></a>Why is this better?</h4>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Open for Extension</strong> – New shapes (e.g., <code>Triangle</code>) can be added without modifying <code>AreaCalculator</code>.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Closed for Modification</strong> – The core logic stays unchanged.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Encapsulated Behavior</strong> – Each shape class is responsible for its own area calculation.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#ecommerce-example" name="ecommerce-example"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6d2.png" alt="🛒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> E-Commerce Example</h3>
<p>Imagine a payment system where different payment methods need to be supported:</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example" name="bad-example"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">string</span> <span class="nv">$type</span><span class="p">,</span> <span class="kt">float</span> <span class="nv">$amount</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="nv">$type</span> <span class="o">===</span> <span class="s1">'credit_card'</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// Process credit card</span>
        <span class="p">}</span> <span class="k">elseif</span> <span class="p">(</span><span class="nv">$type</span> <span class="o">===</span> <span class="s1">'paypal'</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// Process PayPal</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Problem:</strong> Every time a new payment method is added, the class needs modification.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#fixed-example" name="fixed-example"></a>Fixed Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">PaymentMethod</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">process</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">CreditCardPayment</span> <span class="kd">implements</span> <span class="nc">PaymentMethod</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">process</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="c1">// Process credit card</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">PayPalPayment</span> <span class="kd">implements</span> <span class="nc">PaymentMethod</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">process</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="c1">// Process PayPal</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="k">private</span> <span class="kt">PaymentMethod</span> <span class="nv">$paymentMethod</span><span class="p">)</span> <span class="p">{}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">process</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">paymentMethod</span><span class="o">-&gt;</span><span class="nf">process</span><span class="p">(</span><span class="nv">$amount</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#benefits" name="benefits"></a>Benefits <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h4>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Easily extendable – Add new payment methods without modifying existing code.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Reduces risk – Core payment logic remains untouched.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Improves readability – No complex <code>if</code> conditions.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#advanced-insights" name="advanced-insights"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Advanced Insights <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<ul>
<li><strong>Design Patterns</strong>: The <strong>Strategy Pattern</strong> is often used to implement OCP.</li>
<li><strong>Framework Best Practices</strong>: Laravel and Symfony implement OCP through middleware and service providers.</li>
<li><strong>OCP and Testing</strong>: Easier to unit test since components are loosely coupled.</li>
</ul>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#tradeoffs" name="tradeoffs"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2696.png" alt="⚖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Trade-offs</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pros:</strong></p>
<ul>
<li><strong>Flexibility</strong> – OCP reduces modification risks in stable code.</li>
<li><strong>Test Stability</strong> – Existing functionality remains unchanged.</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Cons:</strong></p>
<ul>
<li><strong>More Abstraction</strong> – Using interfaces and dependency injection adds more classes.</li>
<li><strong>Overhead</strong> – If the system will never change, adding interfaces might be unnecessary.</li>
<li><strong>YAGNI (You Aren’t Gonna Need It)</strong> – Don’t over-engineer if new features are unlikely.</li>
</ul>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#developer-hints" name="developer-hints"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Developer Hints</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Use <strong>interfaces and abstract classes</strong> to define extension points.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Avoid <strong>modifying stable, tested classes</strong> unless absolutely necessary.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Think <strong>long-term scalability</strong> before choosing rigid, hard-coded implementations.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> If a pattern <strong>adds complexity but solves no problem</strong>, you may not need it.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#conclusion" name="conclusion"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3c1.png" alt="🏁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Conclusion</h3>
<p>A well-designed system should be adaptable to <strong>future needs</strong> without forcing developers to modify <strong>working, tested code</strong>. By leveraging <strong>polymorphism, interfaces, and design patterns</strong>, we achieve flexibility while maintaining stability. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#liskov-substitution-principle-lsp-keep-your-promises" name="liskov-substitution-principle-lsp-keep-your-promises"></a>Liskov Substitution Principle (LSP) &#8211; &#8220;Keep Your Promises&#8221;</h2>
<p><a class="article-body-image-wrapper" href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fw8atfuyc7tmyc0vvwz.png"><img decoding="async" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fw8atfuyc7tmyc0vvwz.png" alt="Image description" /></a><br />(source: <a href="https://trekhleb.dev/blog/2017/solid-principles-around-you/" target="_blank" rel="noopener noreferrer">https://trekhleb.dev/blog/2017/solid-principles-around-you/</a>)</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#academic-definition" name="academic-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Academic Definition</h3>
<blockquote>
<p><strong>Objects in a program should be replaceable with instances of their subtypes without altering the correctness of the program.</strong></p>
</blockquote>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#our-definition" name="our-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Our Definition</h3>
<p>If a class (child) extends another class (parent), it should behave in a way that doesn’t break expectations set by the parent class. Any subclass should be usable in place of its superclass without unexpected behavior.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#simple-definition" name="simple-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4dd.png" alt="📝" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Simple Definition</h3>
<p>A subclass should respect the promises made by its parent class. If you replace the parent class with a subclass, everything should still work correctly.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#paw-patrol-analogy-the-special-snowplow-problem" name="paw-patrol-analogy-the-special-snowplow-problem"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f43e.png" alt="🐾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Paw Patrol Analogy: The Special Snowplow Problem</h3>
<p>Imagine the Paw Patrol vehicles. Each pup has their own special ride, but all of them <strong>must be drivable</strong>.</p>
<p>Now imagine if Everest’s snowplow <strong>couldn’t drive on roads</strong> because it was only built for ice. If a mission required her to drive on a normal road, the system would break because her vehicle doesn’t meet the basic expectation of “being able to drive.”</p>
<p>That’s an LSP violation—her vehicle is a “subclass” of the general &#8220;Paw Patrol Vehicle,&#8221; but it doesn’t fully substitute for it in every situation.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#key-learnings" name="key-learnings"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Key Learnings</h3>
<ol>
<li><strong>Child classes must respect the contract of their parent classes.</strong></li>
<li><strong>Avoid violating expectations</strong>—subclasses must behave consistently with their base class.</li>
<li><strong>If a subclass has to override too much behavior</strong>, it might not truly be a subtype and could indicate a bad inheritance choice.</li>
<li><strong>LSP helps keep code predictable</strong>—it prevents unexpected failures when replacing a base class with a subclass.</li>
</ol>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example-violating-lsp-in-php" name="bad-example-violating-lsp-in-php"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" />: Violating LSP in PHP</h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">Bird</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">fly</span><span class="p">():</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s2">"I am flying!"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Penguin</span> <span class="kd">extends</span> <span class="nc">Bird</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">fly</span><span class="p">():</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"I can't fly!"</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">function</span> <span class="n">makeBirdFly</span><span class="p">(</span><span class="kt">Bird</span> <span class="nv">$bird</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nv">$bird</span><span class="o">-&gt;</span><span class="nf">fly</span><span class="p">();</span>
<span class="p">}</span>

<span class="nv">$penguin</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Penguin</span><span class="p">();</span>
<span class="k">echo</span> <span class="nf">makeBirdFly</span><span class="p">(</span><span class="nv">$penguin</span><span class="p">);</span> <span class="c1">// &#x274c; Breaks expectation!</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f534.png" alt="🔴" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Issue:</strong> <code>Penguin</code> extends <code>Bird</code>, but it breaks the expectation that all birds can fly.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#fixed-example-using-interfaces-to-respect-lsp" name="fixed-example-using-interfaces-to-respect-lsp"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Fixed Example: Using Interfaces to Respect LSP</h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">Bird</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">eat</span><span class="p">():</span> <span class="kt">string</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">interface</span> <span class="nc">FlyingBird</span> <span class="kd">extends</span> <span class="nc">Bird</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">fly</span><span class="p">():</span> <span class="kt">string</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Sparrow</span> <span class="kd">implements</span> <span class="nc">FlyingBird</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">eat</span><span class="p">():</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s2">"I eat seeds."</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">fly</span><span class="p">():</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s2">"I can fly!"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Penguin</span> <span class="kd">implements</span> <span class="nc">Bird</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">eat</span><span class="p">():</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s2">"I eat fish."</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">function</span> <span class="n">observeBird</span><span class="p">(</span><span class="kt">Bird</span> <span class="nv">$bird</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nv">$bird</span><span class="o">-&gt;</span><span class="nf">eat</span><span class="p">();</span>
<span class="p">}</span>

<span class="nv">$sparrow</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Sparrow</span><span class="p">();</span>
<span class="nv">$penguin</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Penguin</span><span class="p">();</span>

<span class="k">echo</span> <span class="nf">observeBird</span><span class="p">(</span><span class="nv">$sparrow</span><span class="p">);</span> <span class="c1">// &#x2705; Works fine!</span>
<span class="k">echo</span> <span class="nf">observeBird</span><span class="p">(</span><span class="nv">$penguin</span><span class="p">);</span> <span class="c1">// &#x2705; Works fine!</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e2.png" alt="🟢" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fix:</strong> Instead of forcing all birds to be able to fly, we separate &#8220;flying&#8221; behavior into a different interface. This way, penguins don’t have to pretend they can fly.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#ecommerce-example-the-free-shipping-issue" name="ecommerce-example-the-free-shipping-issue"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6d2.png" alt="🛒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> E-Commerce Example: The Free Shipping Issue</h3>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example-breaking-the-parent-contract" name="bad-example-breaking-the-parent-contract"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" />: Breaking the Parent Contract</h4>
<p>Imagine an order system where <code>StandardOrder</code> has a method <code>getShippingCost()</code>. A developer extends it for <code>FreeShippingOrder</code> but violates expectations:</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">StandardOrder</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getShippingCost</span><span class="p">():</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mf">5.99</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">FreeShippingOrder</span> <span class="kd">extends</span> <span class="nc">StandardOrder</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getShippingCost</span><span class="p">():</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"This order has free shipping!"</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">function</span> <span class="n">processOrder</span><span class="p">(</span><span class="kt">StandardOrder</span> <span class="nv">$order</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="s2">"Shipping Cost: "</span> <span class="mf">.</span> <span class="nv">$order</span><span class="o">-&gt;</span><span class="nf">getShippingCost</span><span class="p">();</span>
<span class="p">}</span>

<span class="nv">$order</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FreeShippingOrder</span><span class="p">();</span>
<span class="k">echo</span> <span class="nf">processOrder</span><span class="p">(</span><span class="nv">$order</span><span class="p">);</span> <span class="c1">// &#x274c; Unexpected exception!</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f534.png" alt="🔴" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Issue:</strong> <code>FreeShippingOrder</code> breaks the contract by throwing an exception instead of returning a valid shipping cost.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#fixed-example-using-a-different-approach" name="fixed-example-using-a-different-approach"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Fixed Example: Using a Different Approach</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">Order</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getShippingCost</span><span class="p">():</span> <span class="kt">float</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">StandardOrder</span> <span class="kd">implements</span> <span class="nc">Order</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getShippingCost</span><span class="p">():</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mf">5.99</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">FreeShippingOrder</span> <span class="kd">implements</span> <span class="nc">Order</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getShippingCost</span><span class="p">():</span> <span class="kt">float</span> <span class="p">{</span>
        <span class="k">return</span> <span class="mf">0.00</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">function</span> <span class="n">processOrder</span><span class="p">(</span><span class="kt">Order</span> <span class="nv">$order</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="s2">"Shipping Cost: "</span> <span class="mf">.</span> <span class="nv">$order</span><span class="o">-&gt;</span><span class="nf">getShippingCost</span><span class="p">();</span>
<span class="p">}</span>

<span class="nv">$order</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FreeShippingOrder</span><span class="p">();</span>
<span class="k">echo</span> <span class="nf">processOrder</span><span class="p">(</span><span class="nv">$order</span><span class="p">);</span> <span class="c1">// &#x2705; Outputs "Shipping Cost: 0.00"</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e2.png" alt="🟢" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fix:</strong> Instead of forcing <code>FreeShippingOrder</code> to inherit from <code>StandardOrder</code>, we use an <code>Order</code> interface, ensuring all orders can return a shipping cost without surprises.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#advanced-insights" name="advanced-insights"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Advanced Insights <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<ol>
<li><strong>LSP helps prevent bad inheritance hierarchies.</strong> If you constantly override parent methods in a subclass, consider <strong>composition</strong> over inheritance.</li>
<li><strong>Use Interfaces to enforce behavior contracts</strong>—avoid forcing all child classes into behaviors they don’t support.</li>
<li><strong>LSP violations often indicate design flaws.</strong> If your subclass keeps breaking expectations, your class hierarchy may be wrong.</li>
<li><strong>Invariance vs Covariance vs Contravariance:</strong> Be mindful of how method parameters and return types evolve in subclasses.</li>
</ol>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#tradeoffs" name="tradeoffs"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2696.png" alt="⚖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Trade-offs</h3>
<div class="table-wrapper-paragraph">
<table>
<thead>
<tr>
<th><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pros</strong></th>
<th><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Cons</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Ensures subclasses don’t break existing code</td>
<td>May lead to extra abstraction layers</td>
</tr>
<tr>
<td>Helps catch bad inheritance early</td>
<td>Too many interfaces can lead to complexity</td>
</tr>
<tr>
<td>Makes extending systems easier</td>
<td>Sometimes inheritance is still the simpler choice</td>
</tr>
</tbody>
</table>
</div>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#developer-hints" name="developer-hints"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Developer Hints</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>DO:</strong> Use LSP to validate your class hierarchies—if a subclass must override too many methods, it’s likely a bad fit.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>DON’T:</strong> Inherit from a class just to &#8220;reuse&#8221; some methods—if the behaviors aren’t consistent, prefer composition.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>DO:</strong> Use interfaces and careful method contracts to ensure subclasses behave as expected.</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>DON’T:</strong> Assume that &#8220;all X should do Y&#8221;—if exceptions exist, rethink your hierarchy.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#conclusion" name="conclusion"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3c1.png" alt="🏁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Conclusion</h3>
<p>Liskov Substitution Principle ensures that subclasses can always stand in for their parent class <strong>without surprises</strong>. It’s one of the most overlooked SOLID principles but arguably one of the most important for keeping systems <strong>extendable and predictable</strong>.</p>
<p>Use LSP to validate your class hierarchies. If your subclass <strong>breaks expected behavior</strong>, it&#8217;s a sign you might need <strong>a different inheritance model or composition instead</strong>. Keep your promises, and your codebase will stay clean and maintainable!</p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#interface-segregation-principle-isp" name="interface-segregation-principle-isp"></a>Interface Segregation Principle (ISP)</h2>
<p><a class="article-body-image-wrapper" href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2agpndrjv1t864f2lhjh.png"><img decoding="async" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2agpndrjv1t864f2lhjh.png" alt="Image description" /></a><br />(source: <a href="https://trekhleb.dev/blog/2017/solid-principles-around-you/" target="_blank" rel="noopener noreferrer">https://trekhleb.dev/blog/2017/solid-principles-around-you/</a>)</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#academic-definition" name="academic-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Academic Definition</h3>
<blockquote>
<p>&#8220;Clients should not be forced to depend on methods they do not use.&#8221;</p>
</blockquote>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#our-definition" name="our-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Our Definition</h3>
<p>Interfaces should be focused and granular, ensuring that implementing classes only need to adhere to methods that are relevant to them. This prevents classes from being bloated with unnecessary dependencies and improves code maintainability.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#simple-definition" name="simple-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4dd.png" alt="📝" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Simple Definition</h3>
<p>Don&#8217;t force a class to implement methods it doesn’t need.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#paw-patrol-analogy" name="paw-patrol-analogy"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f43e.png" alt="🐾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Paw Patrol Analogy</h3>
<p>Imagine all Paw Patrol pups had to follow the same &#8220;Rescue Operations&#8221; interface. That would mean Skye (the helicopter pup) would have to implement &#8220;Water Cannon Operation&#8221; even though she has no water cannons! Instead, it&#8217;s better to have separate interfaces: one for fire rescue (Marshall) and one for aerial rescue (Skye). This ensures that each pup only implements the operations they actually perform.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#key-learnings" name="key-learnings"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Key Learnings</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Interfaces should be <strong>focused</strong> and <strong>cohesive</strong>—not overloaded with unrelated methods.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Use <strong>multiple small interfaces</strong> instead of <strong>one large interface</strong>.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Helps avoid unnecessary dependencies and improves modularity.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Reduces the likelihood of implementing empty or throwaway methods.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Works well with <strong>Dependency Inversion Principle (DIP)</strong> by defining specific contract expectations.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#advanced-insights" name="advanced-insights"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Advanced Insights <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<ul>
<li><strong>Granular Interfaces → Better Code Maintainability</strong>: By keeping interfaces small, you prevent a ripple effect of unnecessary method changes in unrelated classes.</li>
<li><strong>Avoid Interface Pollution</strong>: Large interfaces force implementing classes to define methods they don’t use, leading to bad design and unnecessary complexity.</li>
<li><strong>Natural Extension of SRP</strong>: ISP is like SRP but at the interface level—ensuring each interface has a single, clear responsibility.</li>
<li><strong>Refactoring Legacy Code</strong>: If you have bloated interfaces, split them into <strong>cohesive, role-based interfaces</strong>.</li>
<li><strong>Multiple Implementations</strong>: You can mix and match smaller interfaces in various ways without forcing unrelated methods onto a class.</li>
</ul>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example-bloated-interface" name="bad-example-bloated-interface"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" />: Bloated Interface</h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">Worker</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">work</span><span class="p">():</span> <span class="kt">void</span><span class="p">;</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">eat</span><span class="p">():</span> <span class="kt">void</span><span class="p">;</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">sleep</span><span class="p">():</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Robot</span> <span class="kd">implements</span> <span class="nc">Worker</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">work</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"I am working!"</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">eat</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"Robots don't eat!"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">sleep</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"Robots don't sleep!"</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Problem:</strong> The <code>Worker</code> interface forces <code>Robot</code> to implement <code>eat()</code> and <code>sleep()</code>, which don’t make sense.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#good-example-segregated-interfaces" name="good-example-segregated-interfaces"></a>Good Example: Segregated Interfaces <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">Workable</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">work</span><span class="p">():</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">interface</span> <span class="nc">HumanNeeds</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">eat</span><span class="p">():</span> <span class="kt">void</span><span class="p">;</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">sleep</span><span class="p">():</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">Robot</span> <span class="kd">implements</span> <span class="nc">Workable</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">work</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"I am working!"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">HumanWorker</span> <span class="kd">implements</span> <span class="nc">Workable</span><span class="p">,</span> <span class="nc">HumanNeeds</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">work</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Working hard!"</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">eat</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Eating lunch."</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">sleep</span><span class="p">():</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Going to sleep."</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Now each class only implements the methods it actually needs!</strong></p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#ecommerce-example" name="ecommerce-example"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6d2.png" alt="🛒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> E-Commerce Example</h3>
<p>Imagine you have a large <code>PaymentProcessor</code> interface that forces all payment gateways (PayPal, Stripe, Bitcoin) to implement methods like <code>refund()</code> and <code>chargeBack()</code>, even if some gateways don’t support chargebacks.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example-bloated-interface" name="bad-example-bloated-interface"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" />: Bloated Interface</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span><span class="p">;</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">refund</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span><span class="p">;</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">chargeBack</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">BitcoinProcessor</span> <span class="kd">implements</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Processing Bitcoin payment."</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">refund</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"Bitcoin transactions are irreversible!"</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">chargeBack</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s2">"Bitcoin has no chargebacks!"</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Problem:</strong> Bitcoin does not support refunds or chargebacks, yet it’s forced to implement these methods.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#segregated-interfaces-good-example" name="segregated-interfaces-good-example"></a>Segregated Interfaces (Good Example) <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">interface</span> <span class="nc">Refundable</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">refund</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">interface</span> <span class="nc">Chargebackable</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">chargeBack</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">BitcoinProcessor</span> <span class="kd">implements</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Processing Bitcoin payment."</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">CreditCardProcessor</span> <span class="kd">implements</span> <span class="nc">PaymentProcessor</span><span class="p">,</span> <span class="nc">Refundable</span><span class="p">,</span> <span class="nc">Chargebackable</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Processing Credit Card payment."</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">refund</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Processing refund."</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">chargeBack</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">void</span> <span class="p">{</span>
        <span class="k">echo</span> <span class="s2">"Processing chargeback."</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Now, Bitcoin only implements <code>PaymentProcessor</code>, and Credit Card processors can add <code>Refundable</code> and <code>Chargebackable</code>.</strong></p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#tradeoffs" name="tradeoffs"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2696.png" alt="⚖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Trade-offs</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pros:</strong></p>
<ul>
<li>Prevents unnecessary dependencies.</li>
<li>Improves readability and maintainability.</li>
<li>Easier to refactor without breaking implementations.</li>
<li>Better aligns with the <strong>Single Responsibility Principle (SRP)</strong>.</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Cons:</strong></p>
<ul>
<li>Can lead to <strong>too many</strong> small interfaces.</li>
<li>Requires <strong>careful naming</strong> to keep interfaces meaningful.</li>
<li>Might <strong>increase boilerplate</strong> in some cases.</li>
</ul>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#developer-hints" name="developer-hints"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Developer Hints</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Split interfaces when:</strong></p>
<ul>
<li>A class is implementing empty methods.</li>
<li>A class throws exceptions for methods it doesn’t support.</li>
<li>A method is only used in <strong>some</strong> implementations but not others.</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Keep interfaces meaningful:</strong></p>
<ul>
<li>Don&#8217;t over-fragment interfaces into tiny, meaningless pieces.</li>
<li>A good rule: If <strong>two implementations always share the same methods</strong>, keep them together.</li>
</ul>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Use with Dependency Injection:</strong></p>
<ul>
<li>Granular interfaces make <strong>Dependency Injection (DI)</strong> much cleaner.</li>
</ul>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#conclusion" name="conclusion"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3c1.png" alt="🏁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Conclusion</h3>
<p>Interface Segregation ensures that interfaces stay clean and meaningful. Instead of bloated, one-size-fits-all contracts, ISP encourages <strong>focused, role-specific interfaces</strong> that keep classes lean and purposeful. By following ISP, you create software that is <strong>modular, easy to extend, and avoids unnecessary coupling</strong>.</p>
<p>By embracing ISP, your codebase stays <strong>flexible, maintainable, and scalable</strong>—just like a well-organized Paw Patrol team! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f436.png" alt="🐶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#dependency-inversion-principle-dip" name="dependency-inversion-principle-dip"></a>Dependency Inversion Principle (DIP)</h2>
<p><a class="article-body-image-wrapper" href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad1eyh2ilp1exhm9p31d.png"><img decoding="async" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fad1eyh2ilp1exhm9p31d.png" alt="Image description" /></a><br />(source: <a href="https://trekhleb.dev/blog/2017/solid-principles-around-you/" target="_blank" rel="noopener noreferrer">https://trekhleb.dev/blog/2017/solid-principles-around-you/</a>)</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#academic-definition" name="academic-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4da.png" alt="📚" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Academic Definition</h3>
<blockquote>
<p><strong>High-level modules should not depend on low-level modules. Both should depend on abstractions.</strong></p>
<p><strong>Abstractions should not depend on details. Details should depend on abstractions.</strong></p>
</blockquote>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#our-definition" name="our-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Our Definition</h3>
<p>DIP ensures that <strong>core logic (high-level modules)</strong> does not directly depend on <strong>specific implementations (low-level modules)</strong>. Instead, both depend on a common <strong>interface or abstraction</strong>.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#simple-definition" name="simple-definition"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4dd.png" alt="📝" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Simple Definition</h3>
<p>Instead of hardcoding dependencies, rely on <strong>interfaces</strong> or <strong>dependency injection</strong> to allow for easier maintenance, testing, and swapping implementations.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#paw-patrol-analogy" name="paw-patrol-analogy"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f43e.png" alt="🐾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Paw Patrol Analogy</h3>
<p>Imagine <strong>Ryder</strong>, the leader of Paw Patrol, who needs a pup for a rescue mission. Instead of calling <strong>Chase</strong> directly, he calls for a &#8220;Police Pup.&#8221; This allows <strong>Chase</strong> to respond, but if another police dog joins the team, he can step in without changing Ryder’s commands.</p>
<p>By coding to an <strong>abstraction (&#8220;Police Pup&#8221;)</strong> instead of a <strong>concrete implementation (&#8220;Chase&#8221;)</strong>, Ryder ensures flexibility.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#key-learnings" name="key-learnings"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Key Learnings</h3>
<p>1&#x20e3; <strong>High-Level Modules (Core Logic) Should Not Depend on Low-Level Modules (Implementations)</strong></p>
<ul>
<li>Example: An <code>OrderService</code> should not directly depend on <code>MySQLDatabase</code> but instead on <code>DatabaseInterface</code>.</li>
</ul>
<p>2&#x20e3; <strong>Abstractions Should Not Depend on Details</strong></p>
<ul>
<li>The interface should define behavior, not implementation details.</li>
</ul>
<p>3&#x20e3; <strong>Use Dependency Injection for Flexibility</strong></p>
<ul>
<li>Instead of creating objects inside a class (<code>new MySQLDatabase()</code>), pass them as dependencies (<code>DatabaseInterface $db</code>).</li>
</ul>
<p>4&#x20e3; <strong>Promotes Testing and Maintainability</strong></p>
<ul>
<li>Easily mock dependencies in unit tests by swapping implementations.</li>
</ul>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#simple-example-violating-dip" name="simple-example-violating-dip"></a>Simple Example (Violating DIP)</h3>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example-hardcoded-dependency" name="bad-example-hardcoded-dependency"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" />: Hardcoded Dependency</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">MySQLDatabase</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getUser</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$id</span><span class="p">):</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s2">"User data from MySQL"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">UserService</span> <span class="p">{</span>
    <span class="k">private</span> <span class="kt">MySQLDatabase</span> <span class="nv">$database</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">()</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">database</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">MySQLDatabase</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">getUser</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$id</span><span class="p">):</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">database</span><span class="o">-&gt;</span><span class="nf">getUser</span><span class="p">(</span><span class="nv">$id</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a5.png" alt="💥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Problem:</strong> If we switch to <code>PostgreSQLDatabase</code>, we must modify <code>UserService</code>, violating DIP.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#the-fix-applying-dip" name="the-fix-applying-dip"></a>The Fix: Applying DIP</h3>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#good-example-using-an-interface" name="good-example-using-an-interface"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Good Example: Using an Interface</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">DatabaseInterface</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getUser</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$id</span><span class="p">):</span> <span class="kt">string</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">MySQLDatabase</span> <span class="kd">implements</span> <span class="nc">DatabaseInterface</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getUser</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$id</span><span class="p">):</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s2">"User data from MySQL"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">PostgreSQLDatabase</span> <span class="kd">implements</span> <span class="nc">DatabaseInterface</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">getUser</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$id</span><span class="p">):</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s2">"User data from PostgreSQL"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">UserService</span> <span class="p">{</span>
    <span class="k">private</span> <span class="kt">DatabaseInterface</span> <span class="nv">$database</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="kt">DatabaseInterface</span> <span class="nv">$database</span><span class="p">)</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">database</span> <span class="o">=</span> <span class="nv">$database</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">getUser</span><span class="p">(</span><span class="kt">int</span> <span class="nv">$id</span><span class="p">):</span> <span class="kt">string</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">database</span><span class="o">-&gt;</span><span class="nf">getUser</span><span class="p">(</span><span class="nv">$id</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// Usage</span>
<span class="nv">$service</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">UserService</span><span class="p">(</span><span class="k">new</span> <span class="nc">MySQLDatabase</span><span class="p">());</span>
<span class="nv">$service</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">UserService</span><span class="p">(</span><span class="k">new</span> <span class="nc">PostgreSQLDatabase</span><span class="p">());</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Now <code>UserService</code> does not depend on a specific database but on <code>DatabaseInterface</code></strong>, making it flexible.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#ecommerce-example" name="ecommerce-example"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6d2.png" alt="🛒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> E-Commerce Example</h3>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#bad-example-hardcoded-payment-processor" name="bad-example-hardcoded-payment-processor"></a>Bad Example <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a8.png" alt="🚨" class="wp-smiley" style="height: 1em; max-height: 1em;" />: Hardcoded Payment Processor</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">PaymentService</span> <span class="p">{</span>
    <span class="k">private</span> <span class="kt">StripePaymentProcessor</span> <span class="nv">$processor</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">()</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">processor</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StripePaymentProcessor</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">processor</span><span class="o">-&gt;</span><span class="nf">pay</span><span class="p">(</span><span class="nv">$amount</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a5.png" alt="💥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Issue:</strong> Tied to Stripe; hard to replace with PayPal.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#good-example-dip-with-interfaces" name="good-example-dip-with-interfaces"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Good Example (DIP with Interfaces)</h4>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">interface</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">pay</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">bool</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">StripePaymentProcessor</span> <span class="kd">implements</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">pay</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">bool</span> <span class="p">{</span>
        <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">// Process payment via Stripe</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">PayPalPaymentProcessor</span> <span class="kd">implements</span> <span class="nc">PaymentProcessor</span> <span class="p">{</span>
    <span class="k">public</span> <span class="k">function</span> <span class="n">pay</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">):</span> <span class="kt">bool</span> <span class="p">{</span>
        <span class="k">return</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">// Process payment via PayPal</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span> <span class="nc">PaymentService</span> <span class="p">{</span>
    <span class="k">private</span> <span class="kt">PaymentProcessor</span> <span class="nv">$processor</span><span class="p">;</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="kt">PaymentProcessor</span> <span class="nv">$processor</span><span class="p">)</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">processor</span> <span class="o">=</span> <span class="nv">$processor</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="k">function</span> <span class="n">processPayment</span><span class="p">(</span><span class="kt">float</span> <span class="nv">$amount</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="n">processor</span><span class="o">-&gt;</span><span class="nf">pay</span><span class="p">(</span><span class="nv">$amount</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// Usage</span>
<span class="nv">$paymentService</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PaymentService</span><span class="p">(</span><span class="k">new</span> <span class="nc">StripePaymentProcessor</span><span class="p">());</span>
<span class="nv">$paymentService</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PaymentService</span><span class="p">(</span><span class="k">new</span> <span class="nc">PayPalPaymentProcessor</span><span class="p">());</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Now the service works with <strong>any</strong> payment processor.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#advanced-insights" name="advanced-insights"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Advanced Insights <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>IoC Containers (Dependency Injection Containers)</strong><br /><br />Modern frameworks (Laravel, Symfony) use IoC containers to <strong>bind interfaces to implementations</strong>, automating dependency resolution.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="nv">$container</span><span class="o">-&gt;</span><span class="nf">bind</span><span class="p">(</span><span class="nc">PaymentProcessor</span><span class="o">::</span><span class="n">class</span><span class="p">,</span> <span class="nc">StripePaymentProcessor</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="nv">$paymentService</span> <span class="o">=</span> <span class="nv">$container</span><span class="o">-&gt;</span><span class="nf">make</span><span class="p">(</span><span class="nc">PaymentService</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Easier Unit Testing</strong><br /><br />By injecting dependencies, you can mock them in tests:</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="nv">$mockProcessor</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">createMock</span><span class="p">(</span><span class="nc">PaymentProcessor</span><span class="o">::</span><span class="n">class</span><span class="p">);</span>
<span class="nv">$mockProcessor</span><span class="o">-&gt;</span><span class="nf">method</span><span class="p">(</span><span class="s1">'pay'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">willReturn</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
<span class="nv">$service</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PaymentService</span><span class="p">(</span><span class="nv">$mockProcessor</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">assertTrue</span><span class="p">(</span><span class="nv">$service</span><span class="o">-&gt;</span><span class="nf">processPayment</span><span class="p">(</span><span class="mi">100</span><span class="p">));</span>
</code></pre>
<div class="highlight__panel js-actions-panel">
<div class="highlight__panel-action js-fullscreen-code-action"> </div>
</div>
</div>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#tradeoffs" name="tradeoffs"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2696.png" alt="⚖" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Trade-offs</h3>
<p>1&#x20e3; <strong>Over-Abstraction</strong>: Too many interfaces can complicate simple cases.<br />2&#x20e3; <strong>Initial Setup Overhead</strong>: More upfront work vs. hardcoding dependencies.<br />3&#x20e3; <strong>Not Always Needed</strong>: Small scripts may not benefit from DIP.<br />4&#x20e3; <strong>Performance</strong>: Extra layers add slight performance costs.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#developer-hints" name="developer-hints"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Developer Hints</h3>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Use interfaces when multiple implementations are possible.</strong><br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>If a dependency rarely changes, DIP might be unnecessary overhead.</strong><br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f504.png" alt="🔄" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Combine with IoC containers for better dependency management.</strong></p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#conclusion" name="conclusion"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3c1.png" alt="🏁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Conclusion</h3>
<p>DIP helps create flexible, scalable, and testable code. While overusing it can lead to unnecessary complexity, applying it where appropriate <strong>ensures long-term maintainability and adaptability</strong>.</p>
<hr />
<p><strong>Learnings and Findings from the Blog Post</strong></p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#the-essence-of-solid-beyond-textbook-definitions" name="the-essence-of-solid-beyond-textbook-definitions"></a><strong>The Essence of SOLID Beyond Textbook Definitions</strong></h2>
<p>We have consistently moved beyond simply memorizing the SOLID principles. Instead, we have deeply examined their real-world applications, trade-offs, and potential misuses. The key insight is that SOLID is not a rigid framework but a set of guiding principles that, when applied pragmatically, result in <strong>maintainable, flexible, and understandable</strong> software.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#what-we-learned" name="what-we-learned"></a><strong>What We Learned:</strong></h3>
<p>1&#x20e3; SOLID <strong>is a means, not an end</strong>—it should improve software, not be followed blindly.<br />2&#x20e3; Principles should <strong>evolve naturally</strong> with software needs rather than being enforced prematurely.<br />3&#x20e3; <strong>Balance is key</strong>: applying SOLID too rigidly can introduce unnecessary complexity, while ignoring it leads to unmanageable abstractions.<br />4&#x20e3; Naming and categorization of abstract concepts help communicate intent and keep teams aligned.</p>
<hr />
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#solid-principles-recap" name="solid-principles-recap"></a><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f504.png" alt="🔄" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>SOLID Principles Recap</strong></h3>
<p>Each principle is a tool to write better, maintainable, and scalable software. While following them strictly isn’t always necessary, understanding them deeply allows you to make informed trade-offs when designing software.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#single-responsibility-principle-srp" name="single-responsibility-principle-srp"></a>1&#x20e3; <strong>Single Responsibility Principle</strong> (SRP)</h4>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Rule</strong>: A class should only have one reason to change.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Benefit</strong>: Reduces complexity and improves maintainability.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pitfall</strong>: Over-applying SRP can create too many small classes.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#openclosed-principle-ocp" name="openclosed-principle-ocp"></a>2&#x20e3; <strong>Open-Closed Principle</strong> (OCP)</h4>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Rule</strong>: Code should be open for extension but closed for modification.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Benefit</strong>: Prevents modifying stable, tested code when adding new features.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pitfall</strong>: Over-abstraction can make code difficult to understand.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#liskov-substitution-principle-lsp" name="liskov-substitution-principle-lsp"></a>3&#x20e3; <strong>Liskov Substitution Principle</strong> (LSP)</h4>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Rule</strong>: Subtypes must be substitutable for their base types.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Benefit</strong>: Ensures a predictable, bug-free inheritance structure.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pitfall</strong>: Violations often happen when child classes break parent contracts.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#interface-segregation-principle-isp" name="interface-segregation-principle-isp"></a>4&#x20e3; <strong>Interface Segregation Principle</strong> (ISP)</h4>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Rule</strong>: No class should be forced to depend on methods it does not use.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Benefit</strong>: Creates leaner, more reusable interfaces.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pitfall</strong>: Too many interfaces can create confusion or interface bloat.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#dependency-inversion-principle-dip" name="dependency-inversion-principle-dip"></a>5&#x20e3; <strong>Dependency Inversion Principle</strong> (DIP)</h4>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Rule</strong>: Depend on abstractions, not concrete implementations.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Benefit</strong>: Encourages decoupled, flexible, and testable code.<br /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Pitfall</strong>: Overuse can lead to too many indirections, making debugging harder.</p>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#abstractions-when-to-generalize-and-when-to-copypaste" name="abstractions-when-to-generalize-and-when-to-copypaste"></a><strong>Abstractions: When to Generalize and When to Copy-Paste</strong></h2>
<p><a class="article-body-image-wrapper" href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldgeihlz2loa3hbsx9if.png"><img decoding="async" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldgeihlz2loa3hbsx9if.png" alt="Image description" /></a><br />(source: <a href="https://www.reddit.com/r/Design/comments/6qh8ni/the_abstractometer/" target="_blank" rel="noopener noreferrer">https://www.reddit.com/r/Design/comments/6qh8ni/the_abstractometer/</a>)</p>
<p>The Abstract-o-Meter reminds us that effective software design lies in finding the balance between clarity and usability. Every abstraction should:</p>
<ul>
<li>Hide unnecessary details, making systems easier to understand.</li>
<li>Preserve essential clarity, ensuring they remain relevant to the real-world domain.</li>
</ul>
<p>Whether you’re designing a small utility class or architecting a large-scale system, always aim for the heart in the middle of the Abstract-o-Meter. This is the area where your abstractions remain meaningful, useful and maintainable, and only then will other developers actually use them.</p>
<p>One of the most significant learning is about <strong>the right time to introduce abstractions</strong> versus when copy-pasting is actually preferable. The classic fear of duplication (&#8220;DRY principle&#8221;) must be balanced with <strong>avoiding premature abstractions</strong> that introduce unnecessary coupling and complexity.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#key-takeaways" name="key-takeaways"></a><strong>Key Takeaways:</strong></h3>
<p>1&#x20e3; <strong>Duplication is often cheaper</strong> than the wrong abstraction.<br />2&#x20e3; Generalization should be based on <strong>real-world observed repetition</strong>, not speculative future needs.<br />3&#x20e3; Over-abstraction leads to <strong>hard-to-read, bloated code</strong> where understanding business rules requires digging through multiple indirections.<br />4&#x20e3; High <strong>cohesion and minimal dependencies</strong> should be prioritized when designing abstractions.</p>
<h4><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#pragmatic-rule-of-thumb" name="pragmatic-rule-of-thumb"></a><strong>Pragmatic Rule of Thumb:</strong></h4>
<ul>
<li>First occurrence? <strong>Write it.</strong></li>
<li>Second occurrence? <strong>Copy it.</strong></li>
<li>Third occurrence? <strong>Consider abstraction—but validate first.</strong></li>
</ul>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#naming-and-conceptual-thinking-the-front-garden-and-neighborhood-metaphors" name="naming-and-conceptual-thinking-the-front-garden-and-neighborhood-metaphors"></a><strong>Naming and Conceptual Thinking: The &#8220;Front Garden&#8221; and &#8220;Neighborhood&#8221; Metaphors</strong></h2>
<p>We explored how defining abstract <strong>conceptual names</strong> improves communication. The <strong>Front Garden</strong> and <strong>Neighborhood</strong> analogy illustrated the power of naming in programming and software architecture:</p>
<ul>
<li>By naming <strong>broad categories of problems</strong>, we create <strong>reusable mental models</strong> that allow easier discussions.</li>
<li>Instead of explaining every case separately, we can <strong>define an abstract concept</strong> (like &#8220;OCP Violation&#8221; or &#8220;Front Garden Boundary&#8221;) and use it as shorthand.</li>
<li><strong>Rules should be flexible principles</strong>, not rigid constraints—much like in software, where strict application of SOLID without context leads to over-engineering.</li>
</ul>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#the-solid-but-practical-mindset-knowing-when-to-bend-the-rules" name="the-solid-but-practical-mindset-knowing-when-to-bend-the-rules"></a><strong>The &#8220;SOLID but Practical&#8221; Mindset: Knowing When to Bend the Rules</strong></h2>
<p>Throughout our discussions, a recurring theme was <strong>pragmatism over dogma</strong>. Many developers apply SOLID too rigidly, causing unnecessary complexity. The real mastery lies in knowing when to <strong>intentionally</strong> bend or break the rules <strong>for the right reasons</strong>.</p>
<h3><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#key-lessons" name="key-lessons"></a><strong>Key Lessons:</strong></h3>
<ul>
<li><strong>SRP (Single Responsibility Principle)</strong>: Some responsibilities can be combined if they always change together.</li>
<li><strong>OCP (Open-Closed Principle)</strong>: Sometimes modifying a class is more maintainable than excessive abstractions.</li>
<li><strong>LSP (Liskov Substitution Principle)</strong>: If a subclass needs excessive modifications, reconsider the inheritance structure.</li>
<li><strong>ISP (Interface Segregation Principle)</strong>: Avoid creating too many interfaces that fragment business logic.</li>
<li><strong>DIP (Dependency Inversion Principle)</strong>: Use abstractions but avoid forcing yourself to abstract every dependency.</li>
</ul>
<hr />
<h2><a href="https://dev.to/suckup_de/solid-principles-from-paw-patrol-to-linux-penguins-379b-temp-slug-530584/edit#final-thought-the-futureproof-developer-mindset" name="final-thought-the-futureproof-developer-mindset"></a><strong>Final Thought: The &#8220;Future-Proof&#8221; Developer Mindset</strong></h2>
<ul>
<li><strong>Principles exist to serve the software, not the other way around.</strong></li>
<li><strong>Code should evolve naturally</strong>, following real needs instead of speculative complexity.</li>
<li><strong>Naming is critical</strong>, not just for variables but for abstract concepts that help us discuss software design effectively.</li>
<li><strong>Abstractions are a tool</strong>, not a requirement—sometimes, copy-pasting is the best decision.</li>
<li><strong>Balance pragmatism with best practices</strong>, and don’t fear breaking SOLID rules <strong>if it makes the code better</strong>.</li>
</ul>
<p>By combining <strong>deep technical knowledge</strong> with <strong>practical experience</strong>, we can write software that is both maintainable and efficient—without falling into the traps of over-engineering or unnecessary complexity. Happy coding!</p>
</div>
</div>
</article>
</div>
<div id="editor-actions" class="crayons-article-form__footer"><button class="c-btn c-btn--primary mr-2 whitespace-nowrap" type="button">Save changes</button></div>
</form></main></div>
</div>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fsolid-principles-from-paw-patrol-to-linux-penguin%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dsolid-principles-from-paw-patrol-to-linux-penguin&amp;action_name=SOLID+Principles%3A+From+Paw+Patrol+to+the+Neighborhood&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/01/solid-principles-from-paw-patrol-to-linux-penguin/?pk_campaign=feed&amp;pk_kwd=solid-principles-from-paw-patrol-to-linux-penguin/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6962</post-id>	</item>
		<item>
		<title>Why Agile Won’t Fix Your Project</title>
		<link>http://suckup.de/2025/01/why-agile-wont-fix-your-project/?pk_campaign=feed&amp;pk_kwd=why-agile-wont-fix-your-project&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=why-agile-wont-fix-your-project</link>
					<comments>http://suckup.de/2025/01/why-agile-wont-fix-your-project/?pk_campaign=feed&amp;pk_kwd=why-agile-wont-fix-your-project#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Fri, 24 Jan 2025 01:09:16 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6948</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/01/why-agile-wont-fix-your-project/?pk_campaign=feed&#038;pk_kwd=why-agile-wont-fix-your-project">Why Agile Won’t Fix Your Project</a></p>
<p>We’ve all heard the promises of Agile: faster delivery, more flexibility, and a better team dynamic. But let’s face it—Agile won’t save your project if the foundation isn’t right. Frameworks are tools, not magic wands, and success depends on one key factor: your people. Without commitment, purpose, and vision, even the best methodology falls flat. &#8230; <a href="http://suckup.de/2025/01/why-agile-wont-fix-your-project/?pk_campaign=feed&#038;pk_kwd=why-agile-wont-fix-your-project" class="more-link">Continue reading <span class="screen-reader-text">Why Agile Won’t Fix Your Project</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fwhy-agile-wont-fix-your-project%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhy-agile-wont-fix-your-project&amp;action_name=Why+Agile+Won%E2%80%99t+Fix+Your+Project&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/01/why-agile-wont-fix-your-project/?pk_campaign=feed&#038;pk_kwd=why-agile-wont-fix-your-project">Why Agile Won’t Fix Your Project</a></p>

<p>We’ve all heard the promises of Agile: faster delivery, more flexibility, and a better team dynamic. But let’s face it—Agile won’t save your project if the foundation isn’t right. Frameworks are tools, not magic wands, and success depends on one key factor: your people. Without commitment, purpose, and vision, even the best methodology falls flat.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Commitment Is the Foundation</strong></h3>



<p>In every successful project I’ve seen, there’s one constant: the team cares. They’re passionate about the project, the technology, or the customer. When people are engaged, they bring their A-game. Without that commitment, Agile rituals become hollow motions—stand-ups where no one stands up for quality and retrospectives that only scratch the surface.</p>



<p>But how do you ignite that spark?</p>



<ul class="wp-block-list">
<li><strong>Give Purpose:</strong> Teams perform better when they know why their work matters. Whether it’s a product that changes lives or a system that transforms workflows, connect the dots between their efforts and the bigger picture.</li>



<li><strong>Empower Ownership:</strong> Nothing kills commitment faster than micromanagement. Give your team the autonomy to solve problems their way, and they’ll take pride in their work.</li>



<li><strong>Set the North Star:</strong> Someone needs to have the big picture in mind. This isn’t about controlling every detail; it’s about providing clarity and direction. A team without a vision is just a group of people checking tasks off a backlog.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Agile: A Framework, Not a Fix</strong></h3>



<p>Agile isn’t inherently bad—it’s just not a silver bullet. A poorly implemented Agile process can feel like busy work, creating friction instead of flow. You’ve seen it: endless sprints with no tangible value, misaligned priorities, and teams that are Agile in name only.</p>



<p>The truth is, Agile is just a tool, and like any tool, its effectiveness depends on how you use it. Without the right culture, mindset, and leadership, Agile can’t thrive.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>The Power of Flow</strong></h3>



<p>When your team is committed and has a clear purpose, they enter the elusive “flow” state. Flow is where the magic happens: work feels both challenging and enjoyable, and everything just clicks. Achieving flow requires more than process—it demands an environment that fosters focus, removes blockers, and aligns everyone toward shared goals.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Common Pitfalls in Agile Projects</strong></h3>



<ul class="wp-block-list">
<li><strong>Lack of Vision:</strong> If the goals are unclear, the team loses direction. Agile iterations can’t compensate for a missing strategy.</li>



<li><strong>Token Empowerment:</strong> Teams are told they’re empowered, but their decisions are constantly overridden by management.</li>



<li><strong>Process Over People:</strong> Agile becomes a checkbox exercise, focusing on rituals instead of outcomes.</li>



<li><strong>Burnout Culture:</strong> Passion doesn’t mean working endless hours. A healthy pace is critical for long-term success.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Building the Right Environment</strong></h3>



<p>Here’s what makes the difference:</p>



<ol class="wp-block-list">
<li><strong>Clarity and Direction</strong>: Define a clear vision and align the team’s work with it. Avoid vague objectives—make the goals tangible and achievable.</li>



<li><strong>Purposeful Leadership</strong>: Leaders need to support, not control. Their role is to remove obstacles, align efforts, and amplify strengths.</li>



<li><strong>Empowerment</strong>: Trust your team to make decisions. Give them the tools, autonomy, and confidence to innovate.</li>



<li><strong>Continuous Reflection</strong>: Agile emphasizes improvement, but that requires honesty. Create a safe space for open feedback and genuine introspection.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Final Thoughts: Commitment Over Process</strong></h3>



<p>At the end of the day, success isn’t about following Agile to the letter. It’s about creating an environment where your team thrives. Agility is just one piece of the puzzle. Your team’s commitment, passion, and purpose are what truly drive results.</p>



<p>So don’t just “go Agile.” Build a culture that values people over processes, outcomes over rituals, and vision over micromanagement. Agile might not save your project, but your team will.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Because in the end, your people are your greatest asset.</strong></p>


<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fwhy-agile-wont-fix-your-project%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhy-agile-wont-fix-your-project&amp;action_name=Why+Agile+Won%E2%80%99t+Fix+Your+Project&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/01/why-agile-wont-fix-your-project/?pk_campaign=feed&amp;pk_kwd=why-agile-wont-fix-your-project/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6948</post-id>	</item>
		<item>
		<title>LLM Prompt Optimizations: Practical Techniques for Developers</title>
		<link>http://suckup.de/2025/01/llm-prompt-optimizations-practical-techniques-for-developers/?pk_campaign=feed&amp;pk_kwd=llm-prompt-optimizations-practical-techniques-for-developers&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=llm-prompt-optimizations-practical-techniques-for-developers</link>
					<comments>http://suckup.de/2025/01/llm-prompt-optimizations-practical-techniques-for-developers/?pk_campaign=feed&amp;pk_kwd=llm-prompt-optimizations-practical-techniques-for-developers#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Fri, 24 Jan 2025 00:16:57 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[LLM]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6940</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/01/llm-prompt-optimizations-practical-techniques-for-developers/?pk_campaign=feed&#038;pk_kwd=llm-prompt-optimizations-practical-techniques-for-developers">LLM Prompt Optimizations: Practical Techniques for Developers</a></p>
<p>Optimizing inputs for LLMs ensures better, more consistent outputs while leveraging the full potential of the model&#8217;s underlying capabilities. By understanding core concepts like tokenization, embeddings, self-attention, and context limits, you can tailor inputs to achieve desired outcomes reliably. Below, you&#8217;ll find fundamental techniques and best practices organized into practical strategies. PS: You can use &#8230; <a href="http://suckup.de/2025/01/llm-prompt-optimizations-practical-techniques-for-developers/?pk_campaign=feed&#038;pk_kwd=llm-prompt-optimizations-practical-techniques-for-developers" class="more-link">Continue reading <span class="screen-reader-text">LLM Prompt Optimizations: Practical Techniques for Developers</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fllm-prompt-optimizations-practical-techniques-for-developers%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dllm-prompt-optimizations-practical-techniques-for-developers&amp;action_name=LLM+Prompt+Optimizations%3A+Practical+Techniques+for+Developers&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/01/llm-prompt-optimizations-practical-techniques-for-developers/?pk_campaign=feed&#038;pk_kwd=llm-prompt-optimizations-practical-techniques-for-developers">LLM Prompt Optimizations: Practical Techniques for Developers</a></p>

<p>Optimizing inputs for LLMs ensures better, more consistent outputs while leveraging the full potential of the model&#8217;s underlying capabilities. By understanding core concepts like tokenization, embeddings, self-attention, and context limits, you can tailor inputs to achieve desired outcomes reliably. Below, you&#8217;ll find fundamental techniques and best practices organized into practical strategies.</p>



<p>PS: You can use this content to automatically improve your prompt by asking as follows: <a class="THGLZiYzqWGWKdttMOgKMIHkarZmDticds " href="https://chatgpt.com/share/6785a41d-72a0-8002-a1fe-52c14a5fb1e5" target="_self" data-test-app-aware-link="">https://chatgpt.com/share/6785a41d-72a0-8002-a1fe-52c14a5fb1e5</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 1. Controlling Probabilities: Guide Model Outputs</h3>



<p><a href="#-1-controlling-probabilities-guide-model-outputs"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong> LLMs always follow probabilities when generating text. For every token, the model calculates a probability distribution based on the context provided. By carefully structuring inputs or presenting examples, we can shift the probabilities toward the desired outcome:</p>



<ul class="wp-block-list">
<li>Providing more examples helps the model identify patterns and generate similar outputs.</li>



<li>Clear instructions reduce ambiguity, increasing the probability of generating focused responses.</li>



<li>Contextual clues and specific phrasing subtly guide the model to prioritize certain outputs.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong> The model operates using token probabilities:</p>



<ul class="wp-block-list">
<li>Each token (word or part of a word) is assigned a likelihood based on the input context.</li>



<li>By influencing the input, we can make certain tokens more likely to appear in the output.</li>
</ul>



<p>For example:</p>



<ul class="wp-block-list">
<li>A general query like &#8220;Explain energy sources&#8221; might distribute probabilities evenly across different energy types.</li>



<li>A more specific query like &#8220;Explain why solar energy is sustainable&#8221; shifts the probabilities toward solar-related tokens.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Shifting Probabilities in Prompts:</strong> The structure and wording of your prompt significantly influence the token probabilities:</p>



<ul class="wp-block-list">
<li><strong>For specific outputs:</strong> Use targeted phrasing to increase the likelihood of desired responses: <code>Explain why renewable energy reduces greenhouse gas emissions.</code></li>



<li><strong>For diverse outputs:</strong> Frame open-ended questions to distribute probabilities across a broader range of topics: <code>What are the different ways to generate clean energy?</code></li>



<li><strong>Few-Shot Learning:</strong> Guide the model using few-shot learning to set patterns: <code>Example 1: Input: Solar energy converts sunlight into electricity. Output: Solar energy is a renewable power source. Example 2: Input: Wind energy generates power using turbines. Output: Wind energy is clean and sustainable. Task: Input: Hydropower generates electricity from flowing water. Output:</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>Use clear, direct instructions for precise outputs: <code>Write a PHP function that adds two integers and returns a structured response as an array.</code></li>



<li>Use contextual clues to steer the response: <code>Explain why PHP is particularly suited for web development.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> LLMs break down code and comments into tokens, so structuring your PHPDocs helps focus probabilities effectively. Provide clarity and guidance through structured documentation:</p>



<pre class="wp-block-preformatted">/**
 * Adds two integers and returns a structured response.
 *
 * @param int $a The first number.
 * @param int $b The second number.
 * 
 * @return array{result: int, message: string} A structured response with the sum and a message.
 */
function addIntegers(int $a, int $b): array {
    $sum = $a + $b;

    return [
        'result' =&gt; $sum,
        'message' =&gt; "The sum of $a and $b is $sum."
    ];
}</pre>



<ul class="wp-block-list">
<li>Include examples in PHPDocs to further refine the probabilities of correct completions: /** * Example: * Input: addIntegers(3, 5) * Output: [&#8216;result&#8217; => 8, &#8216;message&#8217; => &#8216;The sum of 3 and 5 is 8&#8217;] */</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2702.png" alt="✂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 2. Tokenization and Embeddings: Use Context Efficiently</h3>



<p><a href="#-2-tokenization-and-embeddings-use-context-efficiently"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong> LLMs break down words into tokens (numbers) to relate them to each other in multidimensional embeddings (vectors). The more meaningful context you provide, the better the model can interpret relationships and generate accurate outputs:</p>



<ul class="wp-block-list">
<li>Tokens like &#8220;renewable energy&#8221; and &#8220;sustainability&#8221; have semantic proximity in the embedding space.</li>



<li>More context allows the model to generate richer and more coherent responses.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li>Tokens are the smallest units the model processes. For example, &#8220;solar&#8221; and &#8220;energy&#8221; may be separate tokens, or in compound languages like German, one long word might be broken into multiple tokens.</li>



<li>Embeddings map these tokens into vectors, enabling the model to identify their relationships in high-dimensional space.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Optimizing Tokenization in Prompts:</strong> To make the most of tokenization and embeddings:</p>



<ul class="wp-block-list">
<li><strong>Minimize irrelevant tokens:</strong> Focus on core concepts and avoid verbose instructions.</li>



<li><strong>Include context-rich phrases:</strong> Relevant terms improve the embedding connections.</li>



<li><strong>Simplify Language:</strong> Use concise phrasing to minimize token count: <code>Solar energy is renewable and reduces emissions.</code></li>



<li><strong>Remove Redundancy:</strong> Eliminate repeated or unnecessary words: <code>Explain why solar energy is sustainable.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>Include only essential terms for better embedding proximity: <code>Describe how solar panels generate electricity using photovoltaic cells.</code></li>



<li>Avoid vague or verbose phrasing: <code>Explain solar energy and its uses in a way that a normal person can understand and provide details.</code></li>



<li>Use specific language to avoid diluting the context: <code>Explain why solar energy is considered environmentally friendly and cost-effective.</code></li>



<li>Avoid vague instructions that lack actionable context: <code>Explain me solar energy.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> Write compact and clear PHPDocs to save tokens and improve context:</p>



<pre class="wp-block-preformatted">/**
 * Converts raw user input into a structured format.
 *
 * @param string $input Raw input data.
 * 
 * @return array{key: int, value: string} Structured output.
 */
function parseInput(string $input): array {
    $parts = explode(":", $input);

    return [
        'key' =&gt; (int)$parts[0],
        'value' =&gt; trim($parts[1])
    ];
}</pre>



<ul class="wp-block-list">
<li>Use compact and descriptive documentation to maximize token efficiency: /** * Example: * Input: &#8220;42:Hello&#8221; * Output: [&#8216;foo&#8217; => 42, &#8216;bar&#8217; => &#8216;Hello&#8217;] */</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ed.png" alt="🧭" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 3. Self-Attention and Structure: Prioritize Context</h3>



<p><a href="#-3-self-attention-and-structure-prioritize-context"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong> LLMs work with the principle of <a href="https://towardsdatascience.com/deep-dive-into-self-attention-by-hand-%EF%B8%8E-f02876e49857" target="_blank" rel="noreferrer noopener nofollow">self-attention</a>, where the input tokens are interrelated with each other to determine the relevance and context. This mechanism assigns importance scores to tokens, ensuring that the most relevant words and their relationships are prioritized.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li><strong>Self-attention layers:</strong> Compare each token with every other token in the input to generate an attention score.</li>



<li><strong>Multi-head attention:</strong> Allows the model to consider multiple perspectives simultaneously, balancing relevance and context.</li>



<li><strong>Pitfall:</strong> Too many irrelevant tokens dilute the attention scores, leading to distorted outputs.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Optimizing Structure in Prompts:</strong></p>



<ul class="wp-block-list">
<li><strong>Structure Your Inputs:</strong> Use lists, steps, or sections to emphasize relationships: <code>Compare the benefits of solar and wind energy: 1. Environmental impact 2. Cost-efficiency 3. Scalability</code></li>



<li><strong>Minimize Irrelevant Tokens:</strong> Keep prompts focused and free from extraneous details.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li><strong>Well-Structured:</strong> Organize tasks into sections: <code>Explain the environmental and economic benefits of renewable energy in two sections: 1. Environmental 2. Economic</code></li>



<li><strong>Unstructured:</strong> Avoid asking everything at once: <code>What are the environmental and economic benefits of renewable energy?</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> In PHPDocs, organize information logically to enhance clarity and guide models effectively:</p>



<pre class="wp-block-preformatted">/**
 * Calculates the cost efficiency of renewable energy.
 *
 * Steps:
 * 1. Evaluate savings-to-investment ratio.
 * 2. Return a percentage efficiency score.
 *
 * @param float $investment Initial investment cost.
 * @param float $savings Annual savings.
 * 
 * @return float Efficiency percentage.
 */
function calculateEfficiency(float $investment, float $savings): float {
    return ($savings / $investment) * 100;
}</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f9.png" alt="🧹" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 4. Context Management and Token Limits</h3>



<p><a href="#-4-context-management-and-token-limits"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong> LLMs operate within a fixed token limit (e.g., ~8k tokens for GPT-4), encompassing both input and output. Efficiently managing context ensures relevant information is prioritized while avoiding irrelevant or redundant content.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li><strong>Chunking:</strong> Break long inputs into smaller, manageable parts: <code>Step 1: Summarize the introduction of the report. Step 2: Extract key arguments from Section 1. Step 3: Combine summaries for a final overview.</code></li>



<li><strong>Iterative Summarization:</strong> Condense sections before integrating them: <code>Summarize Section 1: Solar energy’s benefits. Summarize Section 2: Wind energy’s benefits. Combine both summaries.</code></li>



<li><strong>Pitfall:</strong> Excessive context can truncate critical data due to token limits.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>For large inputs, use step-by-step processing: <code>Step 1: Summarize the introduction of the document. Step 2: Extract key arguments from Section 1. Step 3: Combine these points into a cohesive summary.</code></li>



<li>Avoid presenting the full text in a single prompt: <code>Summarize this 20-page document.</code></li>



<li>Focus on specific sections or tasks: <code>Summarize the introduction and key points from Section 1.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> Divide tasks into smaller functions to handle token limits better:</p>



<pre class="wp-block-preformatted">function summarizeSection(string $section): string {
    // Summarize section content.
}

function combineSummaries(array $summaries): string {
    // Merge individual summaries.
}</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3a8.png" alt="🎨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 5. Reasoning and Goals: Strengthen Prompt Direction</h3>



<p><a href="#-5-reasoning-and-goals-strengthen-prompt-direction"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong> LLMs generate better results when the reasoning behind a task and its intended goal are explicitly stated. This guides the model&#8217;s probabilities toward meaningful and relevant outcomes.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li>Explicit reasoning provides semantic depth, helping the model focus on the task’s purpose.</li>



<li>Explaining the goal improves alignment with user expectations and narrows token probabilities.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>State the reason for the task and its goal: <code>Explain renewable energy because I need to create an introductory guide for high school students.</code></li>



<li>Avoid generic prompts without a clear goal: <code>Describe renewable energy.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> Use PHPDocs to explain both the reasoning and expected outcomes of a function:</p>



<pre class="wp-block-preformatted">/**
 * Generates a detailed user profile report.
 *
 * This function is designed to create a comprehensive profile report based on user data inputs. 
 * It is useful for analytical dashboards requiring well-structured user insights.
 *
 * @param array{name: string, age: int, email: string} $userData The user data array.
 * 
 * @return string A formatted profile report.
 */
function generateProfileReport(array $userData): string {
    return sprintf(
        "User Profile:\nName: %s\nAge: %d\nEmail: %s\n",
        $userData['name'],
        $userData['age'],
        $userData['email']
    );
}</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 6. Iterative Refinement: Simplify Complex Tasks</h3>



<p><a href="#-6-iterative-refinement-simplify-complex-tasks"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong><br />Breaking down complex tasks into smaller, manageable steps improves accuracy and ensures the model generates focused and coherent outputs. This method allows you to iteratively refine results, combining outputs from smaller subtasks into a complete solution.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li><strong>Chunking:</strong> Split large tasks into multiple smaller ones to avoid overwhelming the model.</li>



<li><strong>Validation:</strong> Intermediate outputs can be validated before moving to the next step, minimizing errors.</li>



<li><strong>Recombination:</strong> Smaller validated outputs are merged for the final result.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>For multi-step tasks, provide clear, incremental instructions: <code>Step 1: Summarize the environmental benefits of solar energy. Step 2: Describe the cost savings associated with solar energy. Step 3: Combine these summaries into a single paragraph.</code></li>



<li>Avoid handling complex tasks in a single step: <code>Explain the environmental benefits and cost savings of solar energy in one response.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> Ask the LLM to create the code step by step and ask for confirmation after each step so that the LLM can focus on one aspect of the implementation at a time. Focus on one aspect of the implementation at a time.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 7. Cross-Contextual Coherence: Maintain Consistency</h3>



<p><a href="#-7-cross-contextual-coherence-maintain-consistency"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong><br />LLMs lack persistent memory between interactions, making it essential to reintroduce necessary context for consistent responses across prompts. By maintaining cross-contextual coherence, outputs remain aligned and relevant, even in multi-step interactions.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li>Use <strong>context bridging</strong>: Reference key elements from previous responses to maintain relevance.</li>



<li>Store critical details in persistent structures, such as arrays or JSON, to reintroduce when needed.</li>



<li>Avoid overloading with irrelevant details, which can dilute coherence.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>Reintroduce essential context from previous interactions: <code>Based on our discussion about renewable energy, specifically solar power, explain the benefits of wind energy.</code></li>



<li>Summarize intermediate outputs for clarity: <code>Summarize the main benefits of renewable energy. Then expand on solar and wind energy.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> Use seperated files for Code-Examples that we can provide e.g. <code>Custom GPTs</code> so it can learn from learnings/findings this way.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 8. Style and Tone: Adapt Outputs to the Audience</h3>



<p><a href="#-8-style-and-tone-adapt-outputs-to-the-audience"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong> LLMs generate better responses when the desired style and tone are explicitly stated. By matching the tone to the audience, you can make content more engaging and effective.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li>The model uses semantic cues in the prompt to adjust style and tone.</li>



<li>Specific words and phrases like &#8220;formal,&#8221; &#8220;casual,&#8221; or &#8220;technical&#8221; help steer the model’s output.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>Specify the tone and audience: <code>Write a technical explanation of solar panels for an engineering audience.</code></li>



<li>Adjust the style for different contexts: <code>Explain solar panels in a simple and friendly tone for kids.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> In PHPDocs, define the intended audience and tone to guide LLM-generated documentation:</p>



<pre class="wp-block-preformatted">/**
 * Calculates the total energy output of a solar panel system.
 *
 * Intended Audience: Engineers and technical experts.
 * Tone: Formal and technical.
 *
 * @param float $panelArea The total area of solar panels in square meters.
 * @param float $efficiency The efficiency rate of the solar panels (0-1).
 * @param float $sunlightHours Daily sunlight hours.
 * 
 * @return float Total energy output in kilowatt-hours.
 */
function calculateSolarOutput(float $panelArea, float $efficiency, float $sunlightHours): float {
    return $panelArea * $efficiency * $sunlightHours;
}</pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 9. Fine-Tuning and Domain Expertise</h3>



<p><a href="#-9-fine-tuning-and-domain-expertise"></a></p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Theory:</strong> Fine-tuning allows LLMs to specialize in specific domains by further training them on domain-specific datasets. This enhances their ability to generate accurate, relevant, and nuanced outputs tailored to specialized tasks or fields.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2699.png" alt="⚙" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Technology:</strong></p>



<ul class="wp-block-list">
<li>Fine-tuning adjusts the weights of a pre-trained model by using a curated dataset that focuses on a specific domain.</li>



<li>This process requires labeled data and computational resources but significantly improves task performance in niche areas.</li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prompt Tips:</strong></p>



<ul class="wp-block-list">
<li>Use fine-tuning to simplify prompts for repeated tasks: <code>Generate a legal brief summarizing the key points from this case.</code></li>



<li>Without fine-tuning, include detailed instructions and examples in your prompt: <code>Write a summary of this legal case focusing on liability and negligence, using a formal tone.</code></li>
</ul>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Code Tips:</strong> When fine-tuning is not an option, structure your PHPDocs to include domain-specific context for LLMs:</p>



<pre class="wp-block-preformatted">/**
 * Generates a compliance report for renewable energy projects.
 *
 * This function creates a detailed compliance report tailored for regulatory agencies. It checks for adherence to
 * energy efficiency standards and sustainability guidelines.
 *
 * @param array&lt;string, mixed&gt; $projectData Details of the renewable energy project.
 * @param string $region The region for which the compliance report is generated.
 * 
 * @return string The compliance report in a formatted string.
 */
function generateComplianceReport(array $projectData, string $region): string {
    // Example report generation logic.
    return sprintf(
        "Compliance Report for %s:\nProject: %s\nStatus: %s\n",
        $region,
        $projectData['name'] ?? 'Unnamed Project',
        $projectData['status'] ?? 'Pending Review'
    );
}</pre>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fllm-prompt-optimizations-practical-techniques-for-developers%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dllm-prompt-optimizations-practical-techniques-for-developers&amp;action_name=LLM+Prompt+Optimizations%3A+Practical+Techniques+for+Developers&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/01/llm-prompt-optimizations-practical-techniques-for-developers/?pk_campaign=feed&amp;pk_kwd=llm-prompt-optimizations-practical-techniques-for-developers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6940</post-id>	</item>
		<item>
		<title>The Wild West of Coding: Why We’re Still Burning Digital Cities</title>
		<link>http://suckup.de/2025/01/the-wild-west-of-coding-why-were-still-burning-digital-cities/?pk_campaign=feed&amp;pk_kwd=the-wild-west-of-coding-why-were-still-burning-digital-cities&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=the-wild-west-of-coding-why-were-still-burning-digital-cities</link>
					<comments>http://suckup.de/2025/01/the-wild-west-of-coding-why-were-still-burning-digital-cities/?pk_campaign=feed&amp;pk_kwd=the-wild-west-of-coding-why-were-still-burning-digital-cities#comments</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Thu, 23 Jan 2025 23:57:41 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6935</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2025/01/the-wild-west-of-coding-why-were-still-burning-digital-cities/?pk_campaign=feed&#038;pk_kwd=the-wild-west-of-coding-why-were-still-burning-digital-cities">The Wild West of Coding: Why We’re Still Burning Digital Cities</a></p>
<p>The year 2050 is closer than the year 1990, yet we’re still writing code like it’s the 1800s. It’s 2025, and while we’ve made incredible strides in software development—automated memory management, static analysis tools, refactoring IDEs, and AI copilots like ChatGPT—it still feels like the Wild West. Sure, the tools are better, but the way &#8230; <a href="http://suckup.de/2025/01/the-wild-west-of-coding-why-were-still-burning-digital-cities/?pk_campaign=feed&#038;pk_kwd=the-wild-west-of-coding-why-were-still-burning-digital-cities" class="more-link">Continue reading <span class="screen-reader-text">The Wild West of Coding: Why We’re Still Burning Digital Cities</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fthe-wild-west-of-coding-why-were-still-burning-digital-cities%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dthe-wild-west-of-coding-why-were-still-burning-digital-cities&amp;action_name=The+Wild+West+of+Coding%3A+Why+We%E2%80%99re+Still+Burning+Digital+Cities&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2025/01/the-wild-west-of-coding-why-were-still-burning-digital-cities/?pk_campaign=feed&#038;pk_kwd=the-wild-west-of-coding-why-were-still-burning-digital-cities">The Wild West of Coding: Why We’re Still Burning Digital Cities</a></p>

<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>The year 2050 is closer than the year 1990, yet we’re still writing code like it’s the 1800s.</p>



<p>It’s 2025, and while we’ve made incredible strides in software development—automated memory management, static analysis tools, refactoring IDEs, and AI copilots like ChatGPT—it still feels like the Wild West. Sure, the tools are better, but the way we approach software remains chaotic, inefficient, and overly reliant on custom solutions.</p>



<p>Every day, thousands of developers solve the same problems repeatedly. Companies roll out their own authentication systems, file upload handlers, and error trackers. Many of these are flawed. Vulnerabilities creep in because we’re not building resilient systems—we’re building digital bonfires.</p>



<p>This isn’t progress. This is the time before the First Industrial Revolution of Software Development.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Lessons from History: What the Past Teaches About Our Digital Fires</strong></h3>



<h4 class="wp-block-heading"><strong>1. The Great Fire of Hamburg (1842): Building Without Safety</strong></h4>



<p>In 1842, a quarter of Hamburg burned to the ground. The city’s lack of fire safety standards—wooden buildings, narrow streets, no prevention systems—made disaster inevitable.</p>



<p>Software today mirrors this recklessness:</p>



<ul class="wp-block-list">
<li>File upload systems without malware checks.</li>



<li>APIs with vulnerabilities because “it’s faster to skip security.”</li>



<li>Custom-built logging systems without consistency or reliability.</li>
</ul>



<p>After the fire, Hamburg rebuilt with fireproof materials and strict regulations. We need the same shift in software development: adopting <strong>universal standards</strong>, <strong>secure-by-design frameworks</strong>, and <strong>centralized tools</strong> to prevent disaster before it happens.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>2. Electrical Sockets in the Early 1900s: Chaos Without Standards</strong></h4>



<p>Before standardization, electrical sockets were a mess. Every region had its own plug type, making interoperability nearly impossible. Plugging in a device often meant wasting time finding the right adapter.</p>



<p>Software development today is no different:</p>



<ul class="wp-block-list">
<li>APIs lack consistent patterns.</li>



<li>Libraries solve the same problem in incompatible ways.</li>



<li>Developers reinvent logging, error handling, and authentication with every project.</li>
</ul>



<p>The solution? <strong>Standardized, language-agnostic tools</strong>—the equivalent of universal plug designs. Imagine APIs and services that integrate seamlessly across languages and frameworks:</p>



<ul class="wp-block-list">
<li>Centralized <strong>logging and error tracking APIs</strong>, similar to Sentry but designed for internal use with cross-language compatibility.</li>



<li>High-performance <strong>Unix socket APIs</strong> for tasks like logging, monitoring, and file scanning.</li>



<li>Shared SDKs for foundational needs like security or metrics collection.</li>
</ul>



<p>By building shared infrastructure, we could eliminate redundant work and improve reliability across projects.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading"><strong>3. The Facade Problem: Buying Software for Looks, Not Stability</strong></h4>



<p>Imagine buying a house because the facade looks amazing but never checking the foundation. That’s how most software is evaluated today:</p>



<ul class="wp-block-list">
<li>Buyers focus on flashy UIs and marketing demos.</li>



<li>Security, scalability, and maintainability are often ignored.</li>
</ul>



<p>This approach leads to brittle, insecure systems. What’s missing? <strong>Inspectors for digital bridges</strong>—specialized roles that assess software foundations, enforce accountability, and ensure systems are solid beneath their shiny exteriors.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Moving Toward the First Industrial Revolution of Software Development</strong></h3>



<p>The Industrial Revolution replaced handcrafting with standardization and mass production. Software development is still stuck in its pre-industrial phase:</p>



<ul class="wp-block-list">
<li>Custom solutions are built repeatedly for the same problems.</li>



<li>Accountability is rare—no one ensures the &#8220;bridge&#8221; (software) is stable before it’s deployed.</li>
</ul>



<p>To mature as an industry, we need:</p>



<h4 class="wp-block-heading"><strong>1. Universal Blueprints</strong></h4>



<p>Developers today still create bespoke solutions for common problems. We need standardized tools and APIs, such as:</p>



<ul class="wp-block-list">
<li>A <strong>unified SDK for antivirus scanning</strong>, accessible via <code>/usr/sbin/antivirus</code> or <code>unix:///var/run/antivirus</code>.</li>



<li>Centralized APIs for error tracking, metrics, and monitoring, with cross-language support.</li>
</ul>



<h4 class="wp-block-heading"><strong>2. Specialized Roles</strong></h4>



<p>In the 19th century, collapsing bridges led to the creation of specialized roles: architects for design, builders for execution, and inspectors for safety. Software teams need similar specialization:</p>



<ul class="wp-block-list">
<li><strong>System Inspectors</strong> to evaluate software for security, scalability, and maintainability.</li>



<li><strong>Digital Firefighters</strong> to enforce standards and proactively address vulnerabilities.</li>
</ul>



<h4 class="wp-block-heading"><strong>3. Accountability</strong></h4>



<p>When a bridge collapses, someone is held responsible. In software, failures are often patched silently or ignored. We need:</p>



<ul class="wp-block-list">
<li>Transparency: Bugs and vulnerabilities must be documented openly.</li>



<li>Retrospectives: Focused on systemic improvements, not just quick fixes.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Building Digital Cities That Don’t Burn</strong></h3>



<p>Imagine a future where software is built like modern cities:</p>



<ul class="wp-block-list">
<li><strong>Fireproof Systems</strong>: Universal standards for security, maintainability, and testing.</li>



<li><strong>Digital Firefighters</strong>: Publicly funded teams safeguarding critical infrastructure.</li>



<li><strong>Inspectors for Digital Bridges</strong>: Specialized roles ensuring software is built to last.</li>
</ul>



<p>AI tools like GPT can help accelerate this process, but they are not the solution. AI is like the steam engine of programming—amplifying productivity but requiring skilled operators. If we don’t lay the right foundations, AI will only magnify our inefficiencies.</p>



<p>This future isn’t about writing more code—it’s about creating <strong>resilient, scalable systems</strong> that stand the test of time. The tools to build fireproof digital cities are already here. The question is: are we ready to use them?</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Let’s move beyond the Wild West of coding and into the Industrial Revolution our industry desperately needs. It’s time to stop building bonfires and start building something that lasts.</p>


<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2025%2F01%2Fthe-wild-west-of-coding-why-were-still-burning-digital-cities%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dthe-wild-west-of-coding-why-were-still-burning-digital-cities&amp;action_name=The+Wild+West+of+Coding%3A+Why+We%E2%80%99re+Still+Burning+Digital+Cities&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2025/01/the-wild-west-of-coding-why-were-still-burning-digital-cities/?pk_campaign=feed&amp;pk_kwd=the-wild-west-of-coding-why-were-still-burning-digital-cities/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6935</post-id>	</item>
		<item>
		<title>Legacy Codebase: A Love Story</title>
		<link>http://suckup.de/2023/01/legacy-codebase-a-love-story/?pk_campaign=feed&amp;pk_kwd=legacy-codebase-a-love-story&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=legacy-codebase-a-love-story</link>
					<comments>http://suckup.de/2023/01/legacy-codebase-a-love-story/?pk_campaign=feed&amp;pk_kwd=legacy-codebase-a-love-story#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Wed, 04 Jan 2023 01:45:22 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6911</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2023/01/legacy-codebase-a-love-story/?pk_campaign=feed&#038;pk_kwd=legacy-codebase-a-love-story">Legacy Codebase: A Love Story</a></p>
<p>After some years, working with a > 10 years old legacy PHP codebase, I can truly say: you can escape the legacy codebase and introduce whatever is helpful, in a well-maintained system. Here are 5 important steps that I have done: Here are 5 additional steps that I already introduce: Here is what helped me &#8230; <a href="http://suckup.de/2023/01/legacy-codebase-a-love-story/?pk_campaign=feed&#038;pk_kwd=legacy-codebase-a-love-story" class="more-link">Continue reading <span class="screen-reader-text">Legacy Codebase: A Love Story</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2023%2F01%2Flegacy-codebase-a-love-story%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dlegacy-codebase-a-love-story&amp;action_name=Legacy+Codebase%3A+A+Love+Story&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2023/01/legacy-codebase-a-love-story/?pk_campaign=feed&#038;pk_kwd=legacy-codebase-a-love-story">Legacy Codebase: A Love Story</a></p>

<p>After some years, working with a > 10 years old legacy PHP codebase, I can truly say: you can escape the legacy codebase and introduce whatever is helpful, in a well-maintained system. </p>



<p>Here are <strong>5</strong> important steps that I have done:</p>



<ul class="wp-block-list">
<li> <strong>Custom error handling</strong>: Reporting notices for developers, report bad &#8220;assert&#8221; calls in the dev container, report bad indexes, reporting wrong code usage, &#8230;</li>



<li><strong>Autocompletion for everything</strong>: classes, properties, SQL queries, CSS, HTML, JavaScript in PHP (e.g. via /* @lang JavaScript */ in PhpStorm), &#8230;</li>



<li><strong>Static-Code Analysis</strong>: Preventing bugs is even better than fixing bugs, so just stop stupid bugs and use types in your code.</li>



<li><strong>Automate the refactoring</strong>: With tools like PHP-CS-Fixer or Rector you can not only fix your code one time, you can fix any future wrong usage of the code.</li>



<li><strong>Do not use strings for code</strong>: Just use constants, classes, properties, &#8230; use something that can be processes by your static-code analysis and something where you will have autocompletion.  </li>
</ul>



<p></p>



<p>Here are <strong>5</strong> additional steps that I already introduce:</p>



<ul class="wp-block-list">
<li><strong>Sentry</strong>: External error collecting (aggregating) tool + custom handler to see e.g. IDs of every Active Record object.</li>



<li><strong>Generics</strong>: via PHPDocs + autocompletion via PhpStorm</li>



<li><strong>No &#8220;mixed&#8221; types</strong>: Now we use something like, e.g. &#8220;array&lt;int, string>&#8221; instead of &#8220;array&#8221;.</li>



<li><strong>PSR standards</strong>: e.g. PSR-15 request handler, PSR-11 container, PSR-3 logger, &#8230; </li>



<li><strong>Code Style</strong>: One code style to rule them all, we use PHP-CS-Fixer and PHP-Code-Sniffer to check / fix our code style for all ~ 10,000 PHP classes.</li>
</ul>





<h3>Here is what helped me mostly while working with old existing code.</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>First rule, first: <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f947.png" alt="🥇" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <em>think</em> or / and ask someone in the team</p>
</blockquote>



<h4 class="wp-block-heading"><span style="text-decoration: underline;">Analyzing</span>: Here are some things that helped my analyzing software problems in our codebase.</h4>



<ul class="wp-block-list">
<li><strong>Errors:</strong> Better error handling / reporting with a custom error handler, with all relevant information.</li>



<li><strong>Understandable logging</strong>: Hint, you can just use syslog for medium-sized applications.</li>



<li><strong>Grouping errors</strong>: Displaying and grouping all the stuff (PHP / JS / errors + our own custom reports) into Sentry (<a href="https://sentry.io/" target="_blank" rel="noreferrer noopener nofollow">https://sentry.io/</a>), now you can easily see how e.g. how many customers are effected from an error.</li>



<li><strong>git history</strong>: Often new bugs were introduced with the latest changes (at least in often used components), so that good commit messages are really helpful to find this changes. (<a href="https://github.com/voku/dotfiles/wiki/git-commit-messages" target="_blank" rel="noreferrer noopener">https://github.com/voku/dotfiles/wiki/git-commit-messages</a>)</li>



<li><strong>Local containers</strong>: If you can just download the application with a database dump from yesterday, you can analyze many problems without touching any external server.</li>



<li><strong>Linux tools</strong>: mytop, strace, htop, iotop, lsof, &#8230;</li>



<li><strong>Database tools</strong>:  EXPLAIN [SQL], IDE integration / autocompletion, &#8230;</li>
</ul>



<h4 class="wp-block-heading"><span style="text-decoration: underline;">Fixing</span>: Here are some tricks for fixing existing code more easily.</h4>



<ul class="wp-block-list">
<li><strong>IDE</strong>: PhpStorm with auto-completion and suggestions (including results from static analysis)</li>



<li><strong>auto-code-style formatter</strong>: (as pre-commit hook) is also helpful because I do not need to think about this anymore while fixing code </li>



<li><strong>git stuff</strong>: sometimes it can also be helpful to understand git and how to revert or cherry-pick some changes</li>
</ul>



<h4 class="wp-block-heading"><strong><span style="text-decoration: underline;">Preventing</span></strong>: Here are some hints how you can prevent some bugs.</h4>



<ul class="wp-block-list">
<li><strong>custom static analysis rules</strong>: <a href="http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/">http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/</a></li>



<li><strong>root cause</strong>: fixing the root cause of a problem, sometimes this is very hard because you need to fully understand the problem first, bust mostly spending this time is a good investment</li>



<li><strong>testing</strong>: writing a test is always a good idea, at least to prevent the same problem</li>
</ul>





<hr />
<p><strong>Job</strong>: If you now would like to work with this codebase (PHP 8 | MySQL 8 | Ubuntu), please contact <a href="https://www.linkedin.com/in/larsmoelleken/">me</a> and take a look at this job offer: <a href="https://meerx.de/karriere/softwareentwickler-softwareentwicklerin/" target="_blank" rel="noopener">https://meerx.de/karriere/softwareentwickler-softwareentwicklerin/</a></p>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2023%2F01%2Flegacy-codebase-a-love-story%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dlegacy-codebase-a-love-story&amp;action_name=Legacy+Codebase%3A+A+Love+Story&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2023/01/legacy-codebase-a-love-story/?pk_campaign=feed&amp;pk_kwd=legacy-codebase-a-love-story/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6911</post-id>	</item>
		<item>
		<title>What have I learned so far in my job?</title>
		<link>http://suckup.de/2023/01/what-have-i-learned-so-far-in-my-job/?pk_campaign=feed&amp;pk_kwd=what-have-i-learned-so-far-in-my-job&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=what-have-i-learned-so-far-in-my-job</link>
					<comments>http://suckup.de/2023/01/what-have-i-learned-so-far-in-my-job/?pk_campaign=feed&amp;pk_kwd=what-have-i-learned-so-far-in-my-job#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Tue, 03 Jan 2023 23:55:03 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6888</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2023/01/what-have-i-learned-so-far-in-my-job/?pk_campaign=feed&#038;pk_kwd=what-have-i-learned-so-far-in-my-job">What have I learned so far in my job?</a></p>
<p>I will start a new job next month (02-2023), so time to recap, I&#8217;m going to describe what I&#8217;ve learned so far. me: Lars Moelleken &#124;> Assistant for business IT> IT specialist for system integration> IT specialist for application development What did I learn as IT specialist for system integration? – You only learn as much as &#8230; <a href="http://suckup.de/2023/01/what-have-i-learned-so-far-in-my-job/?pk_campaign=feed&#038;pk_kwd=what-have-i-learned-so-far-in-my-job" class="more-link">Continue reading <span class="screen-reader-text">What have I learned so far in my job?</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2023%2F01%2Fwhat-have-i-learned-so-far-in-my-job%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhat-have-i-learned-so-far-in-my-job&amp;action_name=What+have+I+learned+so+far+in+my+job%3F&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2023/01/what-have-i-learned-so-far-in-my-job/?pk_campaign=feed&#038;pk_kwd=what-have-i-learned-so-far-in-my-job">What have I learned so far in my job?</a></p>

<p>I will start a new job next month (02-2023), so time to recap, I&#8217;m going to describe what I&#8217;ve learned so far.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>me: <a href="https://www.linkedin.com/in/larsmoelleken/" target="_blank" rel="noreferrer noopener">Lars Moelleken</a> |</em><br /><em>> Assistant for business IT</em><br /><em>> IT specialist for system integration</em><br /><em>> IT specialist for application development</em></p>
</blockquote>



<h2 class="wp-block-heading">What did I learn as IT specialist for system integration?</h2>



<h3 class="wp-block-heading">– You only learn as much as you want to learn.</h3>



<p>In contrast to school / technical college, I could and had to teach and work on many things myself during the training.&nbsp;And you quickly realize that you only learn as much as you want.&nbsp;Once you&#8217;ve understood this, you&#8217;re happy to sit down and learn whatever you want. For example, local or online courses, go to meetups or conferences.&nbsp;Worry about your skill because if you do something, you should do it right.</p>



<p>“An investment in knowledge still pays the best interest.”&nbsp;– Benjamin Franklin</p>



<h3 class="wp-block-heading">– No panic!</h3>



<p>What you learn pretty quickly as a sysadmin is “keep calm” and think first – then act.&nbsp;Hasty actionism does not help and usually even damages.&nbsp;Before you act, you should first obtain some information yourself (information from log files, hardware status, system status, &#8230;) so that you really know how to fix the error.</p>



<h3 class="wp-block-heading">– Unix &amp; command line &lt;3</h3>



<p>If you haven&#8217;t worked with a Unix operating system before, you unfortunately don&#8217;t know what you&#8217;re missing out on.&nbsp;If you want or have to use Windows for whatever reason, you can nowadays still use some of the advantages of Linux via WSL (Windows Subsystem for Linux).&nbsp;Leave your own comfort zone and trying out new operating systems helps to understand your computer better overall.&nbsp;At this point, I would have recommended “Arch Linux” as sysadmin, but today I would choose something that needs less maintaining. </p>



<p>One should also become familiar with the command line if you want to increase your productivity rapidly.&nbsp;For example, you should take a closer look at the following commands: e.g. find / grep / lsof / strace</p>



<h3 class="wp-block-heading">– Read the official documentation.</h3>



<p>It is often better to read the official documentation of the thing (hardware || software) you are currently using.&nbsp;While you start programming or learn a new programming language / framework, we often use stackoverflow.com and quickly finds answers and code examples, but the &#8220;why&#8221; and &#8220;how&#8221; is usually neglected.&nbsp;If you look at the specification / documentation first, you not only solve this problem, you also understand the problem, and maybe you will learn how to solve similar problems.</p>



<h3 class="wp-block-heading">– Always make a backup (never use “sudo” drunken).</h3>



<p>Some things you have to learn the hard way,&nbsp;apparently installing &#8220;safe-rm&#8221; was part of it for me! </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><code>apt-get&nbsp;install safe-rm</code></p>
</blockquote>



<p>“Man has three ways of acting wisely. First, on meditation; that is the noblest. Secondly, on imitation; that is the easiest. Thirdly, on experience; that is the bitterest.&#8221;&nbsp;– (Confucius)</p>



<h3 class="wp-block-heading">– Be honest with customers, employees and yourself.</h3>



<p>Be honest with customers, especially when things go wrong.&nbsp;If the customer&#8217;s product (e.g. server) fails, then offer solutions and no excuses and solve the problem, not the question of blame.&nbsp;No one is helped by pointing the finger at colleagues or customers, not at the server, not at the customer and ultimately not at yourself.</p>



<h3 class="wp-block-heading">– Ask questions if you don&#8217;t understand something.</h3>



<p>Don&#8217;t talk to customers about something you don&#8217;t understand, not knowing something (especially in training) is fine, but then ask a colleague before you talk to a customer about it! </p>



<h3 class="wp-block-heading">– Think about what you are doing (not only at work).</h3>



<p>If you question things and think about your work and what you do, then you can develop personally.&nbsp;Question critical, for example, whether you should really order from Amazon, or should you rather order the book directly from the publisher?&nbsp;What is the advantage for the author and do I have any disadvantages?&nbsp;Should we use Nagios or rather Icinga directly?&nbsp;Question your work and critically evaluate whether this is really a good / safe / future-oriented solution.</p>



<p>If you are not sure yourself or your perspective is too limited (because you only know this one solution, for example), then you should acquire new knowledge, research other solutions or “best practices” and discuss the topic with others.</p>



<h3 class="wp-block-heading">– Use Google correctly …</h3>



<p>1. When searching an issue, look for the error message in quotes: &#8220;Lars Moelleken&#8221;</p>



<p>2. You can limit the result to special URLs: <a href="https://www.google.com/search?q=inurl%3Amoelleken.org&amp;oq=inurl%3Amoelleken.org" target="_blank" rel="noreferrer noopener nofollow">inurl:moelleken.org</a></p>



<p>3. Sometimes it&#8217;s helpful to find only specific files: <a href="https://www.google.com/search?q=filetype%3Atxt+inurl%3Asuckup.de&amp;oq=filetype%3Atxt+inurl%3Asuckup.de" target="_blank" rel="noreferrer noopener nofollow">filetype:txt inurl:suckup.de</a></p>



<p>&gt; There are even more tricks that can help you in your daily work, just Google for it:</p>



<p>Full example: <em><a href="index.of mp3 “M&auml;nner Sind Schweine” -html -htm -php" target="_blank" rel="noreferrer noopener nofollow">intitle:index</a><a href="https://www.google.com/search?q=intitle%3Aindex.of+mp3+%E2%80%9CM%C3%A4nner+Sind+Schweine%E2%80%9D+-html+-htm+-php">.of mp3 “M&auml;nner Sind Schweine” -html -htm -php</a></em></p>



<h2 class="wp-block-heading">What did I learn as IT specialist for application development?</h2>



<h3 class="wp-block-heading">– You never stop learning&#8230;</h3>



<p>When you start to deal with web programming (HTML, CSS, JS, PHP, &#8230;), you don&#8217;t even know where to start.&nbsp;There is so much to learn, and this feeling accompanies you for some time (years) until you recognize recurring concepts.&nbsp;However, the advantage in web programming is that many different things have common APIs or at least can be combined.&nbsp;I can write a class in PHP that creates data attributes for my HTML, which I can read out with JavaScript to design them accordingly using CSS classes.&nbsp;But it stays the same, you never stop learning, and that&#8217;s also what&#8217;s so exciting about this job.</p>



<h3 class="wp-block-heading">– Try to write code every day.&nbsp;(but set yourself a LIMIT)</h3>



<p>Even if the boss isn&#8217;t in the office today, and you don&#8217;t have any more tasks, then write some code, if you&#8217;re sitting on the couch at home (and no new series is running on Netflix), then write or read some code and if you&#8217;re on vacation, you&#8217;re on vacation!</p>



<p>Here is an interesting link from &#8220;John Resig&#8221; (jQuery):<br /><a href="http://ejohn.org/blog/write-code-every-day/" target="_blank" rel="noreferrer noopener nofollow">http://ejohn.org/blog/write-code-every-day/</a></p>



<h3 class="wp-block-heading">– Think in modules and packages…</h3>



<p>If you write software every day, you don&#8217;t want to code the same functionality (e.g. database connection, send e-mail or error logging &#8230;) multiple times for different projects (and remember, mostly you don&#8217;t want to code standard functions yourself).&nbsp;Therefore, every programmer should think in modules and design an application in different, preferably interchangeable parts.&nbsp;Often, the system can then also be expanded better, since there is already an interface for modules that can be used.&nbsp;The independence and decoupling of program parts also has the advantage that side effects from different places in the source code are further avoided.&nbsp;In addition, one should minimize the coupling of the corresponding modules, otherwise one gains nothing from modules.</p>



<p>There are already package managers for almost everything in web development. e.g.:<br />– Frontend (css, js): npm<br />– Backend (php): composer</p>



<h3 class="wp-block-heading">– Open-Source-Software</h3>



<p>If you are already working with modules and packages, you can publish them as an OSS project + run tests via GitHub actions + code coverage + at least a small amount of documentation. For these reasons alone, publishing as open source is worthwhile.&nbsp;The code quality also increases (in my experience), since the source code is released to the public and therefore more or less conscious attention is paid to the code quality.</p>



<p>The moment when you get your first pull request for your software or code together with someone from Israel, Turkey and the USA is priceless.</p>



<p>At some point, you would like to have the same advantages of OSS in your daily work because often, there is no package (code is directly added into the existing code), no tests (even not for bugs) and no documentation. So, possibly, you have now collected enough arguments to convince your boss to publish some package from your code at work.</p>



<h3 class="wp-block-heading">– Git &amp; Good</h3>



<p>I don&#8217;t know how people can work with the PC without version control.&nbsp;I even use “git” for smaller private projects or for configuration files.&nbsp;The following are some advantages, but the list can certainly be extended with a few more points:</p>



<p>– changes can be traced (git log, git blame)<br />– changes can be undone (git revert, git reset)<br />– changes can be reviewed by other employees<br />– employees can work on a project at the same time (git commit, git pull, git push)<br />– development branches (forks) can be developed simultaneously (git checkout -b , git branches)</p>



<h3 class="wp-block-heading">– Use GitHub and learn from the best.</h3>



<p>GitHub itself is not  open-source, but there has been an unofficial agreement to use the platform for open-source projects.&nbsp;You can therefore find many good developers and projects there, and you can learn a lot just by reading the source code / changes.&nbsp;Especially because you can understand and follow the development of the projects: How do others structure your code?&nbsp;How do others write their &#8220;commit&#8221; messages?&nbsp;How much code should a method contain?&nbsp;How much code should a class contain?&nbsp;Which variable names are better to avoid?&nbsp;How to use specific libraries / tools? How do others test their code? &#8230;</p>



<h3 class="wp-block-heading">– try { tests() }</h3>



<p>Especially when you write tests for your own code, you catch yourself testing exactly the cases that you have already considered, so you should test the corresponding functionality with different (not yet considered) input. Here are some inputs for testing: <a href="https://github.com/minimaxir/big-list-of-naughty-strings" target="_blank" rel="noreferrer noopener nofollow">https://github.com/minimaxir/big-list-of-naughty-strings</a></p>



<p>Hint: We should add another test whenever an error occurred, so that already fixed error does not come back to use.</p>



<h3 class="wp-block-heading">&#8211; Automate your tests.</h3>



<p>Unit tests, integration tests and front-end tests only help if they are also executed, so you should deal with automated tests at an early stage and also run them automatically when the source code changes.&nbsp;Where and when these tests are run also determines how effective these tests ultimately are.&nbsp;As soon as you have written a few tests, you will understand why it is better not to use additional parameters for methods and functions, since the number of tests increases exponentially.</p>



<h3 class="wp-block-heading">– Deployment is also important.</h3>



<p>As soon as you work with more than one developer on a project, or the project will become more complex, you want to use some kind of deployment. As in application development, often the simplest solution is also here a good starting point: e.g. just pull the given changes into a directory and change the symlink from the existing source directory so that you can switch or rollback all files easily. PS: And you properly never need to write database-migration rollbacks, I never used them. </p>



<h3 class="wp-block-heading">– Understanding concepts is more important than implementing them.</h3>



<p>Understanding design patterns (programming concepts) not only helps in the current programming language, but can mostly be applied to other programming languages ​​as well.</p>



<p>Basic concepts (classes, objects, OOP, functions, ORM, MVC, DDD, unit tests, data binding, router, hooks, template engine, &#8230;) can be found in many frameworks / programming languages ​​and once you have understood the terms and concepts, it is no longer that difficult to use new / different frameworks.&nbsp;And you can see different strengths and weaknesses of these frameworks and tools: &#8220;If you only have a hammer as a tool, you see a nail in every problem.&#8221;</p>



<h3 class="wp-block-heading">– Solving problems also means understanding customers.</h3>



<p>Design patterns are part of the basic equipment, but you should always ask yourself: Which problem is actually supposed to be solved with the given solution?&nbsp;If necessary, you can find an even more elegant / simpler solution.&nbsp;And sometimes the customer actually wants something thoroughly different, he just doesn&#8217;t know it yet or someone has misunderstood the customer.</p>



<h3 class="wp-block-heading">– Solving problems also means understanding processes.</h3>



<p>But it is just as important to understand why a certain feature is implemented, and otherwise you are programming something that is either not needed or used at all.&nbsp;One should therefore understand the corresponding task before implementation and even before planning in the overall context.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="936" height="698" data-attachment-id="6331" data-permalink="http://suckup.de/?attachment_id=6331" data-orig-file="http://suckup.de/wp-content/uploads//2016/01/projekt-schaukel-baum.png" data-orig-size="936,698" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="projekt-schaukel-baum" data-image-description="" data-image-caption="" data-medium-file="http://suckup.de/wp-content/uploads//2016/01/projekt-schaukel-baum-300x224.png" data-large-file="http://suckup.de/wp-content/uploads//2016/01/projekt-schaukel-baum.png" src="https://suckup.de/wp-content/uploads//2016/01/projekt-schaukel-baum.png" alt="project-swing-tree" class="wp-image-6331" srcset="http://suckup.de/wp-content/uploads/2016/01/projekt-schaukel-baum.png 936w, http://suckup.de/wp-content/uploads/2016/01/projekt-schaukel-baum-300x224.png 300w, http://suckup.de/wp-content/uploads/2016/01/projekt-schaukel-baum-768x573.png 768w" sizes="auto, (max-width: 936px) 100vw, 936px" /></figure>
</div>


<h3 class="wp-block-heading">&#8211; Spread code across multiple files.</h3>



<p>Use one file for a class, use one file for CSS properties of a module or a specific page, use a new file for each new view.&nbsp;Dividing the source code into different files / directories offers many advantages, so the next developer knows where new source code should be stored and you can find your way around the source code faster.&nbsp;Many frameworks already provide a predefined directory structure. </p>



<h3 class="wp-block-heading">– Readability comes first!</h3>



<p>The readability of source code should always come first, since you or your work colleagues will have to maintain or expand this code in the future.</p>



<p>YouTube&#8217;s videos about “Clean Code”:&nbsp;<a href="https://www.youtube.com/results?search_query=%22Clean+Code%22&amp;search_sort=video_view_count" target="_blank" rel="noreferrer noopener nofollow">https://www.youtube.com/results?search_query=%22Clean+Code%22&amp;search_sort=video_view_count</a></p>



<p>Best Practices:&nbsp;<a href="http://code.tutsplus.com/tutorials/top-15-best-practices-for-writing-super-readable-code-net-8118" target="_blank" rel="noreferrer noopener nofollow">http://code.tutsplus.com/tutorials/top-15-best-practices-for-writing-super-readable-code-net-8118</a></p>



<h3 class="wp-block-heading">– Good naming is one of the most difficult tasks in programming.</h3>



<p>It starts with the domain name / project name, goes through file names, to directory names, class names, method names, variable names, CSS class names.&nbsp;Always realize that others will read this and need to understand it.&nbsp;Therefore, you should also avoid unnecessary abbreviations and write what you want to describe.</p>



<p>We want to describe what the function does and not how it is implemented.</p>



<p>⇾ Incorrect: sendMailViaSwiftmailer(), sendHttpcallViaCurl(), &#8230;<br />⇾ Correct: mail-&gt;send(), http-&gt;send(), &#8230;</p>



<p>Variables should describe what they contain and not how they are stored.</p>



<p>⇾ Incorrect: $array2use, $personsArray, …<br />⇾ Correct: $pages, $persons, …</p>



<p>Summary: Describe what the variable/method/function/class is, not how it is implemented: <a href="https://github.com/kettanaito/naming-cheatsheet" target="_blank" rel="noreferrer noopener nofollow">https://github.com/kettanaito/naming-cheatsheet</a></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><a href="https://suckup-de.translate.goog/2014/05/weniger-schlecht-php-programmieren/?_x_tr_sl=de&amp;_x_tr_tl=en&amp;_x_tr_hl=de&amp;_x_tr_pto=wapp">Programming less bad PHP</a></p>
</blockquote>



<figure class="wp-block-embed is-type-wp-embed is-provider-suckup-de wp-block-embed-suckup-de"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="O4wRWmU7Rr"><a href="http://suckup.de/2014/05/weniger-schlecht-php-programmieren/">Weniger schlecht PHP programmieren</a></blockquote><iframe loading="lazy" class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8220;Weniger schlecht PHP programmieren&#8221; &#8212; SUCKUP.de" src="http://suckup.de/2014/05/weniger-schlecht-php-programmieren/embed/#?secret=UI9fm7j9TA#?secret=O4wRWmU7Rr" data-secret="O4wRWmU7Rr" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>



<h3 class="wp-block-heading">– Save on comments (at least inline)…</h3>



<p>Good comments explain &#8220;why&#8221; and not &#8220;what&#8221; the code is doing, and should offer the reader added value that is not already described in the source code.</p>



<p>Sometimes it makes sense to add some &#8220;what&#8221; comments anyway, e.g. for complicated regex or some other not optimal code that needs some hints.</p>



<p>Examples of inline comments:</p>



<p>bad code:</p>



<pre class="wp-block-preformatted">// Check if the user is already logged in if ( isset ( $_SESSION['user_loggedin']) &amp;&amp; $_SESSION['user_loggedin'] &gt; 1 ) { ... }
       </pre>



<p>slightly better code:</p>



<pre class="wp-block-preformatted">// check if the user is already logged-in 
if ( session ( 'user_loggedin' ) &gt; 1 ) { ... }
      </pre>



<p>better code:</p>



<pre class="wp-block-preformatted">if ( $user-&gt;isLoggedin === true ) { ... }     </pre>



<p>&#8230; and another example &#8230;</p>



<p>bad code:</p>



<pre class="wp-block-preformatted">// regex: email 
if (! preg_match ( '/^(.*&lt;?)(.*)@(.*)(&gt;?)$/' , $email ) { ... }
    </pre>



<p>better code:</p>



<pre class="wp-block-preformatted">define ( 'EMAIL_REGEX_SIMPLE' , '/^(.*&lt;?)(.*)@(.*)(&gt;?)$/' ); 

if (! preg_match ( EMAIL_REGEX_SIMPLE , $email ) { ... }    </pre>



<h3 class="wp-block-heading">– Consistency in a project is more important than personal preferences!</h3>



<p>Use the existing code and use given functions.&nbsp;If it brings benefits, then change / refactor the corresponding code, but then refactor all places in the project which are implemented in this way.</p>



<p>Example: If you have formerly worked without a template system and would like to use one for &#8220;reasons&#8221;, then use this for all templates in the project and not just for your current use case; otherwise, inconsistencies will arise in the project.&nbsp;For example, if you create a new &#8220;Email→isValid()&#8221; method, then you should also replace all previous RegEx attempts in the current project with the &#8220;Email&#8221; class; otherwise inconsistencies will arise again.</p>



<p>Read more about the topic: </p>



<p>&#8211; &#8220;Be consistent [and try to automate this process, please]!&#8221; <a href="http://suckup.de/2020/01/do-not-fear-the-white-space-in-your-code/">http://suckup.de/2020/01/do-not-fear-the-white-space-in-your-code/</a></p>



<p>&#8211; &#8220;Why do we write unreadable code?&#8221;<br /><a href="http://suckup.de/2020/07/how-to-write-readable-code/">http://suckup.de/2020/01/do-not-fear-the-white-space-in-your-code/</a></p>



<h3 class="wp-block-heading">– A uniform code style has a positive effect on quality!</h3>



<p>As in real life, if there is already rubbish somewhere, the inhibition threshold to dump rubbish there drops extremely.&nbsp;But if everything looks nice and tidy, then nobody just throws a “randumInt() { return 4;&nbsp;}” function on the floor.</p>



<p>It also helps to automate some refactoring because the code looks everywhere the same, you can also apply the same e.g. PHP-CS-Fixer and you do not need to think about every different coding style. </p>



<h3 class="wp-block-heading">– Use functional principles &amp; object-oriented concepts.</h3>



<p>A pure function (“Pure Functions”) only depends on its parameters and with the same parameters it always returns the same result.&nbsp;These principles can also be considered in OOP and create so-called immutable classes (immutable class).</p>



<p><a href="https://en.wikipedia.org/wiki/Pure_function">https://en.wikipedia.org/wiki/Pure_function</a><br /><a href="https://de.wikipedia.org/wiki/Object-oriented_programming">https://de.wikipedia.org/wiki/Object-oriented_programming</a><br /><a href="https://en.wikipedia.org/wiki/Immutable_object">https://en.wikipedia.org/wiki/Immutable_object</a></p>



<h3 class="wp-block-heading">– Please do not use global variables!</h3>



<p>Global variables make testing difficult because they can cause side effects.&nbsp;Also, it&#8217;s difficult to refactor code with global variables because you don&#8217;t know what effects these changes will have on other parts of the system.</p>



<p>In some programming languages ​​(e.g. JavaScript, Shell) all variables are global and only become local with a certain keyword (e.g. in the scope of a function or a class).</p>



<h3 class="wp-block-heading">&#8211; Learn to use your tools properly!</h3>



<p>For example, if you&#8217;re writing code with Notepad, you can dig a hole with a spoon, which is just as efficient.&nbsp;Learn keyboard shortcuts for your programs and operating system!&nbsp;Use an IDE, e.g. from JetBrains (<a href="https://www.jetbrains.com/products.html" target="_blank" rel="noreferrer noopener nofollow">https://www.jetbrains.com/products.html</a>) and use additional plugins and settings.</p>



<p>Modern IDEs also give hints/suggestions on how to improve your code.&nbsp;For example, for PHP, you can use PhpStorm + PHPStan and share the global IDE Inspections settings in the team.</p>



<h3 class="wp-block-heading">– Performance?</h3>



<p>In nearly every situation you don&#8217;t have to worry too much about performance, as modern programming languages ​​/ frameworks support us and with common solutions; otherwise the motto is &#8220;profiling, profiling&#8230; profiling&#8221;!</p>



<h3 class="wp-block-heading">– Exceptions === Exceptions</h3>



<p>You should not use exceptions to handle normal errors.&nbsp;Exceptions are exceptions, and regular code handles the regular cases!&nbsp;&#8220;Use exceptions only in exceptional circumstances&#8221; (Pragmatic Programmers).&nbsp;And nearly under no circumstances you should “choke off” exceptions, e.g. by trivially catching several exceptions.</p>



<h3 class="wp-block-heading">– Finish your work</h3>



<p>You should finish what you started.&nbsp;For example, if you need to use &#8220;fopen()&#8221; you should also use &#8220;fclose()&#8221; in the same code block. So, nobody in the team needs to clean up your stuff after he / she uses your function. </p>



<h3 class="wp-block-heading">– Source code should be searchable [Ctrl + F] …</h3>



<p>The source code should be easy to search through, so you should avoid using string nesting + &#8220;&amp;&#8221; with Sass, for example, and also avoid using PHP functions such as &#8220;extract()&#8221;.&nbsp;Whenever variables are not declared, but created as if by magic (e.g. using magic methods in PHP), it is no longer so easy to change the source text afterward.</p>



<p>Example in PHP: (bad)</p>



<pre class="wp-block-preformatted">extract ( array ( 'bar' =&gt; 'bar' , 'lall' =&gt; 1 )); 
var_dump ( $bar ); // string 'bar' (length=3)      </pre>



<p>Example in Sass: (bad)</p>



<pre class="wp-block-preformatted">. teaser { 
  font - size : 12px ; 

  &amp; __link { 
    color : rgb ( 210 , 210 , 22 ); } }
  
</pre>



<p>Sass Nesting (code style):&nbsp;<a href="https://github.com/grvcoelho/css#nesting" target="_blank" rel="noreferrer noopener nofollow">https://github.com/grvcoelho/css#nesting</a></p>



<h3 class="wp-block-heading">– Program for your use case!</h3>



<p>A big problem in programming is that you have to try to think and program in a generalized way so that you can (easily) expand the source code if new requirements are added or you can (easily) change it.</p>



<p>What does project sometimes look like?&nbsp;→ A customer orders 10,000 green apples from a farm, changes his order to 10,000 red apples the morning before delivery and when these are delivered, the customer would prefer 10,000 pears and would like to pay for them in 6 months.</p>



<p>And precisely for this reason you should only write the source code that is really required for the current use case because you can&#8217;t map all eventualities anyway and the source code is unnecessarily complicated.</p>



<h3 class="wp-block-heading">– KISS – Keep it simple, stupid.</h3>



<p>One should always keep in mind that the source code itself is not that valuable.&nbsp;The value only arises when other developers understand it and can adapt / configure / use it for the customer or themselves.&nbsp;This should be kept in mind during programming so that a solution can be implemented as comprehensibly and &#8220;simply&#8221; as possible.&nbsp;And if I don&#8217;t need to use a new class or nice design pattern for the current problem, I probably shouldn&#8217;t.&nbsp;However, this does not mean that you should throw all good intentions overboard and use global variables / singletons everywhere.&nbsp;However, if a simple solution already does the job, go for that one.</p>



<p>A good example of what not to do is the JavaScript DOM Selector API.&nbsp;Not exactly nice to read or write&#8230;</p>



<p>Bad: (DOM Selector via JS)</p>



<pre class="wp-block-preformatted">document.getElementsByTagName ( "div" ) 
document.getElementById ( "foo" ) 
document.getElementsByClassName ( "bar" ) 
document.querySelector ( ".foo" ) 
document.querySelectorAll ( "div.bar" )</pre>



<p>Better: (DOM Selector via jQuery)</p>



<pre class="wp-block-preformatted">$( "div" ) 
$( "#foo" ) 
$( ".bar" ) 
$( ".foo" ) 
$( "div.bar" )</pre>



<h3 class="wp-block-heading">– DRY – Don&#8217;t Reap Yourself.</h3>



<p>Repetitions / redundancies in the source text or in recurring work arise relatively quickly if people do not communicate with each other.&nbsp;But also unintentionally due to errors in the software design because you don&#8217;t have a better idea or don&#8217;t think you have time for it.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="543" height="407" data-attachment-id="6330" data-permalink="http://suckup.de/?attachment_id=6330" data-orig-file="http://suckup.de/wp-content/uploads//2016/01/improve.png" data-orig-size="543,407" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="improve" data-image-description="" data-image-caption="" data-medium-file="http://suckup.de/wp-content/uploads//2016/01/improve-300x225.png" data-large-file="http://suckup.de/wp-content/uploads//2016/01/improve.png" src="https://suckup.de/wp-content/uploads//2016/01/improve.png" alt="improve" class="wp-image-6330" srcset="http://suckup.de/wp-content/uploads/2016/01/improve.png 543w, http://suckup.de/wp-content/uploads/2016/01/improve-300x225.png 300w" sizes="auto, (max-width: 543px) 100vw, 543px" /></figure>
</div>


<p>To avoid repetition, make your solution easy to find and easy to use. So that other devs will use it instead of re-creating a solution.</p>



<h3 class="wp-block-heading">– The will to learn and understand something new is more important than previous knowledge.</h3>



<p>If you can already program ActionScript (Flash), for example, but are not willing to learn something new, then previous knowledge is of no use because &#8220;The only constant in the universe is change.&#8221; &#8211; Heraclitus of Ephesus (about 540 &#8211; 480 BC).</p>



<h3 class="wp-block-heading">– Read good books and magazines.</h3>



<p>Books I have read:&nbsp;<a href="https://www.goodreads.com/user/show/3949219-lars-moelleken" target="_blank" rel="noreferrer noopener nofollow">https://www.goodreads.com/user/show/3949219-lars-moelleken</a><br />Free Books:&nbsp;<a href="https://github.com/vhf/free-programming-books/blob/master/free- programming-books.md" target="_blank" rel="noreferrer noopener nofollow">https://github.com/vhf/free-programming-books/blob/master/free- programming-books.md</a><br />books for programmers:&nbsp;<a href="http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read" target="_blank" rel="noreferrer noopener nofollow">http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read</a></p>



<h3 class="wp-block-heading">– Follow other programmers on Twitter / GitHub / dev.to / YouTube / Medium / …</h3>



<p>It sometimes helps to motivate yourself, to write e.g. a blog post or testing some new stuff, if you know some people how has the same interest, so just follow some of them online, there are many excellent developers out there, and they share their knowledge and tricks mostly for free. :)</p>



<h3 class="wp-block-heading">– Listen to podcasts &amp; subscribe to RSS feeds / newsletters &amp; watch videos, for example from web conferences</h3>



<p>To find out about new technologies, techniques, standards, patterns, etc., it is best to use different media, which can be consumed in different situations.&nbsp;An interesting podcast on “Frontend Architecture” before falling asleep or a video on “DevOps” while preparing lunch, reading a book on the tram in the morning entitled “Programming less badly” … to name just a few examples.</p>



<p>Podcasts:&nbsp;<a href="https://github.com/voku/awesome-web/blob/master/README.md#-audio-podcast" target="_blank" rel="noreferrer noopener">https://github.com/voku/awesome-web/blob/master/README.md#-audio-podcast</a><br />github is awesome: <a href="https://github.com/sindresorhus/awesome" target="_blank" rel="noreferrer noopener">https://github.com/sindresorhus/awesome</a><br />and there is more:&nbsp;<a href="https://github.com/jnv/lists" target="_blank" rel="noreferrer noopener">https://github.com/jnv/lists</a></p>



<h3 class="wp-block-heading">– Attend Meetup&#8217;s &amp; web conferences and talk to other developers.</h3>



<p>Meetups are groups of people who meet regularly and talk about things like Python, Scala, PHP, etc.&nbsp;Usually, someone gives a lecture on a previously agreed topic.</p>



<p>⇉&nbsp;<a href="http://www.meetup.com/de-DE/members/136733532/" target="_blank" rel="noreferrer noopener">http://www.meetup.com/de-DE/members/136733532/</a></p>



<p>Web conferencing is fun.&nbsp;Point.&nbsp;And every developer / admin should visit them because you get new impressions and meet wonderful people.&nbsp;Some conferences are expensive, but here you should contact your employer, if necessary, the company will take care of it.&nbsp;And there are also really cheap conferences.</p>



<h3 class="wp-block-heading">– Post answers at quora.com ||&nbsp;stackoverflow.com ||&nbsp;in forums ||&nbsp;your blog&#8230;</h3>



<p>To deal with a certain topic yourself and to really understand it, it is worth doing research and writing a text (possibly even a lecture) that others can read and criticize and thus improve.</p>



<h3 class="wp-block-heading">– Don&#8217;t stay at work for so long every day; otherwise nobody will be waiting for you at home!</h3>



<p>With all the enthusiasm for the &#8220;job&#8221; (even if it&#8217;s fun), you shouldn&#8217;t lose sight of the essential things.&nbsp;Again, something I had to learn the hard way.&nbsp;:-/</p>



<p></p>


<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2023%2F01%2Fwhat-have-i-learned-so-far-in-my-job%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dwhat-have-i-learned-so-far-in-my-job&amp;action_name=What+have+I+learned+so+far+in+my+job%3F&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2023/01/what-have-i-learned-so-far-in-my-job/?pk_campaign=feed&amp;pk_kwd=what-have-i-learned-so-far-in-my-job/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6888</post-id>	</item>
		<item>
		<title>PHP: Code Quality with Custom Tooling Extensions</title>
		<link>http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/?pk_campaign=feed&amp;pk_kwd=php-code-quality-with-custom-tooling-extensions&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=php-code-quality-with-custom-tooling-extensions</link>
					<comments>http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/?pk_campaign=feed&amp;pk_kwd=php-code-quality-with-custom-tooling-extensions#comments</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Wed, 20 Jul 2022 00:05:53 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6867</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/?pk_campaign=feed&#038;pk_kwd=php-code-quality-with-custom-tooling-extensions">PHP: Code Quality with Custom Tooling Extensions</a></p>
<p>After many years of using PHPStan, PHP-CS-Fixer, PHP_CodeSniffer, &#8230; I will give you one advice: add your own custom code to extend your Code-Quality-Tooling. Nearly every project has custom code that procures the real value for the product / project, but this custom code itself is often not really improved by PHP-CS-Fixer, PHPStan, Psalm, and &#8230; <a href="http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/?pk_campaign=feed&#038;pk_kwd=php-code-quality-with-custom-tooling-extensions" class="more-link">Continue reading <span class="screen-reader-text">PHP: Code Quality with Custom Tooling Extensions</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2022%2F07%2Fphp-code-quality-with-custom-tooling-extensions%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dphp-code-quality-with-custom-tooling-extensions&amp;action_name=PHP%3A+Code+Quality+with+Custom+Tooling+Extensions&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/?pk_campaign=feed&#038;pk_kwd=php-code-quality-with-custom-tooling-extensions">PHP: Code Quality with Custom Tooling Extensions</a></p>

<p>After many years of using PHPStan, PHP-CS-Fixer, PHP_CodeSniffer, &#8230; I will give you one advice: add your own custom code to extend your Code-Quality-Tooling.</p>
<p>Nearly every project has custom code that procures the real value for the product / project, but this custom code itself is often not really improved by PHP-CS-Fixer, PHPStan, Psalm, and other tools. The tools do not know how this custom code is working so that we need to write some extensions for ourselves.</p>
<p>Example: At work, we have some Html-Form-Element (HFE) classes that used some properties from our Active Record classes, and back in the time we used strings to connect both classes. :-/</p>
<p><em>Hint: Strings are very flexible, but also awful to use programmatically in the future. I would recommend avoiding plain strings as much as possible.</em></p>
<h3>1. Custom PHP-CS-Fixer</h3>
<p>So, I wrote a quick script that will replace the strings with some metadata. The big advantage is that this custom PHP-CS-Fixer will also automatically fix code that will be created in the future, and you can apply / check this in the CI-pipline or e.g. in a pre-commit hook or directly in PhpStorm.</p>
<pre>&lt;?php<br /><br />declare(strict_types=1);<br /><br />use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer;<br />use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer;<br />use PhpCsFixer\Tokenizer\Token;<br />use PhpCsFixer\Tokenizer\Tokens;<br /><br />final class MeerxUseMetaFromActiveRowForHFECallsFixer extends AbstractMeerxFixerHelper <br />{<br /><br />    /**<br />     * {@inheritdoc}<br />     */<br />    public function getDocumentation(): string <br />    {<br />        return 'Use ActiveRow-&gt;m() for "HFE_"-calls, if it is possible.';<br />    }<br /><br />    /**<br />     * {@inheritdoc}<br />     */<br />    public function getSampleCode(): string <br />    {<br />        return &lt;&lt;&lt;'PHP'<br />            &lt;?php<br /><br />            $element = UserFactory::singleton()-&gt;fetchEmpty();<br /><br />            $foo = HFE_Date::Gen($element, 'created_date');<br />            PHP;<br />    }<br /><br />    public function isRisky(): bool <br />    {<br />        return true;<br />    }<br /><br />    /**<br />     * {@inheritdoc}<br />     */<br />    public function isCandidate(Tokens $tokens): bool <br />    {<br />        return $tokens-&gt;isTokenKindFound(\T_STRING);<br />    }<br /><br />    public function getPriority(): int {<br />        // must be run after NoAliasFunctionsFixer<br />        // must be run before MethodArgumentSpaceFixer<br />        return -1;<br />    }<br /><br />    protected function applyFix(SplFileInfo $file, Tokens $tokens): void <br />    {<br />        if (v_str_contains($file-&gt;getFilename(), 'HFE_')) {<br />            return;<br />        }<br /><br />        $functionsAnalyzer = new FunctionsAnalyzer();<br /><br />        // fix for "HFE_*::Gen()"<br />        foreach ($tokens as $index =&gt; $token) {<br />            $index = (int)$index;<br /><br />            // only for "Gen()"-calls<br />            if (!$token-&gt;equals([\T_STRING, 'Gen'], false)) {<br />                continue;<br />            }<br /><br />            // only for "HFE_*"-classes<br />            $object = (string)$tokens[$index - 2]-&gt;getContent();<br />            if (!v_str_starts_with($object, 'HFE_')) {<br />                continue;<br />            }<br /><br />            if ($functionsAnalyzer-&gt;isGlobalFunctionCall($tokens, $index)) {<br />                continue;<br />            }<br /><br />            $argumentsIndices = $this-&gt;getArgumentIndices($tokens, $index);<br /><br />            if (\count($argumentsIndices) &gt;= 2) {<br />                [<br />                    $firstArgumentIndex,<br />                    $secondArgumentIndex<br />                ] = array_keys($argumentsIndices);<br /><br />                // If the second argument is not a string, we cannot make a swap.<br />                if (!$tokens[$secondArgumentIndex]-&gt;isGivenKind(\T_CONSTANT_ENCAPSED_STRING)) {<br />                    continue;<br />                }<br /><br />                $content = trim($tokens[$secondArgumentIndex]-&gt;getContent(), '\'"');<br />                if (!$content) {<br />                    continue;<br />                }<br /><br />                $newContent = $tokens[$firstArgumentIndex]-&gt;getContent() . '-&gt;m()-&gt;' . $content;<br /><br />                $tokens[$secondArgumentIndex] = new Token([\T_CONSTANT_ENCAPSED_STRING, $newContent]);<br />            }<br />        }<br />    }<br /><br />    /**<br />     * @param Token[]|Tokens $tokens            &lt;phpdoctor-ignore-this-line/&gt;<br />     * @param int            $functionNameIndex<br />     *<br />     * @return array&lt;int, int&gt; In the format: startIndex =&gt; endIndex<br />     */<br />    private function getArgumentIndices(Tokens $tokens, $functionNameIndex): array <br />    {<br />        $argumentsAnalyzer = new ArgumentsAnalyzer();<br /><br />        $openParenthesis = $tokens-&gt;getNextTokenOfKind($functionNameIndex, ['(']);<br />        $closeParenthesis = $tokens-&gt;findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis);<br /><br />        // init<br />        $indices = [];<br /><br />        foreach ($argumentsAnalyzer-&gt;getArguments($tokens, $openParenthesis, $closeParenthesis) as $startIndexCandidate =&gt; $endIndex) {<br />            $indices[$tokens-&gt;getNextMeaningfulToken($startIndexCandidate - 1)] = $tokens-&gt;getPrevMeaningfulToken($endIndex + 1);<br />        }<br /><br />        return $indices;<br />    }<br />}</pre>
<p>To use your custom fixes, you can register and enable them: <a href="https://cs.symfony.com/doc/custom_rules.html" target="_blank" rel="noopener">https://cs.symfony.com/doc/custom_rules.html</a>  </p>
<p><strong>Example-Result:</strong></p>



<pre class="wp-block-code"><code>
$fieldGroup->addElement(HFE_Customer::Gen($element, 'customer_id'));

// &lt;- will be replaced with ->

$fieldGroup->addElement(HFE_Customer::Gen($element, $element->m()->customer_id));</code></pre>



<p><em>Hint: There are many examples for PHP_CodeSniffer and Fixer Rules on GitHub, you can often pick something that fits 50-70% for your use-case and then modify it for your needs.</em></p>
<p>The &#8220;m()&#8221; method looks like this and will call the simple &#8220;ActiveRowMeta&#8221;-class. This class will return the property name itself instead of the real value.</p>
<pre>/**<br /> * (M)ETA<br /> *<br /> * @return ActiveRowMeta|mixed|static<br /> *                                    &lt;p&gt;<br /> *                                    We fake the return "static" here because we want auto-completion for the current properties in the IDE.<br /> *                                    &lt;br&gt;&lt;br&gt;<br /> *                                    But here the properties contains only the name from the property itself.<br /> *                                    &lt;/p&gt;<br /> *<br /> * @psalm-return object{string,string}<br /> */<br />final public function m() <br />{<br />    return (new ActiveRowMeta())-&gt;create($this);<br />}</pre>
<pre>&lt;?php<br /><br />final class ActiveRowMeta <br />{<br />    /**<br />     * @return static<br />     */<br />    public function create(ActiveRow $obj): self <br />    {<br />        /** @var static[] $STATIC_CACHE */<br />        static $STATIC_CACHE = [];<br /><br />        // DEBUG<br />        // var_dump($STATIC_CACHE);<br /><br />        $cacheKey = \get_class($obj);<br />        if (!empty($STATIC_CACHE[$cacheKey])) {<br />            return $STATIC_CACHE[$cacheKey];<br />        }<br /><br />        foreach ($obj-&gt;getObjectVars() as $propertyName =&gt; $propertyValue) {<br />            $this-&gt;{$propertyName} = $propertyName;<br />        }<br /><br />        $STATIC_CACHE[$cacheKey] = $this;<br /><br />        return $this;<br />    }<br /><br />}</pre>
<h3>2. Custom PHPStan Extension</h3>
<p>In the next step, I added a <a href="https://phpstan.org/developing-extensions/dynamic-return-type-extensions" target="_blank" rel="noopener">DynamicMethodReturnTypeExtension</a> for PHPStan, so that the static code analyze knows the type of the metadata + I still have auto-completion in the IDE via phpdocs.</p>
<p><em>Note: Here I&#8217;ve also made the metadata read-only, so we can&#8217;t misuse the metadata.</em></p>
<pre>&lt;?php<br /><br />declare(strict_types=1);<br /><br />namespace meerx\App\scripts\githooks\StandardMeerx\PHPStanHelper;<br /><br />use PhpParser\Node\Expr\MethodCall;<br />use PHPStan\Analyser\Scope;<br />use PHPStan\Reflection\MethodReflection;<br />use PHPStan\Type\Type;<br /><br />final class MeerxMetaDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension <br />{<br /><br />    public function getClass(): string <br />    {<br />        return \ActiveRow::class;<br />    }<br /><br />    public function isMethodSupported(MethodReflection $methodReflection): bool <br />    {<br />        return $methodReflection-&gt;getName() === 'm';<br />    }<br /><br />    /**<br />     * @var \PHPStan\Reflection\ReflectionProvider<br />     */<br />    private $reflectionProvider;<br /><br />    public function __construct(\PHPStan\Reflection\ReflectionProvider $reflectionProvider) <br />    {<br />        $this-&gt;reflectionProvider = $reflectionProvider;<br />    }<br /><br />    public function getTypeFromMethodCall(<br />        MethodReflection $methodReflection,<br />        MethodCall $methodCall,<br />        Scope $scope<br />    ): Type <br />    {<br />        $exprType = $scope-&gt;getType($methodCall-&gt;var);<br /><br />        $staticClassName = $exprType-&gt;getReferencedClasses()[0];<br />        $classReflection = $this-&gt;reflectionProvider-&gt;getClass($staticClassName);<br /><br />        return new MeerxMetaType($staticClassName, null, $classReflection);<br />    }<br />}</pre>



<pre>&lt;?php<br /><br />declare(strict_types=1);<br /><br />namespace meerx\App\scripts\githooks\StandardMeerx\PHPStanHelper;<br /><br />use PHPStan\Reflection\ClassMemberAccessAnswerer;<br />use PHPStan\Type\ObjectType;<br /><br />final class MeerxMetaType extends ObjectType <br />{<br /><br />    public function getProperty(string $propertyName, ClassMemberAccessAnswerer $scope): \PHPStan\Reflection\PropertyReflection <br />    {<br />        return new MeerxMetaProperty($this-&gt;getClassReflection());<br />    }<br /><br />}</pre>



<pre>&lt;?php<br /><br />declare(strict_types=1);<br /><br />namespace meerx\App\scripts\githooks\StandardMeerx\PHPStanHelper;<br /><br />use PHPStan\Reflection\ClassReflection;<br />use PHPStan\TrinaryLogic;<br />use PHPStan\Type\NeverType;<br />use PHPStan\Type\StringType;<br /><br />final class MeerxMetaProperty implements \PHPStan\Reflection\PropertyReflection <br />{<br /><br />    private ClassReflection $classReflection;<br /><br />    public function __construct(ClassReflection $classReflection) <br />    {<br />        $this-&gt;classReflection = $classReflection;<br />    }<br /><br />    public function getReadableType(): \PHPStan\Type\Type <br />    {<br />        return new StringType();<br />    }<br /><br />    public function getWritableType(): \PHPStan\Type\Type <br />    {<br />        return new NeverType();<br />    }<br /><br />    public function isWritable(): bool <br />    {<br />        return false;<br />    }<br /><br />    public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection <br />    {<br />        return $this-&gt;classReflection;<br />    }<br /><br />    public function isStatic(): bool <br />    {<br />        return false;<br />    }<br /><br />    public function isPrivate(): bool <br />    {<br />        return false;<br />    }<br /><br />    public function isPublic(): bool <br />    {<br />        return true;<br />    }<br /><br />    public function getDocComment(): ?string <br />    {<br />        return null;<br />    }<br /><br />    public function canChangeTypeAfterAssignment(): bool <br />    {<br />        return false;<br />    }<br /><br />    public function isReadable(): bool <br />    {<br />        return true;<br />    }<br /><br />    public function isDeprecated(): \PHPStan\TrinaryLogic <br />    {<br />        return TrinaryLogic::createFromBoolean(false);<br />    }<br /><br />    public function getDeprecatedDescription(): ?string <br />    {<br />        return null;<br />    }<br /><br />    public function isInternal(): \PHPStan\TrinaryLogic <br />    {<br />        return TrinaryLogic::createFromBoolean(false);<br />    }<br />}</pre>



<h2 class="wp-block-heading">Summary</h2>



<p>Think about your custom code and how you can improve it, use your already used tools and extend it to understand your code. Sometimes it&#8217;s easy, and you can add some <a href="https://suckup.de/2020/02/modern-phpdoc-annotations/">modern PHPDocs</a> or you need to go down the rabbit hole and implement some custom stuff, but at last it will help your software, your team and your customers.</p>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2022%2F07%2Fphp-code-quality-with-custom-tooling-extensions%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dphp-code-quality-with-custom-tooling-extensions&amp;action_name=PHP%3A+Code+Quality+with+Custom+Tooling+Extensions&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2022/07/php-code-quality-with-custom-tooling-extensions/?pk_campaign=feed&amp;pk_kwd=php-code-quality-with-custom-tooling-extensions/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6867</post-id>	</item>
		<item>
		<title>Timeout Problems: Web Server + PHP</title>
		<link>http://suckup.de/2022/04/timeout-problems-web-server-php/?pk_campaign=feed&amp;pk_kwd=timeout-problems-web-server-php&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=timeout-problems-web-server-php</link>
					<comments>http://suckup.de/2022/04/timeout-problems-web-server-php/?pk_campaign=feed&amp;pk_kwd=timeout-problems-web-server-php#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Tue, 12 Apr 2022 12:39:18 +0000</pubDate>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[mysql servers]]></category>
		<guid isPermaLink="false">https://suckup.de/?p=6852</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2022/04/timeout-problems-web-server-php/?pk_campaign=feed&#038;pk_kwd=timeout-problems-web-server-php">Timeout Problems: Web Server + PHP</a></p>
<p>What? First there is an HTTP request and that will hit your Web server, then it will pass the request via TCP- or UNIT-Socket via FastCGI to your PHP-FPM Daemon, here we will start a new PHP process and in this process we will connect e.g. to the database and run some queries. The Problem! &#8230; <a href="http://suckup.de/2022/04/timeout-problems-web-server-php/?pk_campaign=feed&#038;pk_kwd=timeout-problems-web-server-php" class="more-link">Continue reading <span class="screen-reader-text">Timeout Problems: Web Server + PHP</span></a></p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2022%2F04%2Ftimeout-problems-web-server-php%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dtimeout-problems-web-server-php&amp;action_name=Timeout+Problems%3A+Web+Server+%2B+PHP&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2022/04/timeout-problems-web-server-php/?pk_campaign=feed&#038;pk_kwd=timeout-problems-web-server-php">Timeout Problems: Web Server + PHP</a></p>

<h2 class="western"><strong>What?</strong></h2>
<div id="article-body" dir="ltr">
<p>First there is an HTTP request and that will hit your Web server, then it will pass the request via TCP- or UNIT-Socket via FastCGI to your PHP-FPM Daemon, here we will start a new PHP process and in this process we will connect e.g. to the database and run some queries.</p>
</div>
<p><img loading="lazy" decoding="async" data-attachment-id="6857" data-permalink="http://suckup.de/?attachment_id=6857" data-orig-file="http://suckup.de/wp-content/uploads//2022/04/7HHxk.jpg" data-orig-size="638,359" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="PHP-Request" data-image-description="" data-image-caption="" data-medium-file="http://suckup.de/wp-content/uploads//2022/04/7HHxk-300x169.jpg" data-large-file="http://suckup.de/wp-content/uploads//2022/04/7HHxk.jpg" class="aligncenter wp-image-6857 size-full" src="http://suckup.de/wp-content/uploads//2022/04/7HHxk.jpg" alt="PHP-Request" width="638" height="359" srcset="http://suckup.de/wp-content/uploads/2022/04/7HHxk.jpg 638w, http://suckup.de/wp-content/uploads/2022/04/7HHxk-300x169.jpg 300w" sizes="auto, (max-width: 638px) 100vw, 638px" /></p>
<div id="article-body" dir="ltr">
<h2><strong>The Problem!</strong></h2>
<p>There are different timeout problems here because we connect different pieces together and this parts need to communicate. But what if one of the pieces does not respond in a given time or, even more bad, if one process is running forever like a bad SQL-query.</p>
<h2><strong>Understand your Timeouts.</strong></h2>
<p>Timeouts are a way to limit the time that a request can run, and otherwise an attacker could simply run a denial-of-service with a simple request. But there are many configurations in several layers: Web server, PHP, application, database, curl, &#8230;</p>
<h3 class="western"><strong>&#8211; Web server</strong></h3>
<p>Mostly you will use Apache or Nginx as Web server and in the end it makes not really a difference, there are different timeout settings, but the idea is almost the same: The Web server will stop the execution and kills the PHP process, now you got a 504 HTTP error (Gateway Timeout) and you will lose your stack trace and error-tracking because we killed our application in the middle of nothing. So, we should keep the Web server running as long as needed.</p>
<p>&#8220;`grep -Ri timeout /etc/apache2/&#8220;`</p>
<blockquote>
<pre style="text-align: left;">/etc/apache2/conf-enabled/timeout.conf:Timeout 60<br /><br />/etc/apache2/mods-available/reqtimeout.conf:&lt;IfModule reqtimeout_module&gt;<br /><br />/etc/apache2/mods-available/reqtimeout.conf: # mod_reqtimeout limits the time waiting on the client to prevent an<br /><br />/etc/apache2/mods-available/reqtimeout.conf: # configuration, but it may be necessary to tune the timeout values to<br /><br />/etc/apache2/mods-available/reqtimeout.conf: # mod_reqtimeout per virtual host.<br /><br />/etc/apache2/mods-available/reqtimeout.conf: # Note: Lower timeouts may make sense on non-ssl virtual hosts but can<br /><br />/etc/apache2/mods-available/reqtimeout.conf: # cause problem with ssl enabled virtual hosts: This timeout includes<br /><br />/etc/apache2/mods-available/reqtimeout.conf: RequestReadTimeout header=20-40,minrate=500<br /><br />/etc/apache2/mods-available/reqtimeout.conf: RequestReadTimeout body=10,minrate=500<br /><br />/etc/apache2/mods-available/reqtimeout.load:LoadModule reqtimeout_module /usr/lib/apache2/modules/mod_reqtimeout.so<br /><br />/etc/apache2/mods-available/ssl.conf: # to use and second the expiring timeout (in seconds).<br /><br />/etc/apache2/mods-available/ssl.conf: SSLSessionCacheTimeout 300<br /><br />/etc/apache2/conf-available/timeout.conf:Timeout 60<br /><br />/etc/apache2/apache2.conf:# Timeout: The number of seconds before receives and sends time out.<br /><br />/etc/apache2/apache2.conf:Timeout 60<br /><br />/etc/apache2/apache2.conf:# KeepAliveTimeout: Number of seconds to wait for the next request from the<br /><br />/etc/apache2/apache2.conf:KeepAliveTimeout 5<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf:&lt;IfModule reqtimeout_module&gt;<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf: # mod_reqtimeout limits the time waiting on the client to prevent an<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf: # configuration, but it may be necessary to tune the timeout values to<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf: # mod_reqtimeout per virtual host.<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf: # Note: Lower timeouts may make sense on non-ssl virtual hosts but can<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf: # cause problem with ssl enabled virtual hosts: This timeout includes<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf: RequestReadTimeout header=20-40,minrate=500<br /><br />/etc/apache2/mods-enabled/reqtimeout.conf: RequestReadTimeout body=10,minrate=500<br /><br />/etc/apache2/mods-enabled/reqtimeout.load:LoadModule reqtimeout_module /usr/lib/apache2/modules/mod_reqtimeout.so<br /><br />/etc/apache2/mods-enabled/ssl.conf: # to use and second the expiring timeout (in seconds).<br /><br />/etc/apache2/mods-enabled/ssl.conf: SSLSessionCacheTimeout 300</pre>
</blockquote>
<p>Here you can see all configurations for Apache2 timeouts, but we only need to change <code> etc/apache2/conf-enabled/timeout.conf`</code>` because it will overwrite `/etc/apache2/apache2.conf` anyway.</p>
<p>PS: Remember to reload / restart your Web server after you change the configurations.</p>
<p>If we want to show the user at least a custom error page, we could add something like:</p>
<blockquote>
<p>ErrorDocument503 /error.php?errorcode=503<br />ErrorDocument 504 /error.php?errorcode=504</p>
</blockquote>
<p>… into our Apache configuration or in a .htaccess file, so that we can still use PHP to show an error page, also if the requested PHP call was killed. The problem here is that we will lose the error message / stack trace / request etc. from the error, and we can’t send e.g. an error into our error logging system. (take a look at sentry, it’s really helpful)</p>
<h3><strong>&#8211; PHP-FPM</strong></h3>
<p>Our PHP-FPM (FastCGI Process Manager) pool can be configured with a timeout (<a href="https://www.php.net/manual/en/install.fpm.configuration.php#request-terminate-timeout" target="_blank" rel="noopener">request-terminate-timeout</a>), but just like the Web server setting, this will kill the PHP worker in the middle of the process, and we can’t handle the error in PHP itself. There is also a setting (<a href="https://www.php.net/manual/en/install.fpm.configuration.php#process-control-timeout" target="_blank" rel="noopener">process_control_timeout</a>) that tells the child processes to wait for this much time before executing the signal received from the parent process, but I am uncertain if this is somehow helpfully here? So, our error handling in PHP can’t catch / log / show the error, and we will get a 503 HTTP error (Service Unavailable) in case of a timeout.</p>
<p>Shutdown functions will not be executed if the process is killed with a SIGTERM or SIGKILL signal. :-/</p>
<p>Source: <a href="https://www.php.net/manual/en/function.register-shutdown-function.php" target="_blank" rel="noopener">register_shutdown_function</a></p>
<p>PS: Remember to reload / restart your PHP-FPM Daemon after you change the configurations.</p>
<h3 class="western">&#8211; PHP</h3>
<p>The first idea from most of us would be maybe to limit the PHP execution time itself, and we are done, but that sounds easier than it is because `max_execution_time` ignores time spent on I/O (system commands e.g. `sleep()`, database queries (<i>SELECT SLEEP(100)</i>). But these are the bottlenecks of nearly all PHP applications, PHP itself is fast but the external called stuff isn’t.</p>
<blockquote>
<p>Theset_time_limit()function and the configuration directive <a href="https://www.php.net/manual/en/info.configuration.php#ini.max-execution-time" target="_blank" rel="noopener">max_execution_time</a> only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using <a href="https://www.php.net/manual/en/function.system.php" target="_blank" rel="noopener">system()</a>, stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.</p>
</blockquote>
<p>Source: <a href="https://www.php.net/manual/en/function.set-time-limit.php" target="_blank" rel="noopener"><u>set_time_limit</u></a></p>
<h3 class="western">&#8211; Database (MySQLi)</h3>
<p>Many PHP applications spend most of their time waiting for some bad SQL queries, where the developer missed adding the correct indexes and because we learned that the PHP max execution time did not work for database queries, we need one more timeout setting here.</p>
<p>There is the MYSQLI_OPT_CONNECT_TIMEOUT and MYSQLI_OPT_READ_TIMEOUT (Command execution result timeout in seconds. Available as of PHP 7.2.0. &#8211; <a href="https://www.php.net/manual/en/mysqli.options.php" target="_blank" rel="noopener">mysqli.options</a>) setting, and we can use that to limit the time for our queries.</p>
<p>In the end you will see a “Errno: 2006 | Error: MySQL server has gone away” error in your PHP application, but this error can be caught / reported, and the SQL query can be fixed, otherwise the Apache or PHP-FPM would kill the process, and we do not see the error because our error handler can’t handle it anyway.</p>
<h2>Summary:</h2>
<p>It’s complicated. PHP is not designed for long execution and that is good as it is, but if you need to increase the timeout it will be more complicated than I first thought. You need for example different “timeout”-code for testing different settings:</p>
<blockquote>
<p>// DEBUG: long-running sql-call<br />// Query(&#8216;SELECT SLEEP(600);&#8217;);<br /><br />// DEBUG: long-running system-call<br />// sleep(600);<br /><br />// DEBUG: long-running php-call<br />// while (1) { } // infinite loop</p>
</blockquote>
<h2><strong>Solution: </strong></h2>
<p>We can combine different timeout, but the timeout from the called commands e.g. database, curl, etc. will be combined with the timeout from PHP (max_execution_time) itself. The timeout from the Web server (e.g. Apache2: Timeout) and from PHP-FPM (request_terminate_timeout) need to be longer than the combined timeout from the application so that we still can use our PHP error handler.</p>
<p>e.g.: ~ 5 min. timeout</p>
<ol>
<li>MySQL read timeout: 240s ⇾ 4 min.
<pre>link-&gt;options(MYSQLI_OPT_READ_TIMEOUT, 240);</pre>
</li>
<li>PHP timeout: 300s ⇾ 5 min.
<pre>max_execution_time = 300</pre>
</li>
<li>Apache timeout: 360s ⇾ 6 min.
<pre>Timeout 360</pre>
</li>
<li>PHP-FPM: 420s ⇾ 7 min.
<pre>request_terminate_timeout = 420</pre>
</li>
</ol>
</div>
<div id="article-body" dir="ltr">
<p> </p>
<p>Links:</p>
<ul>
<li><a href="https://tideways.com/profiler/blog/an-introduction-to-php-fpm-tuning" target="_blank" rel="noopener">https://tideways.com/profiler/blog/an-introduction-to-php-fpm-tuning</a></li>
<li><a href="https://www.php.net/manual/en/install.fpm.php" target="_blank" rel="noopener">https://www.php.net/manual/en/install.fpm.php</a></li>
</ul>
</div>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2022%2F04%2Ftimeout-problems-web-server-php%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dtimeout-problems-web-server-php&amp;action_name=Timeout+Problems%3A+Web+Server+%2B+PHP&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2022/04/timeout-problems-web-server-php/?pk_campaign=feed&amp;pk_kwd=timeout-problems-web-server-php/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6852</post-id>	</item>
		<item>
		<title>Prepare your PHP Code for Static Analysis</title>
		<link>http://suckup.de/2020/12/prepare-your-php-code-for-static-analysis/?pk_campaign=feed&amp;pk_kwd=prepare-your-php-code-for-static-analysis&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=prepare-your-php-code-for-static-analysis</link>
					<comments>http://suckup.de/2020/12/prepare-your-php-code-for-static-analysis/?pk_campaign=feed&amp;pk_kwd=prepare-your-php-code-for-static-analysis#comments</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Sun, 13 Dec 2020 01:28:00 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[phpstan]]></category>
		<guid isPermaLink="false">http://suckup.de/?p=6787</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2020/12/prepare-your-php-code-for-static-analysis/?pk_campaign=feed&#038;pk_kwd=prepare-your-php-code-for-static-analysis">Prepare your PHP Code for Static Analysis</a></p>
<p>Prepare your PHP Code for Static Code Analysis, so that e.g. PHPStan or Psalm will understand your code.</p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2020%2F12%2Fprepare-your-php-code-for-static-analysis%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dprepare-your-php-code-for-static-analysis&amp;action_name=Prepare+your+PHP+Code+for+Static+Analysis&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2020/12/prepare-your-php-code-for-static-analysis/?pk_campaign=feed&#038;pk_kwd=prepare-your-php-code-for-static-analysis">Prepare your PHP Code for Static Analysis</a></p>

<p>Three years ago I got a new job as PHP developer, before that I called myself web developer because I build ReactJS, jQuery, CSS, HTML, &#8230; and PHP  stuff for a web agency. So now I am a full-time PHP developer and I converted a non typed  (no PHPDoc + no native types) project with ~ 10.000 classes into a project with ~ 90% type coverage. Here is what I have learned.</p>
<h4>1. Write code with IDE autocompletion support.</h4>
<p>If you have autocompletion in the IDE most likely the Static Analysis can understand the code as well. </p>
<p><span style="text-decoration: underline;"><em>Example:</em></span></p>
<p>bad:</p>
<p><code>-&gt;get('DB_Connection', true, false);</code></p>
<p>still bad:</p>
<p><code>-&gt;get(DB_Connection::class);</code></p>
<p>good:</p>
<p><code>getDbConnection(): DB_Connection</code></p>
<h4>2. Magic in Code is bad for the long run!</h4>
<p>Magic methods (__get, __set, &#8230;) for example can help to implement new stuff very fast, but the problem is nobody will understand it, you will have no autocompletion, no refactoring options, other developers will need more time to read and navigate in the code and in the end it will cost you much more time than you can save with it.</p>
<h4>3. Break the spell on Magic Code &#8230;</h4>
<p>&#8230; by explaining to everyone (Devs &gt; IDE &gt; Tools) what it does.</p>
<p><span style="text-decoration: underline;"><em>Example 1:</em></span></p>
<p>We use a simple Active Record Pattern, but we put all SQL stuff into the Factory classes, so that the Active Record class can be simple. (<a href="https://github.com/voku/phpstorm_issue_53352/tree/master/src/App/modules/Foo/libs" target="_blank" rel="noopener">Example</a>) But because of missing support for Generics we had no autocompletion without adding many dummy methods into the classes. So one of my first steps was to introduce a “<a href="https://gist.github.com/voku/3aba12eb898dfa209a787c398a331f9c" target="_blank" rel="noopener">PhpCsFixer</a>” that automatically adds the missing methods of the parent class with the correct types via “@method”-comments into these classes. </p>
<p><em><span style="text-decoration: underline;">Example 2:</span></em></p>
<p>Sometimes you can use more modern <a href="https://suckup.de/2020/02/modern-phpdoc-annotations/" target="_blank" rel="noopener">PHPDocs</a> to explain the function. Take a look at the “array_first” function in the linked Post.</p>
<p><em><span style="text-decoration: underline;">Example 3:</span></em></p>
<pre>/**<br /> * Return an array which has the Property-Values of the given Objects as Values.<br /> *<br /> * @param object[]    $ObjArray<br /> * @param string      $PropertyName<br /> * @param null|string $KeyPropertyName if given uses this Property as key for the returned Array otherwise the keys from the<br /> *                                     given array are used<br /> *<br /> * @throws Exception if no property with the given name was found<br /> *<br /> * @return array<br /> */<br />function propertyArray($ObjArray, $PropertyName, $KeyPropertyName = null): array {<br />    // init<br />    $PropertyArray = [];<br /><br />    foreach ($ObjArray as $key =&gt; $Obj) {<br />        if (!\property_exists($Obj, $PropertyName)) {<br />            throw new Exception('No Property with Name ' . $PropertyName . ' in Object Found - Value');<br />        }<br /><br />        $usedKey = $key;<br />        if ($KeyPropertyName) {<br />            if (!\property_exists($Obj, $KeyPropertyName)) {<br />                throw new Exception('No Property with Name ' . $PropertyName . ' in Object Found - Key');<br />            }<br />            $usedKey = $Obj-&gt;{$KeyPropertyName};<br />        }<br /><br />        $PropertyArray[$usedKey] = $Obj-&gt;{$PropertyName};<br />    }<br /><br />    return $PropertyArray;<br />}</pre>
<p>Sometimes it&#8217;s hard to describe the specific output types, so here you need to extend the  functions of your Static Code Analyze Tool, so that it knows what you are doing. ⇾ <a href="https://gist.github.com/voku/80722c9310c21719fbcfbfeb565cc6f9" target="_blank" rel="noopener">for example here you can find a solution for PHPStan</a> ⇽  but there is still no support for the IDE and so maybe it&#8217;s not the best idea to use magic like that at all. And I am sure it&#8217;s more simple to use specific and simple methods instead:  e.g. <code>BillCollection-&gt;getBillDates()</code></p>
<h4>4. Try to not use strings for the code.</h4>
<p>Strings are simple and flexible, but they are also bad for the long run. Mostly strings are used because it looks like a simple solution, but often they are redundant, you will have typos everywhere and the IDE and/or Static Analysis can&#8217;t analyze them because it&#8217;s just text.</p>
<p><em><span style="text-decoration: underline;">Example:</span></em></p>
<p>bad: </p>
<pre>AjaxEditDate::generator($bill-&gt;bill_id, $bill-&gt;date, 'Bill', 'date');</pre>
<ul>
<li>&#8220;Bill&#8221; ⇾ is not needed here, we can call e.g. <code>get_class($bill)</code> in the &#8220;generator&#8221; method</li>
<li>&#8220;date&#8221; ⇾ is not needed here, we can <a href="https://github.com/voku/phpstorm_issue_53352/blob/master/src/Framework/ActiveRecord/ActiveRow.php#L37" target="_blank" rel="noopener">fetch the property</a> name from the class</li>
<li>&#8220;$bill-&gt;bill_id&#8221; ⇾ is not needed here, we can get the primary id value from the class</li>
</ul>
<p>good:</p>
<pre>AjaxEditDate::generator($bill, $bill-&gt;m()-&gt;date);</pre>
<h4>5. Automate stuff via git hook and check it via CI server.</h4>
<p>Fixing bad code is only done if you disallow the same bad code for the future. With a pre-commit hook for git it&#8217;s simple to run these checks, but you need to check it again in the CI server because the developers can simply skip these checks.</p>
<p><em><span style="text-decoration: underline;">Example:</span></em></p>
<p>I introduced a check for disallowing global variables (global $foo &amp;&amp; $GLOBALS[&#8216;foo&#8217;]) via “<a href="https://gist.github.com/voku/d7d530ce2c072f5b4bdaafb040d1eb55" target="_blank" rel="noopener">PHP_CodeSniffer</a>”. </p>
<p><em><span style="text-decoration: underline;">Links:</span></em></p>
<ul>
<li><a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" target="_blank" rel="noopener">git-scm.com: git hooks</a></li>
<li><a href="https://github.com/captainhookphp/captainhook" target="_blank" rel="noopener">CaptainHook: git hook library for php</a></li>
</ul>
<h4>6. Use array shapes (or collections) if you need to return an array, please.</h4>
<p><a href="https://phpstan.org/writing-php-code/phpdoc-types#array-shapes" target="_blank" rel="noopener">Array shapes</a> are like arrays but with fixed keys, so that you can define the types of each key in the PHPDocs.</p>
<p>You will have <a href="https://plugins.jetbrains.com/plugin/9927-deep-assoc-completion" target="_blank" rel="noopener">autocompletion for the IDE</a> + all other devs can see what the method will return + you will notice if you&#8217;re better retuning an object because it will be very hard to describe the output for complex data structures and Static Analysis can use and check the types. </p>
<p><em><span style="text-decoration: underline;">Example:</span></em></p>
<pre>/**<br /> * @return array{<br /> *    missing: array&lt;ShoppingCartLib::TAB_*,string&gt;,<br /> *    disabled: array&lt;ShoppingCartLib::TAB_*,string&gt;<br /> * }<br /> */<br />private static function getShoppingCartTabStatus(): array {<br /> ...<br />}</pre>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2020%2F12%2Fprepare-your-php-code-for-static-analysis%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dprepare-your-php-code-for-static-analysis&amp;action_name=Prepare+your+PHP+Code+for+Static+Analysis&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2020/12/prepare-your-php-code-for-static-analysis/?pk_campaign=feed&amp;pk_kwd=prepare-your-php-code-for-static-analysis/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6787</post-id>	</item>
		<item>
		<title>Generics in PHP via PHPDocs</title>
		<link>http://suckup.de/2020/08/generics-in-php-via-phpdocs/?pk_campaign=feed&amp;pk_kwd=generics-in-php-via-phpdocs&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=generics-in-php-via-phpdocs</link>
					<comments>http://suckup.de/2020/08/generics-in-php-via-phpdocs/?pk_campaign=feed&amp;pk_kwd=generics-in-php-via-phpdocs#respond</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Sat, 29 Aug 2020 00:34:02 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[phpdoc]]></category>
		<guid isPermaLink="false">http://suckup.de/?p=6752</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2020/08/generics-in-php-via-phpdocs/?pk_campaign=feed&#038;pk_kwd=generics-in-php-via-phpdocs">Generics in PHP via PHPDocs</a></p>
<p>Examples for Generics in PHP via PHPDocs / Template annotations.</p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2020%2F08%2Fgenerics-in-php-via-phpdocs%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dgenerics-in-php-via-phpdocs&amp;action_name=Generics+in+PHP+via+PHPDocs&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2020/08/generics-in-php-via-phpdocs/?pk_campaign=feed&#038;pk_kwd=generics-in-php-via-phpdocs">Generics in PHP via PHPDocs</a></p>

<p style="text-align: left;">If you did not know that you can use Generics in PHP or you do not exactly know how to use it or why you should use it, then the next examples are for you.</p>
<h3 id="type-variables">Type variables via @template</h3>
<p>The&nbsp;<code>@template</code> tag allows classes and functions to declare a generic type parameter. The next examples starts with simple functions, so that we understand how it works, and then we will see the power of this in classes.</p>



<hr class="wp-block-separator is-style-wide"/>



<p><strong>A dummy function that will return the input.</strong></p>
<p><strong>⇾</strong> <a href="https://phpstan.org/r/1922279b-9786-4523-939d-dddcfd4ebb86" target="_blank" rel="noopener noreferrer"><strong>https://phpstan.org/r/1922279b-9786-4523-939d-dddcfd4ebb86</strong></a></p>



<pre class="wp-block-code"><code>    &lt;?php    

    /**
     * @param \Exception $param
     * @return \Exception
     *
     * @template T of \Exception
     * @psalm-param T $param
     * @psalm-return T
     */
    function foo($param) { ... }

    foo(new \InvalidArgumentException()); // The static-analysis-tool knows that 
                                          // the type is still "\InvalidArgumentException" 
                                          // because of the type variable.
</code></pre>



<p><strong>@template T of \Exception</strong> // here we create a new type variable, and we force that it must be an instance of \Exception</p>
<p><strong>@phpstan-param T $param</strong> // here we say that the static-analysis-tool need to remember the type that this variable had before (you can use @psalm-* or @phpstan-* both works with both tools)</p>
<p><strong>@phpstan-return T</strong> // and that the return type is the same as the input type&nbsp;</p>



<hr class="wp-block-separator is-style-wide"/>



<p><strong>A simple function that gets the first element of an array or a fallback. </strong></p>
<p>In the @param PHPDocs we write “mixed” because this function can handle different types. But this information is not very helpful if you want to understand programmatically what the code does, so we need to give the static-analysis-tools some more information. </p>
<p><strong>⇾ <a href="https://phpstan.org/r/1900a2af-f5c1-4942-939c-409928a5ac4a" target="_blank" rel="noopener noreferrer">https://phpstan.org/r/1900a2af-f5c1-4942-939c-409928a5ac4a</a></strong></p>



<pre class="wp-block-code"><code>    &lt;?php
     
    /**
     * @param array&lt;mixed> $array
     * @param mixed        $fallback &lt;p>This fallback will be used, if the array is empty.&lt;/p>
     *
     * @return mixed|null
     *
     * @template TFirst
     * @template TFirstFallback
     * @psalm-param TFirst&#91;] $array
     * @psalm-param TFirstFallback $fallback
     * @psalm-return TFirst|TFirstFallback
     */
    function array_first(array $array, $fallback)
    {
        $key_first = array_key_first($array);
        if ($key_first === null) {
            return $fallback;
        }

        return $array&#91;$key_first];
    }

    array_first(&#91;1, 2, 3], null); 

    if ($a === 'foo') { // The static-analysis-tool knows that 
                        // === between int|null and 'foo' will always evaluate to false.
	    // ...
    }</code></pre>



<p><strong>@template TFirst</strong> // we again define your typed variables</p>
<p><strong>@template TFirstFallback</strong> // and one more because we have two inputs where we want to keep track of the types</p>
<p><strong>@psalm-param TFirst[] $array</strong> // here we define that $array is an array of TFirst types</p>
<p><strong>@psalm-param TFirstFallback $fallback</strong> // and that $fallback is some other type that comes into this function</p>
<p><strong>@psalm-return TFirst|TFirstFallback</strong> // now we define the return type as an element of&nbsp; the $array or the $fallback type&nbsp;</p>



<hr class="wp-block-separator is-style-wide"/>



<p>&nbsp;<strong>Very basic <em>Active Record</em> + Generics</strong></p>
<p>The IDE support for generics is currently not there, :-/ so that we still need some hacks (see @method) for e.g. PhpStorm to have autocompletion.</p>
<p><strong>⇾ </strong><a href="https://phpstan.org/r/f88f5cd4-1bb9-4a09-baae-069fddb10b12" target="_blank" rel="noopener noreferrer"><strong>https://phpstan.org/r/f88f5cd4-1bb9-4a09-baae-069fddb10b12</strong></a></p>
<p><strong><a href="https://github.com/voku/phpstorm_issue_53352/tree/master/src/Framework/ActiveRecord" target="_blank" rel="noopener noreferrer">https://github.com/voku/phpstorm_issue_53352/tree/master/src/Framework/ActiveRecord</a></strong></p>



<pre class="wp-block-code"><code>&lt;?php

class ActiveRow
{
    /**
     * @var ManagedFactory&lt;static>
     */
    public $factory;

    /**
     * @param Factory&lt;ActiveRow>|ManagedFactory&lt;static> $factory
     * @param null|array                                $row
     */
    public function __construct(Factory $factory, array $row = null) {
        $this->factory = &amp;$factory;
    }
}

/**
 * @template T
 */
abstract class Factory
{
    /**
     * @var string
     *
     * @internal
     *
     * @psalm-var class-string&lt;T>
     */
    protected $classname;

    /**
     * @return static
     */
    public static function create() {
        return new static();
    }
}

/**
 * @template  T
 * @extends   Factory&lt;T>
 */
class ManagedFactory extends Factory
{
    /**
     * @param string $classname
     *
     * @return void
     *
     * @psalm-param class-string&lt;T> $classname
     */
    protected function setClass(string $classname): void
    {
        if (\class_exists($classname) === false) {
            /** @noinspection ThrowRawExceptionInspection */
            throw new Exception('TODO');
        }

        if (\is_subclass_of($classname, ActiveRow::class) === false) {
            /** @noinspection ThrowRawExceptionInspection */
            throw new Exception('TODO');
        }

        $this->classname = $classname;
    }

    // ...
}

final class Foo extends ActiveRow {

    public int $foo_id;

    public int $user_id;

    // --------------------------------------
    // add more logic here ...
    // --------------------------------------
}

/**
 * @method Foo&#91;] fetchAll(...)
 *
 * @see Foo
 *
 * // warning -> do not edit this comment by hand, it's auto-generated and the @method phpdocs are for IDE support       
 * //         -> https://gist.github.com/voku/3aba12eb898dfa209a787c398a331f9c
 *
 * @extends ManagedFactory&lt;Foo>
 */
final class FooFactory extends ManagedFactory
{
    // -----------------------------------------------
    // add sql stuff here ...
    // -----------------------------------------------
}</code></pre>



<hr class="wp-block-separator is-style-wide"/>



<p><strong>A more complex collection example.</strong></p>
<p>In the end we can extend the “AbstractCollection” and the static-analysis-tools knows the types of all the methods.&nbsp;</p>
<p><strong><a href="https://github.com/voku/Arrayy/tree/master/src/Type" target="_blank" rel="noopener noreferrer">https://github.com/voku/Arrayy/tree/master/src/Type</a></strong></p>



<pre class="wp-block-code"><code>/**
 * @template TKey of array-key
 * @template T
 * @template-extends \ArrayObject&lt;TKey,T>
 * @template-implements \IteratorAggregate&lt;TKey,T>
 * @template-implements \ArrayAccess&lt;TKey|null,T>
 */
class Arrayy extends \ArrayObject implements \IteratorAggregate, \ArrayAccess, \Serializable, \JsonSerializable, \Countable
{ ... }

/**
 * @template TKey of array-key
 * @template T
 * @template-extends \IteratorAggregate&lt;TKey,T>
 * @template-extends \ArrayAccess&lt;TKey|null,T>
 */
interface CollectionInterface extends \IteratorAggregate, \ArrayAccess, \Serializable, \JsonSerializable, \Countable
{ ... }

/**
 * @template   TKey of array-key
 * @template   T
 * @extends    Arrayy&lt;TKey,T>
 * @implements CollectionInterface&lt;TKey,T>
 */
abstract class AbstractCollection extends Arrayy implements CollectionInterface
{ ... }

/**
 * @template TKey of array-key
 * @template T
 * @extends  AbstractCollection&lt;TKey,T>
 */
class Collection extends AbstractCollection
{ ... }</code></pre>



<p><strong>Links:</strong></p>
<p>⇾ <a href="https://phpstan.org/blog/generics-in-php-using-phpdocs" target="_blank" rel="noopener noreferrer">https://phpstan.org/blog/generics-in-php-using-phpdocs</a></p>
<p>⇾ <a href="https://psalm.dev/docs/annotating_code/templated_annotations/" target="_blank" rel="noopener noreferrer">https://psalm.dev/docs/annotating_code/templated_annotations/</a></p>
<p>⇾ <a href="https://stitcher.io/blog/php-generics-and-why-we-need-them" target="_blank" rel="noopener noreferrer">https://stitcher.io/blog/php-generics-and-why-we-need-them</a></p>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2020%2F08%2Fgenerics-in-php-via-phpdocs%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dgenerics-in-php-via-phpdocs&amp;action_name=Generics+in+PHP+via+PHPDocs&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2020/08/generics-in-php-via-phpdocs/?pk_campaign=feed&amp;pk_kwd=generics-in-php-via-phpdocs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6752</post-id>	</item>
		<item>
		<title>❤️ Simple PHP Code Parser</title>
		<link>http://suckup.de/2020/08/simple-php-code-parser/?pk_campaign=feed&amp;pk_kwd=simple-php-code-parser&amp;utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=simple-php-code-parser</link>
					<comments>http://suckup.de/2020/08/simple-php-code-parser/?pk_campaign=feed&amp;pk_kwd=simple-php-code-parser#comments</comments>
		
		<dc:creator><![CDATA[voku]]></dc:creator>
		<pubDate>Fri, 07 Aug 2020 00:10:59 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[code]]></category>
		<guid isPermaLink="false">http://suckup.de/?p=6733</guid>

					<description><![CDATA[<p><a href="http://suckup.de/2020/08/simple-php-code-parser/?pk_campaign=feed&#038;pk_kwd=simple-php-code-parser">❤️ Simple PHP Code Parser</a></p>
<p>Simple PHP Code Parser &#124; a simple data structure from your php code</p>
<img src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2020%2F08%2Fsimple-php-code-parser%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dsimple-php-code-parser&amp;action_name=%E2%9D%A4%EF%B8%8F+Simple+PHP+Code+Parser&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></description>
										<content:encoded><![CDATA[<p><a href="http://suckup.de/2020/08/simple-php-code-parser/?pk_campaign=feed&#038;pk_kwd=simple-php-code-parser">❤️ Simple PHP Code Parser</a></p>

<p>It based on code from &#8220;<a href="https://github.com/JetBrains/phpstorm-stubs" target="_blank" rel="noopener noreferrer">JetBrains/phpstorm-stubs&#8221;</a> but instead of Php-Reflection we now use nikic/PHP-Parser, BetterReflection, phpDocumentor and PHPStan/phpdoc-parser internally. So, you can get even more information about the code. For example, psalm- / phpstan-phpdoc annotations or inheritdoc from methods.</p>
<p><strong>Install</strong>:</p>
<pre>composer require voku/simple-php-code-parser</pre>
<p><strong>Link</strong>:</p>
<p><a href="https://github.com/voku/Simple-PHP-Code-Parser">voku/Simple-PHP-Code-Parser</a></p>
<p><strong>More</strong>:</p>
<ul>
<li>there is also a &#8220;.phar&#8221; version for e.g. phpdoc checks: <a href="https://github.com/voku/Simple-PHP-Code-Parser/releases">voku/Simple-PHP-Code-Parser/releases</a></li>
<li>and an API documentations helper for your README file, based on the simple php code parser: <a href="https://github.com/voku/Php-Readme-Helper">voku/Php-Readme-Helper</a></li>
</ul>



<hr class="wp-block-separator is-style-wide"/>



<p><strong>Example</strong>: get value from define in &#8220;\foo\bar&#8221; namespace</p>



<pre class="wp-block-code"><code>$code = '
  &lt;?php
  namespace foo\bar;
  define("FOO_BAR", "Lall");
';

$phpCode = PhpCodeParser::getFromString($code);
$phpConstants = $phpCode->getConstants();

$phpConstants&#91;'\foo\bar\FOO_BAR']->value; // 'Lall'</code></pre>



<hr class="wp-block-separator is-style-wide"/>



<p><strong>Example</strong>: get information about @property phpdoc from a class</p>



<pre class="wp-block-code"><code>$code = '
  &lt;?php
  /** 
   * @property int&#91;] $foo 
   */
  abstract class Foo { }
';

$phpCode = PhpCodeParser::getFromString($code);
$phpClass = $phpCode->getClass('Foo');

$phpClass->properties&#91;'foo']->typeFromPhpDoc); // int</code></pre>



<hr class="wp-block-separator is-style-wide"/>



<p><strong>Example</strong>: get classes from a string (or from a class-name or from a file or from a directory)</p>



<pre class="wp-block-code"><code>$code = '
&lt;?php
namespace voku\tests;
class SimpleClass {}
$obja = new class() {};
$objb = new class {};
class AnotherClass {}
';

$phpCode = \voku\SimplePhpParser\Parsers\PhpCodeParser::getFromString($code);
$phpClasses = $phpCode->getClasses();

var_dump($phpClasses&#91;'voku\tests\SimpleClass']); // "PHPClass"-object</code></pre>



<hr class="wp-block-separator is-style-wide"/>
<img loading="lazy" decoding="async" src="https://suckup.de/piwik/piwik.php?idsite=1&amp;rec=1&amp;url=http%3A%2F%2Fsuckup.de%2F2020%2F08%2Fsimple-php-code-parser%2F%3Fpk_campaign%3Dfeed%26pk_kwd%3Dsimple-php-code-parser&amp;action_name=%E2%9D%A4%EF%B8%8F+Simple+PHP+Code+Parser&amp;urlref=http%3A%2F%2Fsuckup.de%2Ffeed%2F" style="border:0;width:0;height:0" width="0" height="0" alt="" />]]></content:encoded>
					
					<wfw:commentRss>http://suckup.de/2020/08/simple-php-code-parser/?pk_campaign=feed&amp;pk_kwd=simple-php-code-parser/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6733</post-id>	</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

Object Caching 61/163 objects using Memcached
Page Caching using Memcached (Page is feed) 
Content Delivery Network via N/A
Lazy Loading (feed)
Database Caching 2/21 queries in 0.003 seconds using Memcached

Served from: suckup.de @ 2026-03-30 23:56:47 by W3 Total Cache
-->