oliverdavies.uk/content/node.7064860b-42de-47c3-b5ac-3560d941fe0f.yml

180 lines
9.7 KiB
YAML

uuid:
- value: 7064860b-42de-47c3-b5ac-3560d941fe0f
langcode:
- value: en
type:
- target_id: daily_email
target_type: node_type
target_uuid: 8bde1f2f-eef9-4f2d-ae9c-96921f8193d7
revision_timestamp:
- value: '2025-05-11T09:00:20+00:00'
revision_uid:
- target_type: user
target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849
revision_log: { }
status:
- value: true
uid:
- target_type: user
target_uuid: b8966985-d4b2-42a7-a319-2e94ccfbb849
title:
- value: 'Which level is right for you?'
created:
- value: '2024-02-20T00:00:00+00:00'
changed:
- value: '2025-05-11T09:00:20+00:00'
promote:
- value: false
sticky:
- value: false
default_langcode:
- value: true
revision_translation_affected:
- value: true
path:
- alias: /daily/2024/02/20/which-level-is-right-for-you
langcode: en
body:
- value: |
<p>Today, whilst working on <a href="/daily/2024/02/19/introducing-versa">Versa</a>, I was experimenting with different PHPStan levels.</p>
<p>Level 1 is the least strict level, and applies the fewest rules and returns the fewest results.</p>
<p>As you increase the level, the stricter PHPStan is.</p>
<h2 id="levelling-up-to-9">Levelling up to 9</h2>
<p>Here is the code to get the values of the <code>--extra-args</code> and <code>--working-dir</code> options:</p>
<pre><code class="language-php">$extraArgs = $input-&gt;getOption('extra-args');
$workingDir = $input-&gt;getOption('working-dir');
</code></pre>
<p>This passed PHPStan level 8, but these are the errors I get when running level 9:</p>
<pre><code class="language-plain">------ ------------------------------------------------------------------------------------------------------- Line versa
------ ------------------------------------------------------------------------------------------------------- 61 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
62 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
72 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
73 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
84 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
85 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
94 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
95 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
104 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
105 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
119 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
120 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
------ ------------------------------------------------------------------------------------------------------- [ERROR] Found 12 errors
</code></pre>
<p>The issue is that <code>$input-&gt;getOption()</code> from Symfony's <code>InputInterface</code> returns <code>mixed</code> - even though it always returns <code>null</code> or a string.</p>
<p>If I did <code>--working-dir 2</code>, it would return the string <code>"2"</code>.</p>
<p>An empty string throws an error, and an empty value (if there are no extra arguments) returns <code>null</code>.</p>
<p>So, I know <code>$workingDir</code> will always be a string and <code>$extraArgs</code> will either a string or <code>null</code>.</p>
<h2 id="passing-level-8">Passing level 8</h2>
<p>To pass level 8, PHPStan needs to be sure the variables are what I think they are.</p>
<p>Here's the code I can use to get it to pass:</p>
<pre><code class="language-php">$extraArgs = $input-&gt;getOption('extra-args');
$workingDir = $input-&gt;getOption('working-dir');
assert(is_string($extraArgs) || is_null($extraArgs));
assert(is_string($workingDir));
</code></pre>
<p>By using <code>assert()</code> and throwing an Exception if the condition fails, PHPStan is now happy with the code and my code passes level 9.</p>
<h2 id="here%27s-the-thing">Here's the thing</h2>
<p>Although the extra code gets PHPStan to pass, it it worth it?</p>
<p>Is this extra code adding value? Does it make the code more readable or is it likely to prevent a bug?</p>
<p>In this case, I know the value will always be the type I expect.</p>
<p>I can work around this using a baseline or annotations for PHPStan to ignore these lines, <strong>or is level 8 good enough for this project</strong>?</p>
<p>Similar to 100% test coverage, is aiming for the highest PHPStan level an objective to be met, or is enough value being added added by the lower level?</p>
<p>Which level is right for you and this codebase?</p>
format: full_html
processed: |
<p>Today, whilst working on <a href="http://default/daily/2024/02/19/introducing-versa">Versa</a>, I was experimenting with different PHPStan levels.</p>
<p>Level 1 is the least strict level, and applies the fewest rules and returns the fewest results.</p>
<p>As you increase the level, the stricter PHPStan is.</p>
<h2 id="levelling-up-to-9">Levelling up to 9</h2>
<p>Here is the code to get the values of the <code>--extra-args</code> and <code>--working-dir</code> options:</p>
<pre><code class="language-php">$extraArgs = $input-&gt;getOption('extra-args');
$workingDir = $input-&gt;getOption('working-dir');
</code></pre>
<p>This passed PHPStan level 8, but these are the errors I get when running level 9:</p>
<pre><code class="language-plain">------ ------------------------------------------------------------------------------------------------------- Line versa
------ ------------------------------------------------------------------------------------------------------- 61 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
62 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
72 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
73 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
84 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
85 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
94 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
95 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
104 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
105 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
119 Parameter $extraArgs of static method App\Process\Process::create() expects string|null, mixed given.
120 Parameter $workingDir of static method App\Process\Process::create() expects string, mixed given.
------ ------------------------------------------------------------------------------------------------------- [ERROR] Found 12 errors
</code></pre>
<p>The issue is that <code>$input-&gt;getOption()</code> from Symfony's <code>InputInterface</code> returns <code>mixed</code> - even though it always returns <code>null</code> or a string.</p>
<p>If I did <code>--working-dir 2</code>, it would return the string <code>"2"</code>.</p>
<p>An empty string throws an error, and an empty value (if there are no extra arguments) returns <code>null</code>.</p>
<p>So, I know <code>$workingDir</code> will always be a string and <code>$extraArgs</code> will either a string or <code>null</code>.</p>
<h2 id="passing-level-8">Passing level 8</h2>
<p>To pass level 8, PHPStan needs to be sure the variables are what I think they are.</p>
<p>Here's the code I can use to get it to pass:</p>
<pre><code class="language-php">$extraArgs = $input-&gt;getOption('extra-args');
$workingDir = $input-&gt;getOption('working-dir');
assert(is_string($extraArgs) || is_null($extraArgs));
assert(is_string($workingDir));
</code></pre>
<p>By using <code>assert()</code> and throwing an Exception if the condition fails, PHPStan is now happy with the code and my code passes level 9.</p>
<h2 id="here%27s-the-thing">Here's the thing</h2>
<p>Although the extra code gets PHPStan to pass, it it worth it?</p>
<p>Is this extra code adding value? Does it make the code more readable or is it likely to prevent a bug?</p>
<p>In this case, I know the value will always be the type I expect.</p>
<p>I can work around this using a baseline or annotations for PHPStan to ignore these lines, <strong>or is level 8 good enough for this project</strong>?</p>
<p>Similar to 100% test coverage, is aiming for the highest PHPStan level an objective to be met, or is enough value being added added by the lower level?</p>
<p>Which level is right for you and this codebase?</p>
summary: null
field_daily_email_cta: { }