<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Iván Stepaniuk's Technical Blog</title>
    <description>Iván Stepaniuk's blog on crafting software</description>
    <link>https://blog.istepaniuk.com/</link>
    <atom:link href="https://blog.istepaniuk.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 07 Jul 2023 18:31:19 -0500</pubDate>
    <lastBuildDate>Fri, 07 Jul 2023 18:31:19 -0500</lastBuildDate>
    <generator>Jekyll v4.1.0</generator>
    
      <item>
        <title>There Are Only Three Types of Bug</title>
        <description>&lt;p&gt;As soon as there is code, there will be bugs. Gojko Adzic said in a keynote in the Agile Testing Days in Berlin, almost
a decade ago;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;… It’s called an &lt;strong&gt;&lt;em&gt;issue tracker&lt;/em&gt;&lt;/strong&gt; because when you have one, then you have an issue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The traditional bug or “issue tracking” processes have advantages on waterfall engineering processes, but 
they have very little to do with an agile development environment. We don’t need to document past bugs to avoid 
them in the future, we don’t build knowledge bases of defects; we have unit tests that prevent regression.&lt;/p&gt;

&lt;h1 id=&quot;1-urgent-bugs&quot;&gt;1. Urgent bugs&lt;/h1&gt;
&lt;p&gt;Bugs that are so urgent as to stop whatever you are working on and start fixing it.&lt;/p&gt;

&lt;h1 id=&quot;2-important-bugs&quot;&gt;2. Important bugs&lt;/h1&gt;
&lt;p&gt;Bugs that will have the top priority as to what to work on NEXT; they are at the top of your TODO list.&lt;/p&gt;

&lt;h1 id=&quot;3-bugs-that-you-will-not-fix&quot;&gt;3. Bugs that you will NOT fix&lt;/h1&gt;
&lt;p&gt;This defect is not urgent nor important as per the previous definitions and likely has been there for some time. 
If it’s not important enough to be considered of type 2. then there is no need to keep this on any backlog or 
issue tracker. Close it or delete it. Adios.&lt;/p&gt;

&lt;h2 id=&quot;is-its-a-bug-or-a-feature&quot;&gt;Is it’s a bug or a feature?&lt;/h2&gt;
&lt;p&gt;There is no “type 4”. If fixing a bug is not important enough to be of type 2. it’s unlikely that it will 
have priority over anything else in your backlog anyway. If it really does, by all means go ahead and treat the bug
as any other story, subject to the same priorities, refinement and estimation process (if you do that),
and of course the same definition of done. But for example, if you are doing Scrum and you wouldn’t tackle this bug 
on your next sprint either, then I’m afraid it was of type 3.&lt;/p&gt;
</description>
        <pubDate>Thu, 07 Oct 2021 00:00:00 -0500</pubDate>
        <link>https://blog.istepaniuk.com/there-are-only-three-types-of-bug/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/there-are-only-three-types-of-bug/</guid>
        
        <category>agile</category>
        
        
      </item>
    
      <item>
        <title>Sentinel Values Considered Harmful</title>
        <description>&lt;h3 id=&quot;tldr&quot;&gt;TL;DR:&lt;/h3&gt;
&lt;p&gt;Sentinel values and other kinds of “flag” values have no place in modern languages, use types!&lt;/p&gt;

&lt;h3 id=&quot;a-bit-longer&quot;&gt;A bit longer:&lt;/h3&gt;
&lt;p&gt;In languages like C, it is common to use &lt;a href=&quot;https://en.wikipedia.org/wiki/Sentinel_value&quot;&gt;sentinel values&lt;/a&gt;,
sometimes also called flag value, signal value, etc., as a way to interrupt a loop. It is also common 
to return negative values as a way to indicate an error condition where positive values indicate that
things went well.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// not found!&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This makes a lot of sense in C or even straight assembler; the CPU can very quickly determine 
whether a value is positive and branch conditionally.&lt;/p&gt;

&lt;p&gt;You will find similar APIs in modern languages as well, such as Python’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find()&lt;/code&gt;, that keep 
the tradition alive:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;an apple, a pear and a banana&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;orange&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, when writing your own code in a typed language, this is just an anti-pattern, and a clear
indication that &lt;a href=&quot;https://refactoring.guru/smells/primitive-obsession&quot;&gt;you are using primitives where you should not&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So for example in Java, instead of doing:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findCustomerIdByUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Username&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Customer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;customers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Consider the much safer:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CustomerId&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findCustomerIdByUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Username&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Customer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;customers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getUsername&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;NullCustomerId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case, using a &lt;a href=&quot;https://en.wikipedia.org/wiki/Null_object_pattern#Java&quot;&gt;null object pattern&lt;/a&gt; (but
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw new CustomerNotFoundException()&lt;/code&gt; might be the best choice in some circumstances).&lt;/p&gt;
</description>
        <pubDate>Wed, 22 Sep 2021 00:00:00 -0500</pubDate>
        <link>https://blog.istepaniuk.com/sentinel-values-considered-harmful/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/sentinel-values-considered-harmful/</guid>
        
        <category>design</category>
        
        
      </item>
    
      <item>
        <title>Extract Test Fixtures Early</title>
        <description>&lt;h3 id=&quot;tldr&quot;&gt;TL;DR:&lt;/h3&gt;
&lt;p&gt;When writing unit tests, extract test fixtures early on.&lt;/p&gt;

&lt;h3 id=&quot;a-bit-longer&quot;&gt;A bit longer:&lt;/h3&gt;
&lt;p&gt;We often delay some types of refactoring with good reason. During a TDD session, 
an &lt;em&gt;extract class&lt;/em&gt;, or even &lt;em&gt;extract method&lt;/em&gt; done too early might limit your 
refactoring chances later, so we sometimes let refactors “ripe”.&lt;/p&gt;

&lt;p&gt;However, the construction of the objects involved in unit tests is better elsewhere and
not on the tests themselves, as soon as possible.&lt;/p&gt;

&lt;p&gt;The reason is that there is no amount of automatic refactoring that will let you easily change 
the signature of your &lt;em&gt;Value Objects&lt;/em&gt; if they are repeated over and over in every related unit
test.&lt;/p&gt;

&lt;p&gt;So instead of doing:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;it_publishes_an_ugraded_event_when_a_regular_tenant_switches_to_premium&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumPlan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Plan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;example&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premium&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plan&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PlanType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PREMIUM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;tenant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;switchToPlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;premiumPlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;verify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mockEventPublisher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AccountPlanUpgraded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;it_publishes_a_downgraded_event_when_a_regular_tenant_switches_to_a_free_plan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;freePlan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Plan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;example&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plan&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PlanType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FREE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;tenant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;switchToPlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;freePlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;verify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mockEventPublisher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AccountPlanDowngraded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// and many more ... &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Try to introduce fixtures early on:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;it_publishes_an_ugraded_event_when_a_regular_tenant_switches_to_premium&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;premiumPlan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Fixtures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;givenAPremiumPlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;tenant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;switchToPlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;premiumPlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;verify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mockEventPublisher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AccountPlanUpgraded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;it_publishes_a_downgraded_event_when_a_regular_tenant_switches_to_a_free_plan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;freePlan&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Fixtures&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;givenAFreePlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;tenant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;switchToPlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;freePlan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;verify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mockEventPublisher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AccountPlanDowngraded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// and many more ... &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Fri, 10 Sep 2021 00:00:00 -0500</pubDate>
        <link>https://blog.istepaniuk.com/extract-test-fixtures-early/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/extract-test-fixtures-early/</guid>
        
        <category>testing</category>
        
        <category>tdd</category>
        
        <category>design</category>
        
        
      </item>
    
      <item>
        <title>Implementation Inheritance Last</title>
        <description>&lt;h3 id=&quot;tldr&quot;&gt;TL;DR:&lt;/h3&gt;
&lt;p&gt;When designing, consider class composition and delegation BEFORE extending or designing classes for extension. Extension is less reusable and less maintainable. Don’t be very “clever”.&lt;/p&gt;

&lt;h3 id=&quot;a-bit-longer&quot;&gt;A bit longer:&lt;/h3&gt;
&lt;p&gt;Implementation inheritance is often not the best pattern to reuse code or make code reusable.&lt;/p&gt;

&lt;p&gt;Implementation inheritance breaks encapsulation and forces us to peek at the parent implementation to be able to inherit from it safely, the interface of the base class is not a safe contract to extend on.&lt;/p&gt;

&lt;p&gt;Inheritance is the tightest form of code coupling. It is especially dangerous in Ruby when mixed with concerns out of sight, mixins, and the fact that Ruby does not have a ‘final’ or ‘sealed’ mechanism to prevent unsafe inheritance.&lt;/p&gt;

&lt;p&gt;More often than not, it is better to compose or delegate rather to extend, especially when there is no clear and orthodox inheritance pattern (template method, strategy, etc.) It is often impossible to get inheritance right when adding features to existing code that does not follow OCP, not to mention trying to reuse these bits afterwards! Impossible.&lt;/p&gt;

&lt;p&gt;Composition is normally accomplished by DI through the constructor in the object that needs the behavior. DI in the Ruby world is kind of a controversial thing, mainly because of people misread and missquote @dhh. That aside, let’s just refrain from further designing “clever” inheritance-first designs. Even hardcoding dependencies in a service is a better way! (but you better not http://goo.gl/tLMGGb)&lt;/p&gt;

</description>
        <pubDate>Tue, 24 May 2016 00:00:00 -0500</pubDate>
        <link>https://blog.istepaniuk.com/implementation-inheritance-last/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/implementation-inheritance-last/</guid>
        
        <category>design</category>
        
        <category>ruby</category>
        
        
      </item>
    
      <item>
        <title>The Shapes of Bad Code, Part 2</title>
        <description>&lt;p&gt;I have noticed that when looking at some not-so-awesome piece of code for the first time, I can tell many things about it even before putting my glasses on, and while scrolling at a speed at which it is actually impossible to read anything at all.&lt;/p&gt;

&lt;p&gt;This is Part 2, check out &lt;a href=&quot;/the-shapes-of-bad-code-part-1/&quot;&gt;Part 1&lt;/a&gt;!&lt;/p&gt;

&lt;h3 id=&quot;the-shape-of-bad-code-part-2&quot;&gt;The Shape of Bad Code, Part 2&lt;/h3&gt;

&lt;h4 id=&quot;abuse-of-vertical-spaces&quot;&gt;Abuse of vertical spaces&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/img/shape-vertical-space.png&quot; alt=&quot;Vertical space abuse&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The single-responsibility principle applies at many levels, and it definitely does at a method level. When a method does more than one thing but has not been split in separated methods, it is common to see vertical spaces separating this different functions. If you need to add vertical space to understand the body of a method, wouldn’t it be better to extract that second section as a separated method and give it a &lt;strong&gt;good name&lt;/strong&gt;?&lt;/p&gt;

&lt;h4 id=&quot;comment-delimited-sections&quot;&gt;Comment-delimited sections&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/img/shape-vertical-comments.png&quot; alt=&quot;Section comments&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is a somewhat improved version of the previous shape. Each section is separated by vertical space, but comments have been added at the start of each section to try to make the reader’s life easier.&lt;/p&gt;

&lt;p&gt;Again, more often than not, this sections can be extracted into several methods, and those comments can be transformed into the names of the extracted methods. If there where many sections to extract, it is also probable that these methods actually belong to a &lt;strong&gt;new class&lt;/strong&gt;!&lt;/p&gt;

&lt;h4 id=&quot;stay-tuned-for-the-last-ugly-code-shapes&quot;&gt;Stay tuned for the last ugly code shapes!&lt;/h4&gt;
</description>
        <pubDate>Wed, 28 Jan 2015 00:00:00 -0600</pubDate>
        <link>https://blog.istepaniuk.com/the-shapes-of-bad-code-part-2/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/the-shapes-of-bad-code-part-2/</guid>
        
        <category>quality</category>
        
        
      </item>
    
      <item>
        <title>I will never work for you</title>
        <description>&lt;p&gt;There are a couple of industry sectors that I would rather not write software for, ever. The most important ones are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Weapons, Military &amp;amp; Defense&lt;/li&gt;
  &lt;li&gt;Most Coal, Oil &amp;amp; Gas&lt;/li&gt;
  &lt;li&gt;Financial Services&lt;/li&gt;
  &lt;li&gt;High Speed Trading&lt;/li&gt;
  &lt;li&gt;Investment Banking&lt;/li&gt;
  &lt;li&gt;Most Adult Entertainment&lt;/li&gt;
  &lt;li&gt;Casinos &amp;amp; Gambling&lt;/li&gt;
  &lt;li&gt;Most Health Insurance&lt;/li&gt;
  &lt;li&gt;Digital Rights Management&lt;/li&gt;
  &lt;li&gt;Religious Organizations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many others, the common denominator being that I do not believe these activities have a positive impact in our society.&lt;/p&gt;

&lt;h3 id=&quot;invitation&quot;&gt;Invitation&lt;/h3&gt;

&lt;p&gt;I make this list public as an invitation to you, software developer, to examine the &lt;strong&gt;social and ethical consequences&lt;/strong&gt; of our professional activity.&lt;/p&gt;

&lt;p&gt;It is undeniable that programmers have an increasing impact in our world through the software we write. If our only concern is doing our job right but we not mind about the consequences of what do, &lt;strong&gt;we risk becoming mercenaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At any point I suggest that my list is universal, different persons have different thresholds and sensibilities. It is nonetheless important that you ask yourself whether you are being consistent with your own values and principles, and perhaps, make your own list.&lt;/p&gt;

</description>
        <pubDate>Fri, 02 Jan 2015 00:00:00 -0600</pubDate>
        <link>https://blog.istepaniuk.com/i-will-never-work-for-you/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/i-will-never-work-for-you/</guid>
        
        <category>ethics</category>
        
        
      </item>
    
      <item>
        <title>Dear Recruiter</title>
        <description>&lt;p&gt;I am not actively looking for a new job at the moment. Nonetheless, &lt;strong&gt;thank you&lt;/strong&gt; very much for thinking about me for a position, or offering your help with my professional career.&lt;/p&gt;

&lt;p&gt;I am always open for new opportunities, and it is always good to keep an eye on our industry’s needs. I receive many requests or proposals like yours every week. Unfortunately, I could not possibly answer them all personally. That is why I have created this page on my site, I hope you do not mind.&lt;/p&gt;

&lt;p&gt;Even if I were actively searching for a new challenge, there are a couple of things I need to know &lt;strong&gt;upfront&lt;/strong&gt;, before actually considering it. Because this is &lt;strong&gt;non-negotiable&lt;/strong&gt;, I do not deal with external recruiters, headhunters or employment agencies of any sort. Understandably, they cannot provide this information. I am sorry if that is your case.&lt;/p&gt;

&lt;p&gt;The list may seem a bit extensive, but after all, these are basic things I would look for if I was applying for a position myself.&lt;/p&gt;

&lt;h4 id=&quot;basic-company-details&quot;&gt;Basic company details&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Mission, vision, purpose, market/customers.&lt;/li&gt;
  &lt;li&gt;The company founders, key people, who they are &amp;amp; what drives them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;is-there-a-dev-team-already&quot;&gt;Is there a dev team already?&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Who are the key team members&lt;/li&gt;
  &lt;li&gt;What have they done?&lt;/li&gt;
  &lt;li&gt;What are their team practices and values?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Furthermore, if you are an internal recruiter or HR person and can actually point or link to this essential information, note that there are a couple of industries and markets I rather not write software for, ever. See the list in &lt;a href=&quot;/i-will-never-work-for-you&quot; title=&quot;I will never work for you&quot;&gt;this post&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;thanks-for-understanding&quot;&gt;Thanks for understanding!&lt;/h1&gt;

&lt;h3 id=&quot;my-cv&quot;&gt;My CV&lt;/h3&gt;
&lt;p&gt;My &lt;a href=&quot;http://www.linkedin.com/in/istepaniuk&quot; title=&quot;Iván Stepaniuk LinkedIn profile&quot;&gt;LinkedIn profile&lt;/a&gt; is complete and updated. You can easily export a PDF from it if you need it.
There is also more information about me in &lt;a href=&quot;/about&quot;&gt;&lt;strong&gt;this page&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.linkedin.com/in/istepaniuk&quot; title=&quot;Iván Stepaniuk LinkedIn profile&quot;&gt;&lt;img alt=&quot;LinkedIn&quot; src=&quot;/img/icons/linkedin.png&quot; width=&quot;43&quot; height=&quot;43&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;contact-me&quot;&gt;Contact me&lt;/h4&gt;
&lt;p&gt;If you have further questions, you can mail me at istepaniuk@ Google’s well known free email service.&lt;/p&gt;

</description>
        <pubDate>Wed, 31 Dec 2014 00:00:00 -0600</pubDate>
        <link>https://blog.istepaniuk.com/dear-recruiter/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/dear-recruiter/</guid>
        
        <category>recruiter</category>
        
        <category>ethics</category>
        
        <category>hiring</category>
        
        
      </item>
    
      <item>
        <title>The Shapes of Bad Code, Part 1</title>
        <description>&lt;p&gt;I have noticed that when looking at some not-so-awesome piece of code for the first time, I can tell many things about it even before putting my glasses on, and while scrolling at a speed at which it is actually impossible to read anything at all.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h4 id=&quot;-oh-my-god-look-at-this-code&quot;&gt;– &lt;em&gt;“Oh my god, look at this code!”&lt;/em&gt;&lt;/h4&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;the-shape-of-bad-code&quot;&gt;The Shape of Bad Code&lt;/h3&gt;

&lt;p&gt;So what is that I see? The only thing you can see while scrolling that fast and squinting is shapes, the shapes formed by different blocks of text filling the screen, plus the colors of your syntax highlighting.&lt;/p&gt;

&lt;p&gt;So I decided to make some screenshots of my text editor to illustrate some of these bad code shapes, and I will write a post for two of these at a time. I also distorted the images to make sure we are not actually reading this code.&lt;/p&gt;

&lt;h4 id=&quot;code-duplication&quot;&gt;Code Duplication&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/img/shape-duplication.png&quot; alt=&quot;Code duplication&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is probably the best example so it goes first. This is JavaScript, but that is completely irrelevant in this case. This image shows two near-identical functions, both fit the screen and what’s going on is quite obvious. Sometimes a few scroll up &amp;amp; down movements are required to reveal a block of code that has been mercilessly copy-pasted, even more than once. I will not tell you why having duplicated code is bad, you probably learned that the first time you write a program with more than 30 lines.&lt;/p&gt;

&lt;p&gt;This duplication was probably introduced because it would have taken 120 more seconds to understand the original functionality and modify the existing code accordingly. Of course, it will now take 10 minutes to revert the damage, or even more if the different copies started to diverge.&lt;/p&gt;

&lt;h4 id=&quot;too-many-dependencies&quot;&gt;Too Many Dependencies&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/img/shape-imports.png&quot; alt=&quot;Too may dependencies&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is Python code, but the same shape is valid for any other language that requires you to declare the dependencies before using them, and that would be most of them.&lt;/p&gt;

&lt;p&gt;We do not know what is that this piece of code does, but there is something I can be sure of; There is practically no way that a this file/module/class is doing &lt;strong&gt;only one thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If it needs this all these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import&lt;/code&gt; statements, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;single responsibility principle&lt;/a&gt; is clearly not being observed. If the file/module had many smaller classes with different dependencies each, it’s also time to split this file into smaller ones, as almost every reason to observe SRP in classes and methods also applies for entities at the file (or module, package, assembly, etc.) level.&lt;/p&gt;

&lt;h4 id=&quot;more-ugly-code-shapes&quot;&gt;More ugly code shapes!&lt;/h4&gt;
&lt;p&gt;Check out &lt;a href=&quot;/the-shapes-of-bad-code-part-2/&quot;&gt;Part 2&lt;/a&gt;, and also &lt;a href=&quot;/the-shapes-of-bad-code-part-3/&quot;&gt;Part 3&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 29 Dec 2014 00:00:00 -0600</pubDate>
        <link>https://blog.istepaniuk.com/the-shapes-of-bad-code-part-1/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/the-shapes-of-bad-code-part-1/</guid>
        
        <category>quality</category>
        
        
      </item>
    
      <item>
        <title>Something Is Terribly Wrong with Wordpress</title>
        <description>&lt;h3 id=&quot;warning-this-is-just-a-rant-probably-you-should-not-read-it&quot;&gt;WARNING: This is just a rant, probably you should not read it.&lt;/h3&gt;

&lt;p&gt;This 2014 was a year of many changes, new company, new country, new house, all excellent excuses to stop writting posts! Lately, for these and other reasons I was not finding a lot of oportunities to write here. To make it even worse, every time I logged into my wordpress admin interface to write a draft or post, I remembered how hard Wordpress sucks. Really.&lt;/p&gt;

&lt;p&gt;Some years ago I decided to start blogging and went with Wordpress. It was the obvious choice, popular, and very easy to install and use. The problem is that what you get from &lt;strong&gt;Wordpress out of the box is not good enough&lt;/strong&gt;, at least if you are anywhere close to serious about it.&lt;/p&gt;

&lt;p&gt;As soon as you go online the spam will start pouring down. The built-in comment system can drive you crazy when you have 1 real comment for every 5000, but that’s easy, just spend half a day trying plugins until you find the one that does not cost you an eye and actually filters something.&lt;/p&gt;

&lt;p&gt;The same goes for social buttons, analytics, your twitter card, &lt;strike&gt;google authorship&lt;/strike&gt;,… &lt;strong&gt;Plugin magic!&lt;/strong&gt;. Do you want to add some code snippets to your posts? No problem, 3 or 4 plugins latter you will find something that does not completely destroy the theme or brings the whole server down.&lt;/p&gt;

&lt;p&gt;Wordpress releases updates quite often, but many of those installed plugins will start failing with even minor version upgrades, not only because they are hacky (some really are, even the popular ones) but because everything seems to be so tightly coupled to the Wordpress core that &lt;strong&gt;they shouldn’t be called plugins but grafts.&lt;/strong&gt; Good luck trying to keep all those updated. 17 in my case.&lt;/p&gt;

&lt;p&gt;All these hacks slow down your site, but don’t worry, there is a cache plugin to solve that! there is even a plugin to make Wordpress secure enough (WTF!) so your hosting provider does not shut you down when some script tries to brute-force your admin credentials, or when spammers bring your site to it’s knees.&lt;/p&gt;

&lt;h3 id=&quot;back-to-square-one&quot;&gt;Back to square one&lt;/h3&gt;

&lt;p&gt;With all those hacks, the site can respond reasonably fast for the public, but that doesn’t make the admin interface any faster, specially if you are on a cheap hosting provider. Bet your bottom dollar that any support ticket about Wordpress performance is going to contain “disable all the plugins” in the very first answer.&lt;/p&gt;

&lt;h3 id=&quot;questions&quot;&gt;Questions&lt;/h3&gt;

&lt;p&gt;Given that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I have &lt;strong&gt;less than 200KB&lt;/strong&gt; of written content.&lt;/li&gt;
  &lt;li&gt;I have less than 4MB of pictures.&lt;/li&gt;
  &lt;li&gt;The site gets an average of 100 daily sessions with only 1.2 views per sessions.&lt;/li&gt;
  &lt;li&gt;It has very, very ocasional traffic bursts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Why do I need all these plugins?&lt;/li&gt;
  &lt;li&gt;A cache plugin? Why isn’t it just fast enough for this?&lt;/li&gt;
  &lt;li&gt;A security plugin? Why isn’t it secure enough?&lt;/li&gt;
  &lt;li&gt;Why is that the built-in comment system is not practical, even for a small site?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Why do I need a full-fledged RDBMS to power a simple blog?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I just want to write some stuff, it shouldn’t be so damn complicated.&lt;/p&gt;

&lt;h3 id=&quot;the-solution&quot;&gt;The solution&lt;/h3&gt;
&lt;p&gt;If you are not a developer or sysadmin or you would rather spend your time blogging and not dealing with this nightmare, get somebody to manage your Wordpress for you, or get a paid &lt;a href=&quot;http://wordpress.com&quot;&gt;wordpress.com&lt;/a&gt; account, or a &lt;a href=&quot;http://ghost.org&quot;&gt;ghost.org&lt;/a&gt; one, etc. Running it yourself is an incredible waste of time.&lt;/p&gt;

&lt;p&gt;If you ARE a developer or sysadmin wanting to run a tech blog, &lt;strong&gt;there is a solution!&lt;/strong&gt; it’s called &lt;a href=&quot;http://www.jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; and I will tell about it very soon!&lt;/p&gt;
</description>
        <pubDate>Sun, 28 Dec 2014 00:00:00 -0600</pubDate>
        <link>https://blog.istepaniuk.com/something-is-terribly-wrong-with-wordpress/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/something-is-terribly-wrong-with-wordpress/</guid>
        
        <category>blog</category>
        
        <category>wordpress</category>
        
        
      </item>
    
      <item>
        <title>Linux Counter</title>
        <description>&lt;p&gt;I just remembered I have one of these, and look! &lt;del&gt;It still works!&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/linux-counter.png&quot; alt=&quot;https://linuxcounter.net/cert/325954.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Soon it’s going to be 15 years since I started using Linux, time flies.&lt;/p&gt;

&lt;h3 id=&quot;update&quot;&gt;UPDATE:&lt;/h3&gt;
&lt;p&gt;Well… that didn’t last much longer. The Linux Counter project was &lt;a href=&quot;https://web.archive.org/web/20181213155055/https://www.transmensch.de/linuxcounter-project-closed/&quot;&gt;shut down in 2018&lt;/a&gt;.
The last available estimate of Linux users was 91.9 million, as of August 2017.&lt;/p&gt;

</description>
        <pubDate>Sat, 15 Feb 2014 00:00:00 -0600</pubDate>
        <link>https://blog.istepaniuk.com/linux-counter/</link>
        <guid isPermaLink="true">https://blog.istepaniuk.com/linux-counter/</guid>
        
        <category>linux</category>
        
        
      </item>
    
  </channel>
</rss>
