<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.2">Jekyll</generator><link href="https://chocolatedrivendevelopment.com/feed/by_tag/quality.xml" rel="self" type="application/atom+xml" /><link href="https://chocolatedrivendevelopment.com/" rel="alternate" type="text/html" /><updated>2025-08-04T06:59:12+00:00</updated><id>https://chocolatedrivendevelopment.com/feed/by_tag/quality.xml</id><title type="html">Chocolate Driven Development</title><subtitle>The blog Chocolate Driven Development contains things to help in making your software creation better for the business, as well as for the developers.</subtitle><entry><title type="html">Dependency graphs as a design tool</title><link href="https://chocolatedrivendevelopment.com/2024/02/13/dependency-graphs/" rel="alternate" type="text/html" title="Dependency graphs as a design tool" /><published>2024-02-13T00:00:00+00:00</published><updated>2024-02-13T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2024/02/13/dependency-graphs</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2024/02/13/dependency-graphs/"><![CDATA[<p>In languages without automatic memory management,
you need to keep track of the references to memory you allocate.
One way to model that is a graph with no circular paths. 
It becomes a kind of ownership system for the code structures.
That will also show in what files you need to import for your code.
(You should be able to (manually) sort your files,
so that the imports in each file are only of files that come before it.)
That will then also be a guide of who gets to talk to whom.</p>

<p><a href="https://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a>, 
“don’t talk to strangers”, is also easier to remember, 
in a language that forces you to null-check a lot.
It is riskier to talk to your neighbours neighbours if they might have been deallocated.
Following the Law of Demeter aims at loosely coupled architecture,
and code that is easier to change.
Loosely coupled architecture can also be viewed as deliberately coupled architecture. 
To craft those relationship graphs we can reuse the methods for managing memory.</p>

<p>It is good that not all languages require you to allocate memory by hand.
The skills required to design a system that does not leak memory,
might have other usages though. 
Try that the next time you find yourself in a codebase where access to objects 
are expected to work from all over the place.
Code where changing one signature ripples through the entire system.</p>

<p>Questions to ask:</p>
<ul>
  <li>If one object had to both create and destroy this object, who would do that?</li>
  <li>What objects depend on this object existing?</li>
  <li>What objects does this object depend on, that others also need?</li>
</ul>

<p>Keeping a tidy object graph helps with memory management,
but also with separating concerns and easy to change code.</p>

<h3 id="bonus">BONUS:</h3>
<p>Interfaces can be used to avoid import loops in patterns like observer-observable.
And it also creates an abstraction layer for the design (if done properly).</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="quality" /><summary type="html"><![CDATA[How is Law of Demeter related to reference counting? It manages how parts of a software system is connected. Few languages today manage memory manually. But we can still use the same ways of thinking, to support a loosely coupled architecture.]]></summary></entry><entry><title type="html">TDD in the context of writing code to be read</title><link href="https://chocolatedrivendevelopment.com/2024/01/18/tdd-as-a-code-reading-tool/" rel="alternate" type="text/html" title="TDD in the context of writing code to be read" /><published>2024-01-18T00:00:00+00:00</published><updated>2024-01-18T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2024/01/18/tdd-as-a-code-reading-tool</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2024/01/18/tdd-as-a-code-reading-tool/"><![CDATA[<p>In their <a href="https://www.ai.lu.se/2023-12-20">work on code reviews</a> Lo Heander identifies two opposite forces.
We need <strong>understanding</strong>, seeing the code as a part of the system,
and that requires a lot of context.
But we also need <strong>clarity</strong>, 
being able to separate the part of the code that is under review,
and that is better done with less context.</p>

<p>Unit tests define the collaborators and the purpose of a piece of code.
When reading code with unit tests, we can read the tests first,
and focus on how the unit interacts with the system.
The review of the computational code, 
like the body of a function, can then focus on the implementation.</p>

<p>Putting this in the framework created by Heander,
we solve the conflict between clarity and understanding by separation of concerns.
Each test provides context for purpose and interaction for that unit.
At that time we are not interested in the implementation, just the interfaces, 
and can remove that part of the cognitive noise.
When we have enough understanding of the purpose of the code we can move 
to the implementation. 
That should then be a pretty small unit, with well defined collaborators, 
that we are already familiar with from the test.
We have the external context in place and can focus on implementation details.</p>

<p>Separating concerns like that lightens the cognitive load,
and might be a part of solving the conflict between clarity and understanding.</p>

<p>Test driving you code in small units,
does not only help with cognitive load in the moment,
but also helps everyone that will read that piece of code in the future.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="agile" /><category term="code" /><summary type="html"><![CDATA[Unit tests define the collaborators and the purpose of a piece of code. When reading code with unit tests, we can read the tests first, and focus on how the unit interacts with the system. Then reading the computational code is only about the implementation of that unit. Separating concerns like that lightens the cognitive load.]]></summary></entry><entry><title type="html">Wunderbaum testing</title><link href="https://chocolatedrivendevelopment.com/2023/11/23/wunderbaum/" rel="alternate" type="text/html" title="Wunderbaum testing" /><published>2023-11-23T00:00:00+00:00</published><updated>2024-02-16T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/11/23/wunderbaum</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/11/23/wunderbaum/"><![CDATA[<p>Good unit tests help you design code that is easy to use.
They do that by being a little tedious to write.
Remember, <a href="/2022/10/30/playground/">the test is where the code learns to play nice with others.</a></p>

<p>So if the code under test requires a lot of magic to be verified, 
it will not be straightforward to use in the codebase.</p>

<blockquote>
  <p>A rule of thumb is to favour testing frameworks that are so simple that 
you could easily just have written the code yourself. 
A testing framework is a convenience. 
It should not make it possible to test things that you could not test before.</p>
</blockquote>

<p>When you need to construct the test data, 
write your test doubles and create every other dependency needed, 
pure laziness will create code that is modular and easy for others to use.
This is the <em>design pressure</em> from the tests.</p>

<p><a href="/2022/11/04/upside-down/">If you let a framework entangle your code, unit testing gets hard really fast.</a>
A Wunderbaum testing framework will mock and stub your controllers and databases,
instead of helping you keep the domain logic separate and testable.
It removes the design pressure, one of the reasons to write tests first.</p>

<p>Sometimes you end up with a codebase that needs to get under test before it can be fixed.
Often that can be done through approval testing or end-to-end testing,
just to have some sense of safety.
In that process you might also find Wunderbaum testing frameworks helpful, 
since the code stinks so much you need all the perfume you can get.</p>

<p>But when the code just has some odour, try to avoid things that hide the smell.
If your code is hard to test with a slim testing framework,
you probably have code that is too interdependent, or not modular enough.</p>

<p>Keep your code nose fresh and think of design pressure as a friend.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><category term="agile" /><summary type="html"><![CDATA[Some testing frameworks are so powerful that they take away all the design pressure. They have a place in a codebase that stinks so much you can't work in it without some perfume. In all other cases they disturb your nose for well designed code.]]></summary></entry><entry><title type="html">The question trick</title><link href="https://chocolatedrivendevelopment.com/2023/11/16/question-trick/" rel="alternate" type="text/html" title="The question trick" /><published>2023-11-16T00:00:00+00:00</published><updated>2023-11-16T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/11/16/question-trick</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/11/16/question-trick/"><![CDATA[<p>When giving feedback on complex material and finding something unexpected,
there are almost always two alternative explanations.</p>

<p>The one to first come to mind is often <em>This is wrong!</em>.
The other one, easy to miss, is a parallel path of 
<em>I am missing important information</em>.</p>

<p>Before I know what the case is, 
I try to act as if the cat is both dead and alive at the same time.
Both options are true and false.
It keeps the door open for different scenarios, 
and have respect for the competence in the person receiving feedback.</p>

<p>Take a code review as an example, 
where I encounter some asynchronicity.
that looks like it would cause a race condition.</p>

<p>Lets look at the alternative conversations.</p>

<ol>
  <li><strong>I am correct and don’t ask questions</strong>
    <blockquote>
      <p>- <em>Race condition, fix it!</em>.</p>

      <p>- <em>Oh, thank you for spotting. I knew I had to fix it, but forgot.</em></p>
    </blockquote>
  </li>
  <li><strong>I am correct and phrase it as a question</strong>
    <blockquote>
      <p>- <em>This looks like something that could cause a race condition.
Or is there anything I am missing?</em></p>

      <p>- <em>Oh, thank you for spotting. I knew I had to fix it, but forgot.</em></p>
    </blockquote>
  </li>
  <li><strong>I am wrong and don’t ask questions</strong>
    <blockquote>
      <p>- <em>Race condition, fix it!</em>.</p>

      <p>- <em>This part of the data is immutable now.
You must have worked with the other team the week we changed that.
Good I got to tell you!</em></p>
    </blockquote>
  </li>
  <li><strong>I am wrong and phrase it as a question</strong>
    <blockquote>
      <p>- <em>This looks like something that could cause a race condition. 
 Or is there anything I am missing?</em></p>

      <p>- <em>This part of the data is immutable now.
You must have worked with the other team the week we changed that.
Good I got to tell you!</em></p>
    </blockquote>
  </li>
</ol>

<p>The tone shifts a lot depending on how the first sentence is phrased.
And the difference is clearest when the reviewer is wrong.</p>

<p>There is a risk of not sounding sincere in the question, 
then it won’t work. 
People who are underestimated might seem ignorant rather than humble.
That has to be taken into account.</p>

<p>The next time you give feedback, 
phrase it so that the conversation can flow also when you are wrong.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="empathy" /><category term="quality" /><category term="code" /><summary type="html"><![CDATA[Use questions when delivering constructive criticism on something complex. Questions leave room for the possibility that you are wrong.]]></summary></entry><entry><title type="html">The dynamite double</title><link href="https://chocolatedrivendevelopment.com/2023/09/27/dynamite-double/" rel="alternate" type="text/html" title="The dynamite double" /><published>2023-09-27T00:00:00+00:00</published><updated>2023-09-27T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/09/27/dynamite-double</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/09/27/dynamite-double/"><![CDATA[<p>Side effects should be isolated, kept in code that is separate from domain 
logic, and have no conditionals in them. 
They are the adapters in the “ports and adapters”-pattern.</p>

<p>To test code interacting with the ports, we need test doubles to use as the adapters.</p>

<p>As an example we have pseudo code for a system that sometimes start a siren.
The code actually starting the siren is wrapped in a simple class 
implementing the port-protocol <code class="language-plaintext highlighter-rouge">Siren</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>protocol Siren {
    void turnOn()
}
</code></pre></div></div>
<p>The code starting the siren gets it as a parameter,
together with the boolean <code class="language-plaintext highlighter-rouge">emergency</code>.</p>

<p>I really don’t want the siren to go off when there is not 
an emergency.</p>

<p>So to make sure that the function does not even try to start the siren,
we use a Dynamite Double. 
It is a test double that fails the test if the code tries to call its functions.
Touch it and it explodes.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class DynamiteDoubleSiren implements Siren {

    void turnOn(){
        make.test.fail.horribly
    }
}
</code></pre></div></div>

<p>Instead of using a test double that records if,
and how, it has been called,
I feel safer if the “no action”-alternative is tested with 
a dynamite double.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><summary type="html"><![CDATA[When you want your test to make sure that the code does not even try to call a collaborator with side effects, use a dynamite double, that explodes when touched.]]></summary></entry><entry><title type="html">Defining domain boundaries</title><link href="https://chocolatedrivendevelopment.com/2023/09/25/definition/" rel="alternate" type="text/html" title="Defining domain boundaries" /><published>2023-09-25T00:00:00+00:00</published><updated>2023-09-25T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/09/25/definition</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/09/25/definition/"><![CDATA[<p>In mathematics the <em>domain</em> is the input values 
that a function can map to the <em>codomain</em> of output values.
Both the <em>domain</em> and the <em>codomain</em> are part of the functions definition.</p>

<p>Software development is not always as strict, but the mathematical mindset can 
help us in writing predictable code.</p>

<p>In Test Driven Development (TDD) we let the tests and the code grow together, 
creating one failing test at the time and making it pass.</p>

<p>Deliberately deciding what input values are valid for a function is a part of TDD.
We then also define the behaviour if the function can be used outside of its definition.
(In some languages this is done through the definition of signatures and types.)</p>

<p>TDD is a thinking tool more than a way to write test.</p>

<p>Let it help you define your domain and its boundaries.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="quality" /><summary type="html"><![CDATA[In mathematics the definition of a function contains the set of valid input values, the domain. Test Driven Development can help us adapt that mindset and implement the boundaries of our domain in code.]]></summary></entry><entry><title type="html">IT-stress, part 2 — change</title><link href="https://chocolatedrivendevelopment.com/2023/08/22/stress-2/" rel="alternate" type="text/html" title="IT-stress, part 2 — change" /><published>2023-08-22T00:00:00+00:00</published><updated>2024-02-16T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/08/22/stress-2</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/08/22/stress-2/"><![CDATA[<p>Software that is unreliable or hard to use causes stress in the work place. 
It also lowers productivity.</p>

<p><a href="/2023/08/21/stress-1/">The previous post is on coping with IT-stress</a>
This is about preventing it.</p>

<h3 id="software-can-change">Software can change</h3>
<p>Software is named in contrast to hardware.
Computer programs should be easy to change.
You can get an update into production in less then an hour, with modern methods.
( Refer to <a href="/references/accelerate.html">Accelerate</a> 
if you encounter someone who says otherwise.)
If the software is not working, for the ones using it, the software should be changed.</p>

<h3 id="be-a-part-of-the-process">Be a part of the process</h3>
<p>Half of corporate budgets for software (in Sweden) is used for customisation. 
Either for modifications of existing software by external parties
or external developers working on in-house projects.
On top of that, about 40% of IT-workers in Sweden work for companies that produce something else than software.</p>

<p>That is a lot of software being written with a specific customer in mind.
If you are that customer, demand to be a part of the entire process.
Software tailored to your needs requires your input,
just as a suit or dress is made with multiple fittings.</p>

<p>“Off the shelf”-software has to be tried by the end users before committed to.
The cognitive ergonomics when investing in software should be considered similar
to ergonomics when furnishing a workshop or office.</p>

<p>If the software is a part of your “competitive edge”, consider having a dedicated 
team of software developers, who get to know you and your domain really well.
Provide them with direct access to the end user
and put them close to (or in) the product team.</p>

<blockquote>
  <p>The software team should be like a painters brush, 
swift in the hands of product development.</p>
</blockquote>

<p>If your software team can not deliver on that, provide them with training and other support until they do.
Your organisation deserves it.</p>

<h3 id="put-the-user-in-the-center">Put the user in the center</h3>
<p>The purpose of software is to make things better.
It is a failure if the end user can not easily use the product.
We can check that we are building the right thing as we go,
if we have the end user close and work in small steps.
In Extreme Programing, a flavour of agile, the customer is represented in the team.
If that does not work, find another way to get constant and real feedback.
This avoids delivering something that is “done”, but can not be used.</p>

<h3 id="expect-more-of-software">Expect more of software</h3>
<p>Whenever you can, demand more of software you encounter.
<a href="/references/accelerate.html">Accelerate</a> 
is a good book on what can be expected of an organisation delivering software.
<a href="/references/devops-2021.html">The DevOps report 2021</a>
and
<a href="/references/devops-2019.html">The DevOps report 2019</a> 
are shorter reports covering the findings from the research.
Remember that soft in software is soft as in changeable.
If you are in charge of spending money on software, off-the-shelf or in developer hours,
take your responsibility.
Software development is best done with the end user in focus and in small steps.
Don’t accept less.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="product" /><category term="agile" /><summary type="html"><![CDATA[IT-stress has gotten into the top list of problems in the workplace. This is a text about changing that.]]></summary></entry><entry><title type="html">The value of quality</title><link href="https://chocolatedrivendevelopment.com/2023/08/03/the-value-of-quality/" rel="alternate" type="text/html" title="The value of quality" /><published>2023-08-03T00:00:00+00:00</published><updated>2023-08-03T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/08/03/the-value-of-quality</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/08/03/the-value-of-quality/"><![CDATA[<p>This text is a reaction to this micro blog post:</p>

<blockquote>
  <p>early-career people should take the time to download and look at the leaked farcry code.
not to learn some new technical lessons,
but to disabuse themselves of the notion of “clean code”. 
<a href="https://twitter.com/nice_byte/status/1675621641131556864?s=61&amp;t=Mchgzl3goM1KCJAvA_p9oQ">nicebyte</a></p>
</blockquote>

<p>From reading more of the thread, my interpretation is:
“You don’t need good programming practises to make money from software.”
That might be true, in some circumstances, but to make it an “early-career”-advice I would like to add some
perspective.</p>

<p>First I want to separate internal and external software quality,
<a href="/2023/08/01/external-internal-quality/">as described in this post</a>.
Internal quality is from a developer perspective,
external quality is what the user sees.
They can be more or less dependent of each other, but have different effects.</p>

<p>J.B. Rainsberger has a talk on “The economics of software design” (<a href="https://youtu.be/TQ9rng6YFeY?t=735">video</a>).
There he introduces t0, the point in time where the total cost of having written the code is the same
regardless of if we just did it fast and sloppy or slower and intentionally sustainable.
We don’t know when t0 will be, but it exists for every project.
After t0 you reap the profit from having continuously improved the code since the start.
In just implementing features as fast as possible,
we bet against the project surviving past t0.
We only save money by not caring about “clean code” if the project does not reach t0.
The t0 measure is about the value of internal quality.</p>

<p>It is interesting to use a game as an example for when internal quality is unnecessary.
Games are one of the few kinds of software still distributed on physical media.
I believe that a lot of games change less over time then other software.
The cost of a messy codebase come when we want to edit it.
Bugfixes in a feature complete codebase can be plastered on,
as long as the code do not move.</p>

<p>In my <a href="/2023/07/27/useworthiness/">post on useworthiness</a>
I talk about how utility and usability mix to decide if software is worth using. 
If we can not add new features utility will suffer. 
Usability will be a problem if the internal quality problems show as 
external quality problems, or slow down improvements in user experience over all.</p>

<p>For games that change more over time, like Pokémon Go,
the condition of the codebase matters, and will start to show.
<a href="https://www.eurogamer.net/pokemon-go-developer-commits-to-improving-games-quality-after-recent-remote-raid-shiny-snafu?fbclid=IwAR26nV1LOSzsa7lygePIacsFofsfagyYKJlCEUHHfFf4fbTrSB2uPHjq57A"> Niantic has publicly stated that they have quality problems</a>.
In Pokémon Go the problems shows as defects, delayed features and draining of the users resources such as mobile data and battery.
All of that results in lower external quality.</p>

<p>The gamble here is both with t0, “will the project die before the codebase does?”, 
and with the users tolerance for unreliability, in relationship to how the game makes money.</p>

<p>Pokemon Go makes <a href="https://mobilegamer.biz/mays-top-grossing-mobile-games-worldwide/">money</a>, 
but Niantic has still recently <a href="https://variety.com/2023/digital/news/niantic-layoffs-pokemon-go-shutting-down-games-1235658759/">laid off 25% of its workforce</a>.</p>

<p>This is why my “early-career” advice is:</p>
<blockquote>
  <p>Find work where they care about code quality.</p>
</blockquote>

<p>It will be better for your mental health as well, but that is for another post.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><category term="product" /><summary type="html"><![CDATA[Is "clean code" important for successful software development? It depends on the life expectancy of the software, if it needs to follow changes in the business and how well the user reacts to defects.]]></summary></entry><entry><title type="html">Internal or external quality?</title><link href="https://chocolatedrivendevelopment.com/2023/08/01/external-internal-quality/" rel="alternate" type="text/html" title="Internal or external quality?" /><published>2023-08-01T00:00:00+00:00</published><updated>2023-08-01T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/08/01/external-internal-quality</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/08/01/external-internal-quality/"><![CDATA[<p>When talking about software quality we should separate internal and external
quality.
What is the user experience and what is the developer experience?</p>

<p>Internal quality is a codebase where the functionality is easy to change without
unexpected side effects.</p>

<p>External quality is software that behave as expected by the user, 
demanding as little effort as possible.</p>

<p>Sometimes the two are related.
Code forced into new purposes without prior refactoring might behave clunky or erratic.</p>

<p>A lack in internal quality can still be prevented from showing to the user. 
This is where we do endless manual testing, extensive monitoring in operations or add
a lot of extra computational resources.</p>

<p>On the other hand, software with high internal quality might still have poor external quality.
If the behaviour of the application is hard for the user to navigate and predict,
it will still not be perceived as working correctly.</p>

<p>If the software has internal quality it is easier to change.
This makes it easier to do user research and update its behaviour,
so that it works well for the user.</p>

<p>Internal quality makes it easy to write software that do what we expect.
External quality is software that does what the end users expect.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="agile" /><category term="code" /><summary type="html"><![CDATA[When talking about software quality we should separate internal and external quality. Internal quality makes it easy to write software that do what we expect. External quality is software that does what the end users expect.]]></summary></entry><entry><title type="html">Useworthiness</title><link href="https://chocolatedrivendevelopment.com/2023/07/27/useworthiness/" rel="alternate" type="text/html" title="Useworthiness" /><published>2023-07-27T00:00:00+00:00</published><updated>2023-07-27T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2023/07/27/useworthiness</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2023/07/27/useworthiness/"><![CDATA[<p>A product that only improves my life marginally has to be really good 
for me to keep using it.</p>

<p>On the other hand, a badly designed, or even unstable, product that provides
something really valuable, will be used anyway.
(That is, until something better is available, or the pain grows too big.)</p>

<p>Useworthiness is the combination of usability and utility.
How well it works is weighted with how valuable the function is.
Both impact how the user interacts with your product.</p>

<p>Compare it with food.
That something is easy to eat and that it is tasty is two
different things. 
Eating canned corn with a spoon is really easy.
Despite that, I prefer to eat it fresh on the cob, 
including the flossing required afterwards.</p>

<p>If you work with software that provides something really useful,
people might be using it <em>despite</em> its level of quality.</p>

<p>If it is something that the user has to do,
participation data is even less valuable to decide the quality of your product.</p>

<p>Get feedback from you user, besides recorded data,
to separate the usability from the utility and retain customers over time.</p>

<p>If you take pride in producing quality user experience and product stability,
make sure you work with something valuable to people, so that it is not wasted.</p>

<p>User research is the best way to get useworthy products.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="product" /><category term="quality" /><category term="code" /><summary type="html"><![CDATA[Useworthiness is the combination of usability and utility. How well it works is weighted with how valuable the function is. Both impact how the user interacts with software.]]></summary></entry><entry><title type="html">Test it like it’s pure</title><link href="https://chocolatedrivendevelopment.com/2022/11/30/pure/" rel="alternate" type="text/html" title="Test it like it’s pure" /><published>2022-11-30T00:00:00+00:00</published><updated>2022-11-30T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2022/11/30/pure</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2022/11/30/pure/"><![CDATA[<p>A pure function:</p>

<blockquote>
  <ol>
    <li>has no side effects.</li>
    <li>always produces the same output for a given input.</li>
  </ol>
</blockquote>

<p>Pure functions are known to be easy to test.
We can use their characteristics to make all code easier to test.</p>

<h3 id="dont-mix-logic-and-side-effects-in-the-same-method">Don’t mix logic and side effects in the same method</h3>
<p>Even if you don’t write functional code, this is good practise. 
When separated from the rest you can test the logic to your hearts content, 
and create a single integration test for the side effects.
We need side effects, but keep them isolated and in methods without conditionals.</p>

<h3 id="inject-your-dependencies">Inject your dependencies</h3>
<p>If everything that might vary is part of the input,
the output can be deterministic.
In contrast, letting the method have access to collaborators and state
“behind the scenes”, creates variance that is independent of the input.
That will make for more setup in the tests, and more combinations to cover.</p>

<p>Pure functions remove some of the hardest part from testing, 
you can use that knowledge in all software development.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="quality" /><summary type="html"><![CDATA[It is not always possible to write pure functions. Still, the properties of pure functions can help us write testable code.]]></summary></entry><entry><title type="html">The upside-down framework anti-pattern</title><link href="https://chocolatedrivendevelopment.com/2022/11/04/upside-down/" rel="alternate" type="text/html" title="The upside-down framework anti-pattern" /><published>2022-11-04T00:00:00+00:00</published><updated>2022-11-04T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2022/11/04/upside-down</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2022/11/04/upside-down/"><![CDATA[<p>In the tv-series <a href="https://en.wikipedia.org/wiki/Stranger_Things">Stranger things</a> there are tentacles, or maybe vines,
spreading through the underworld called “the upside-down”. 
It’s a scary place of darkness,
and the thick dark cords infiltrate and consume.
The clinging and squirming things are also connected to each other.
Step on one and all the others will know.</p>

<p>There is code like this, frameworks that infiltrate the domain code until they are inseparable. 
Change one part and it affects all of it. You are never safe to move. 
Bad habits of the team that designed the framework will seep into the code base. 
(Regardless if the framework is external or developed alongside the domain logic.) 
Getting free takes time. 
Approval tests and safe refactoring are the flamethrowers that can save us.</p>

<p>To avoid this anti-pattern, keep your frameworks at arms length. 
Isolate code that is framework specific from your domain logic. 
Use interfaces!
<a href="https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)">Hexagonal design (ports and adapters)</a> 
can be used for this.</p>

<p>A bonus is that the code will be testable. 
Frameworks are good at side effects. 
Let them deal with that.
The domain code is then easy to put in unit tests.</p>

<p>If the framework is not working for you, or is updated, 
make sure the interface is preserved and the change is mostly done. 
It won’t even make your nose bleed.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="quality" /><category term="devops" /><summary type="html"><![CDATA[Don't let frameworks interlace with the domain code. Keep them separate and working with the codebase won't require super powers.]]></summary></entry><entry><title type="html">A playground for code</title><link href="https://chocolatedrivendevelopment.com/2022/10/30/playground/" rel="alternate" type="text/html" title="A playground for code" /><published>2022-10-30T00:00:00+00:00</published><updated>2022-10-30T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2022/10/30/playground</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2022/10/30/playground/"><![CDATA[<p>I see unit tests as the playground where code learns to behave.</p>

<p>We want reusable code.
Being easily unit testable is proof that the code can work in two contexts.
As soon as you use the unit outside the test, 
you are already reusing it.</p>

<p>Design pressure from driving development with tests
is like the training kids get from play. 
We teach the code how to interact with others, 
experiment with interfaces, boundaries and naming.</p>

<p>When we have code that works well in a unit test 
(<a href="/2021/12/16/dangerous-skills/">and no, if you need a fancy testing framework the code is not behaving well enough</a> )
we can let it play with the rest of the production code.</p>

<p>If it is a pain to test, it will be a pain to use, maintain and debug. 
So play with the code a bit first, it will be worth it.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="quality" /><summary type="html"><![CDATA[Unit tests are the playground where code learns to behave. If the code is both easy to test and easy to use, it has shown to be reusable.]]></summary></entry><entry><title type="html">Let code grow old in peace</title><link href="https://chocolatedrivendevelopment.com/2022/10/29/grow-old-in-peace/" rel="alternate" type="text/html" title="Let code grow old in peace" /><published>2022-10-29T00:00:00+00:00</published><updated>2022-10-29T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2022/10/29/grow-old-in-peace</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2022/10/29/grow-old-in-peace/"><![CDATA[<p><a href="/2022/10/04/single-responsibility-salt/">Single responsibility principle</a>,
<a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle">open-closed principle</a> and
<a href="https://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a> are all design principles that allow code to grow old in peace.</p>

<p>Code that has a limited responsibility, with only one stakeholder. 
Objects and functions that can be part of composition, without being altered. 
Interactions designed to work even if the implementation details of one actor changes. 
They will all likely result in code that has not been touched or altered for a very long time. 
The code is still in use, but as “done” as code ever gets.</p>

<p>It is a blessing when code is allowed to grow stale. 
We should design our code so that it can slowly sediment, 
harden by itself, 
in the peace good design and proper testing creates.
The codebase as a whole will still evolve, and that is going fast. 
Changes to support the business are quickly done in small units with good interfaces. 
Sometimes a bigger part is swapped out. 
In other cases, an old trustworthy part is promoted into a library. 
There is movement where it is needed, but the ripple effects don’t reach far.</p>

<p>When I hear about code freeze or software hardening as part of a delivery pipeline, 
I think about the aging and maturing of code. 
With small units of decoupled and well tested code, it will naturally harden. 
Some files will be created, 
used for days or decades, 
and then deleted, 
without ever being changed.
Others will have an eventful youth, 
but soon settle into being run, but not altered. 
For me, that is the goal, letting the legacy of code create a solid foundation for new work.</p>

<p>What do you have to change to let your code age in peace?</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="devops" /><category term="quality" /><summary type="html"><![CDATA[Design the code so that as little as possible needs to change when the world changes.]]></summary></entry><entry><title type="html">Anti-work polluters</title><link href="https://chocolatedrivendevelopment.com/2022/10/28/anti-work-polluters/" rel="alternate" type="text/html" title="Anti-work polluters" /><published>2022-10-28T00:00:00+00:00</published><updated>2022-10-28T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2022/10/28/anti-work-polluters</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2022/10/28/anti-work-polluters/"><![CDATA[<p>Anti-work, the unplanned work, that eliminates planned work, as it uninvited enters your day.
It is everything from fire fighting to bug fixes and cleaning up afterwards. 
Your intentions for progress goes up in proverbial smoke.</p>

<p>Not only will anti-work make life harder inside the organisation, 
it also leaks into the surrounding world. 
Anti-work pollution!</p>

<p>There is a lot of literature on the topic targeting the IT-industry.
<a href="/references/phoenix.html">The Phoenix Project</a> both describes where it comes from, 
and parts of what we can do about it. 
Preventing anti-work is also something a Technical Coach helps with.</p>

<p>We want to minimise anti-work to be more profitable and a better work place. 
We should also pay attention to what our anti-work does to people outside the company.
An organisation that fails to prevent anti-work for its employee,
will also cause anti-work for its customer.</p>

<p>It might not be that the entire system is down. 
It is enough that there is some kind of unavailability or error,
that will ask more of the customer than they planned for. 
Restarting apps or devices.
Forms that clear all entries on a single error.
Data that don’t sync properly.
Having to wait or reschedule your task for another time.
And it is not only software that manifests it,
though it is often software involved.
(Or better software could have prevented it.)</p>

<p>Ordered food that only partly show up might not seem like a biggie, 
but it might also cause the anti-work that blows up something really 
important for that individual at that time.</p>

<p>When the anti-work hits your life, instead of your work,
we often lack protective systems. 
The nuclear-family team of two, or one, doesn’t have the redundancy of an IT-department.
If the service you build is of any use, or importance at all, 
it hurts when it fails the user. 
It might only be a paper cut,
but could be one of thousands in total. 
It will probably hit harder for people with less privilege to start with. 
As a system, a society, we should all be more careful with each others time and energy.</p>

<p>Don’t be an anti-work polluter! Take care to build quality software!</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="product" /><category term="equity" /><summary type="html"><![CDATA[Anti-work in an organization will spread to its customers. No defect is too small to lower the quality of life for people a bit, and combined it is an unnecessary burden for the often already disadvantaged.]]></summary></entry><entry><title type="html">Single responsibility and salty porridge</title><link href="https://chocolatedrivendevelopment.com/2022/10/04/single-responsibility-salt/" rel="alternate" type="text/html" title="Single responsibility and salty porridge" /><published>2022-10-04T00:00:00+00:00</published><updated>2022-10-04T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2022/10/04/single-responsibility-salt</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2022/10/04/single-responsibility-salt/"><![CDATA[<p>Single responsibility principle is the S in <a href="https://en.wikipedia.org/wiki/SOLID">SOLID</a>.</p>

<p>There is a proverb present in many languages.</p>

<blockquote>
  <p>Many chefs spoil the soup.</p>
</blockquote>

<p>In German there is a version:</p>

<blockquote>
  <p>Many chefs spoil the porridge, 
by adding too much salt.</p>
</blockquote>

<p>(It sounds much better in German.)</p>

<p>I like the German version since it is specific on how the porridge is ruined. 
Each chef has their own plan, adding their own salt,
and the porridge can’t take it. 
That is what happens with code as well. 
The single responsibility principle is about that.</p>

<p>Code should have only one responsibility, 
so that there is only one chef who might put salt in it.
If a piece of code has more than one stakeholder, chef,
too much stuff, salt, will be added to the code.</p>

<p>So what is a chef/stakeholder in this case?</p>

<p>Stakeholders are people, or organisations,
who want to change how the code works.</p>

<p>It can be an external API that is used, and then changes. 
Governments can change a law that effects your code.
Marketing might be a stakeholder.
A specific target audience for the product might add extra salt.</p>

<p>By separating all those interests, 
preferable using interfaces, 
we can make sure that each chef only puts salt in their own pot of porridge.</p>

<p>ps. Developers sharing responsibility for code is a good thing.
We are not stakeholders in this example, as long as we work as a team.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="learning hour" /><category term="code" /><category term="quality" /><summary type="html"><![CDATA[What does too many stakeholders do to a piece of code?]]></summary></entry><entry><title type="html">Refactor or rewrite?</title><link href="https://chocolatedrivendevelopment.com/2022/05/11/refactor-or-rewrite/" rel="alternate" type="text/html" title="Refactor or rewrite?" /><published>2022-05-11T00:00:00+00:00</published><updated>2022-05-11T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2022/05/11/refactor-or-rewrite</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2022/05/11/refactor-or-rewrite/"><![CDATA[<p>I’ve just migrated this website and feel the need to write about why I don’t like big rewrites.
I moved my blog since the platform I used has flaws I could not live with, and had no power to change.
So I had to move. But otherwise I am “team refactor”. Here I explain why.</p>

<h2 id="specification-missing">Specification missing</h2>
<p>It is very rare that a system has a complete documentation of its feature set. 
When doing a rewrite you still have to figure out what to implement. 
Often that is a big part of the job. That also makes it really hard to estimate the size of the rewrite.</p>

<h2 id="information-in-the-code">Information in the code</h2>
<p>Legacy code contains a lot of information. 
If you don’t know the code well, it is hard to know if it is domain complexity or accidental complexity.
If it is domain complexity, the new system will be as hard to understand, but in a new, unfamiliar way.</p>

<h2 id="stable-and-making-money">Stable and making money</h2>
<p>New code has a tendency to be more flaky than old code. Not true everywhere. 
But those of you who hit this site, while I figured out this or that, knows how my 404-page looks.
I have also not written any blogs in like forever, while working on the website.
An old codebase can be terrible to work in, but it is often running in production and creating value.</p>

<h2 id="sustainable">Sustainable</h2>
<p>When the code is something you own, its condition is in your hands. 
If hard to change code is always thrown out, we miss a chance to learn.
And it is wasteful. Imagine moving house instead of spring cleaning. 
The skills we need for refactoring will make our software better in a way no rewrite ever will.</p>

<p>So learn how to take care of your code. Mend it and refactor it.
Use patterns that will make it possible to replace parts when they get outdated,
without tearing out all the domain code.
The grass is not always greener in green field development.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><summary type="html"><![CDATA[Learning to refactor instead of rewriting preserves the domain knowledge build into the old codebase while it can keep making money. The skill of continuous improvement is important for developers, and might be neglected in a "rewrite" culture.]]></summary></entry><entry><title type="html">Dangerous skills</title><link href="https://chocolatedrivendevelopment.com/2021/12/16/dangerous-skills/" rel="alternate" type="text/html" title="Dangerous skills" /><published>2021-12-16T00:00:00+00:00</published><updated>2021-12-16T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2021/12/16/dangerous-skills</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2021/12/16/dangerous-skills/"><![CDATA[<p>Being good at managing stress could be dangerous.
Being good at preventing long term stress should be our aim.</p>

<p>The same way,
testing the untestable looks good on your resume.
Used careless, it is also a way to allow sloppy software design.
The goal is code that is easy to test.
Because code that is easy to test is easier to work with, long term.
A powerful tool for testing can become a liability.
Awesome testing skills become a danger,
if it leads to code that had no design pressure.</p>

<p>We need skills for the life we have, including its stress and hard to test code.
But don’t confuse necessity with virtue.
To build the world we want to have, we have to hone skills for such a world.
It can be removing the cause of stress or getting better at software architecture.
It will make our old skills a bit less valuable.
Allow yourself to grieve that.
it will also require us to do things we are not that good at yet.
It is ok to find that scary.
Just don’t let today’s skills dictate tomorrow’s reality.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><summary type="html"><![CDATA[Being good at things nobody should ever have to do is a tricky thing. This is a text about wishing for a better world, also when you don't yet have the skills needed to perform well in that world.]]></summary></entry><entry><title type="html">A language agnostic debugging list</title><link href="https://chocolatedrivendevelopment.com/2021/06/09/a-language-agnostic-debugging-list/" rel="alternate" type="text/html" title="A language agnostic debugging list" /><published>2021-06-09T00:00:00+00:00</published><updated>2024-02-16T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2021/06/09/a-language-agnostic-debugging-list</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2021/06/09/a-language-agnostic-debugging-list/"><![CDATA[<p>Checklists are nice cognitive tools.
This one can also work as a reminder when designing code.
Please come with feedback and suggestions for improvement.</p>

<p>It is not always the case that we immediately spot the reason for an error in a codebase.
Sometimes it is hard to find due to the design.
In other cases the definition of correct behaviour is the problem.
It might also be a lack in understanding when it comes to the technology used.
This checklist is useful regardless of your knowledge of the language you are debugging.
Depending on domain knowledge, technical knowledge and the state of the code base,
how long the steps take and what information they give, will vary.
This is, as most knowledge work,
best done together with someone else,
or with an entire team.</p>

<h2 id="a-test">A test</h2>

<p>Write a test,
of some kind,
that captures the unintended behaviour.
In worst case it is a description of steps to take
written on a piece of paper.
Best case is a unit test.
This will define where we see the problem,
with its setup and the state it leaves the program in.</p>

<h2 id="specifications">Specifications</h2>

<p>Do we know for sure that this is a problem,
not just a state where the behaviour is not clearly defined?
Make sure that we know what the code is supposed to do
in this particular case.</p>

<h2 id="location">Location</h2>

<p>Are we sure that this is where the problem is caused? Check that the in-data is correct,
and that the data out is not as expected.
Try to narrow it down,
define as little code as possible where the error might be.</p>

<h2 id="regression">Regression</h2>

<p>Has it ever worked?
If it has, what has changed since then?
Version control is your friend here.</p>

<h2 id="static-analysis">Static analysis</h2>

<p>Is the IDE saying anything?
A real development environment uses parts of the same algorithms
as the compiler/transpiler/interpreter,
to be able to give hints and syntax highlighting.
There is also often static code analysis tools
that can highlight practises that make the code fragile.
Use tools.</p>

<h2 id="surrounding-state">Surrounding state</h2>

<p>Are there inputs, not stated as such, in the code we are looking at?
Some code use state that is external in some way.
One way to check this is by trying to write a unit test,
instead of an integration test.
What do we need in our setup to make it work?
The state could be a global variable used by a collaborator,
today’s date, or some settings in the system.
Make sure that we know all the <em>actual</em> input data to the code we are investigating.
Try to make the implicit input explicit when testing the code.</p>

<h2 id="comparing">Comparing</h2>

<p>If there is comparing going on,
is it done correctly (for that language)?</p>

<h2 id="things-missing">Things missing</h2>

<p>Do we know what could be null/nil/empty?
Keeping null-checks at the boundaries of code makes this easier.
Use the tools the language provide to deal with missing data.</p>

<h2 id="data-structures">Data structures</h2>

<p>Are data-structures used as intended?
If iteration happens,
are the boundaries the right one?
Do the data-structures have any quirks in this framework?</p>

<h2 id="language-specifics">Language specifics</h2>

<p>Are there other language features that could be a problem? In Python,
default arguments can turn into singletons.
In ObjectiveC a method call on a deallocated object will return 0,
or nil, but succeed.
Try to rewrite the code, even if it turns it bulkier,
just to see if misdirected “cleverness” might be the problem.
Then read the documentation to understand what happens if the behaviour changes.</p>

<h2 id="flow">Flow</h2>

<p>Is the flow of execution as we think it is?
Use a debugger to step through the calls, following the control flow.
Test cases can also be run in debug-mode.
Make sure that there are no code skipped.
One example is if code is executed as part of a condition,
that is already evaluated as true, and therefore skipped.</p>

<h2 id="threads">Threads</h2>

<p>Are we working with asynchronous code?
If we are, then make sure that it is done correctly.
Test ways to make sure that all of the suspect code is run synchronous,
to eliminate logic errors that are not timing related
, even if the code can never run like that in production.</p>

<h2 id="identity">Identity</h2>

<p>Is everything what we think it is?
Is the runtime scope clear?
Do we have inheritance, this/self references,
variables or functions that might shadow each other,
or other things that might not be what we assume that they are?
Do we reuse variable names or references?
Might there be things where ownership is unclear and it is garbage collected?
Use a debugger, or print statements, to check that things are what we expect.
(<a href="https://www.youtube.com/watch?v=IyYnnUcgeMc">Playing Destiny’s Child while doing this is optional</a>,
but it is a good reminder that scope in JavaScript is tricky.)</p>

<h2 id="self-care">Self care</h2>

<p>Take a break, if you have not already.
At this point I might start searching the internet,
or try writing a question at Stack Overflow.
(Often the solution is in writing the post, not posting it.)
I might also call a friend.
My experience is that the harder the answer is to find,
on the internet,
the more likely it is that the mistake made is really basic.</p>

<p>Hope this list helps.
I will use it the next time I get stuck on code not working as I intended.</p>

<p>How do you find your mistakes?
Do you have anything to add?
Have I missed anything language specific that is not included in the steps above?</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><category term="list" /><summary type="html"><![CDATA[A cognitive tool in shape of a list of things that often go wrong when writing code. Nice to have when you get stuck.]]></summary></entry><entry><title type="html">TDD cheats, tricks to dodge the hard parts of testing</title><link href="https://chocolatedrivendevelopment.com/2021/04/16/tdd-cheats-tricks-to-dodge-the-hard-parts-of-testing/" rel="alternate" type="text/html" title="TDD cheats, tricks to dodge the hard parts of testing" /><published>2021-04-16T00:00:00+00:00</published><updated>2021-04-16T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2021/04/16/tdd-cheats-tricks-to-dodge-the-hard-parts-of-testing</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2021/04/16/tdd-cheats-tricks-to-dodge-the-hard-parts-of-testing/"><![CDATA[<p>Test Driven Development is sometimes hard.
I have found some “cheats” to make it easier.</p>

<h3 id="test-gets-too-big-and-complicated">Test gets too big and complicated</h3>

<p>Split up the thing you are testing.
Create a collaborator and test that separately or just split up the function.
Splitting up view logic and rendering is nice and make testing easier.</p>

<p><em>Cheat codes:</em> “separation of concerns”,
“model view controller”, “view model - model view”</p>

<h3 id="state-makes-things-hard">State makes things hard</h3>

<p>Sometimes the test depends on a system state
or some other thing that is hard to control in the test.
Inject the tricky thing as a dependency (fancy word for parameter)
to the function/method.
Today’s date should always be injected as a dependency if used.</p>

<p><em>Cheat codes:</em> “dependency injection”</p>

<h3 id="the-framework-i-am-using-has-no-test-doubles">The framework I am using has no test doubles</h3>

<p>Wrap the framework in your own code
and create a double for the wrapper.
That will also isolate the framework,
make it easier to adapt, replace and upgrade.</p>

<p><em>Cheat code</em>: “ports and adapters”, “Hexagonal design”</p>

<h3 id="i-do-not-understand-mocks-stubs-fakes-and-all-the-tricky-words">I do not understand mocks, stubs, fakes and all the tricky words</h3>

<p>Try to avoid side effects in your code as far as possible.
Isolate necessary side effects (as sending/getting data)
to specific areas of the code
— the shell.
A function or method that does not return anything,
aka a void function,
is a sign of a side effect in action.
Make sure void functions do not contain any conditionals (if etc.).
Write the rest of the code without side effects,
levering data. If that is the only place containing logic,
it is the part most important to test.
And that can be done without tricky things as mocks.</p>

<p><em>Cheat code:</em> “pure functions”, “io monads”, “functional core - imperative shell”</p>

<p>Sources:</p>

<p><a href="https://www.destroyallsoftware.com/talks/boundaries">https://www.destroyallsoftware.com/talks/boundaries</a></p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><category term="list" /><summary type="html"><![CDATA[Test Driven Development (and unit testing in general) is easier when some things are avoided or encapsulated. Here are four problems faced when unit testing and their solutoins.]]></summary></entry><entry><title type="html">My health checkup checklist for software projects</title><link href="https://chocolatedrivendevelopment.com/2021/03/15/my-health-checkup-checklist-for-software-projects/" rel="alternate" type="text/html" title="My health checkup checklist for software projects" /><published>2021-03-15T00:00:00+00:00</published><updated>2021-03-15T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2021/03/15/my-health-checkup-checklist-for-software-projects</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2021/03/15/my-health-checkup-checklist-for-software-projects/"><![CDATA[<p>What is good code?
That is not a question easily answered.
But sometimes you need to do a quick assessment
on the state of a software project.
When I get my hands on a new collection of code,
these are the steps I take for a first assessment
on how easy the project will be to work with.
How far I get depends on how much time I have and how the code is.
Language and framework will also matter for how important each step is,
and how well I can answer the questions.
Some findings will make me entirely skip the rest of the section,
as if there are no tests the rest of that section makes no sense.
There are also not always a “right” and a “wrong” answer to the questions,
not only objectively but also from my subjective view.
For me, the most important thing is to know what I am getting myself into.
I hope it can be helpful for others too. My steps are:</p>

<h2 id="1-get-the-code">1. Get the code</h2>

<ul>
  <li>How are the dependencies managed?</li>
  <li>Are there a lot of deprecations and exploits found for the dependencies?</li>
  <li>Is the code “older” than its first commit?
That can happen if the project starts as a copy of an older project.</li>
  <li>If it should compile, does it compile?</li>
</ul>

<h2 id="2-run-the-code">2. Run the code</h2>

<ul>
  <li>Is there a readme?</li>
  <li>If there is a readme and I follow it,
will I have the project running on my computer?</li>
  <li>If the readme is missing, or is not leading to a running project,
what is missing? How much work would it be to fix it?</li>
  <li>How are secrets handled?</li>
  <li>Do I need anything besides the code to run things on my computer?</li>
  <li>Is the setup extra complicated compared to similar projects?</li>
  <li>Is the project prepared for new developers in some other way than a readme?</li>
</ul>

<h2 id="3-tests">3. Tests</h2>

<ul>
  <li>Are there tests?</li>
  <li>It there are tests, can I run them after following the readme?</li>
  <li>Can I run the tests on a computer not connected to the internet?</li>
  <li>What is the coverage for the tests, using metrics available?</li>
  <li>What is the proportion between unit tests and integration tests?</li>
  <li>Are the tests correctly labeled as unit/integration/system…
tests depending on what they do test?</li>
  <li>How is sensitive information, as secrets, handled for tests?</li>
  <li>How is the test data managed?</li>
  <li>Can I break the tests by changing the code?</li>
  <li>If I change the code will it break any tests?</li>
  <li>How much work is it to write the next test?</li>
</ul>

<h2 id="4-read-the-code">4. Read the code</h2>

<ul>
  <li>Can I see the domain in the naming and/or the types?</li>
  <li>How much code is there?
In how big chunks is it grouped (files, classes, functions)?</li>
  <li>Are there private/inner methods/functions/objects?</li>
  <li>Is there a linter? Does it produce any errors or warnings?
What kind of rules are enforced?</li>
  <li>Does the code have the feel of the language it is written in
or can I sense an “accent” from another programming language?</li>
  <li>How are external dependencies used?
Are they isolated or intertwined with the business logic?</li>
  <li>How is data transfer done (network/storage)?
Is it scattered over the code or done in one place?</li>
  <li>Are there a lot of dependencies/imports for each piece of code?</li>
  <li>How is error handling done?</li>
  <li>What does the cyclomatic complexity look like in general?
How is control flow managed? How is iteration and data manipulation done?</li>
  <li>Are there global state,
magic numbers or other implicit dependencies for objects and functions?</li>
  <li>How big portion of the code
do I need to read more than once to understand what it does?</li>
  <li>If I try to refactor the code somewhere random,
perhaps extracting a method, how hard is it?</li>
</ul>

<h2 id="5-version-control">5. Version control</h2>

<ul>
  <li>How big are the changes in the commits?</li>
  <li>How many files do each commit touch?</li>
  <li>Can i make sense of the messages?</li>
</ul>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="quality" /><category term="list" /><summary type="html"><![CDATA[A list of aspects to consider when getting to know a new software project and assessing how easy it will be to work with.]]></summary></entry><entry><title type="html">Software interior design</title><link href="https://chocolatedrivendevelopment.com/2021/03/12/software-interior-design/" rel="alternate" type="text/html" title="Software interior design" /><published>2021-03-12T00:00:00+00:00</published><updated>2021-03-12T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2021/03/12/software-interior-design</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2021/03/12/software-interior-design/"><![CDATA[<p>Software architecture is a known concept.
This is a post about software interior design.</p>

<p>As a developer I spend my work days submerged in code.
That is my work environment,
together with all the tooling that come with it.
For work to be pleasant it matters how the code is written.
And just as software architecture,
with its patterns and structure,
come form the architecture of houses,
there is now software interior design.
I like to share some of my principles around it.</p>

<h2 id="free-your-rooms-of-things-that-distract-and-hinder-you">Free your rooms of things that distract and hinder you</h2>

<ul>
  <li>Use version control to remove everything that is not needed
as the code works now.
No commented out code,
no old classes that stick around just in case you need them again.
Trust your versioning system.</li>
  <li>Use a linter to make the code consistent.</li>
  <li>Do not allow any errors, warnings or broken tests to stay in the code.
It will dull your sense of order.</li>
</ul>

<h2 id="create-spaces-that-serve-the-ones-using-it-well">Create spaces that serve the ones using it well</h2>

<ul>
  <li>Optimise your code for reading,
you will do that much more frequent than you write it.
(The interior design equivalent is
that things should be easier to put away than to take out.)</li>
  <li>Store things together that belong together.
See what files are touched by a change.
If you need to touch the code in a lot of places for one change,
it is a design problem or too big changes.</li>
  <li>Have a working pipeline.
Make sure that you have an environment that you can run and test your code in.</li>
</ul>

<h2 id="things-that-are-cared-for-last-longer">Things that are cared for last longer</h2>

<ul>
  <li>Update frameworks.
Make sure that the documentation and readme is updated too.</li>
  <li>Refactor the code while you modify it.
Tests and a good IDE will do wonders.</li>
  <li>If the code smells, you should probably clean it.
It could need a bigger rewrite than what fits into the everyday work on new features.</li>
</ul>

<h2 id="create-a-place-that-makes-others-feel-welcome">Create a place that makes others feel welcome</h2>

<ul>
  <li>Have a complete readme for setting up the project.
Err on being too explicit
rather than assuming that the one following the guide
knows things they do not.</li>
  <li>Let rules for the project be explicit.
“Configuration as code” and linting are both also social contracts.
Explicit rules can be challenged when new insights arrive
(sometimes in the shape of new people).
The rest of the time no-one has to spend energy on sticking to them if they are automated.</li>
  <li>Use the business domain in the code.
New people will have to learn both of them.
If the knowledge about the business is explicitly expressed in the code,
there is less to learn.
And learning from one of the areas will make the other easier to understand.</li>
</ul>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><category term="empathy" /><summary type="html"><![CDATA[Our mind also has ergonomics. Software interior design is about designing our code, and our systems around it, to make our work easier.]]></summary></entry><entry><title type="html">One test at a time, one step at a time</title><link href="https://chocolatedrivendevelopment.com/2020/11/26/one-test-at-a-time-one-step-at-a-time/" rel="alternate" type="text/html" title="One test at a time, one step at a time" /><published>2020-11-26T00:00:00+00:00</published><updated>2023-09-14T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2020/11/26/one-test-at-a-time-one-step-at-a-time</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2020/11/26/one-test-at-a-time-one-step-at-a-time/"><![CDATA[<p>My favourite way to create something big that works,
is to start with something small that works.
Test Driven Development has the benefit of resulting in automated regression tests,
but that is not my main reason to like it.
According to Theory of Constraints starting with verification reduces waste.
To me the tests are a sounding board in the thinking process of creating software.
So I write one test at the time,
before I write the code,
and here is why:</p>

<h2 id="specific-feedback">Specific feedback</h2>

<p>In the red-green-refactor cycle,
when a test is red,
that was expected to turn green,
we need it to provide feedback.
When the code is not doing what we think it should,
one red test has a lot more information than ten.
With only one red test at the time,
we can be sure that it is the latest change we did that is not working.
When writing trivial code this will never happen.
But not all code is trivial,
and some code get less trivial just before lunch or during a bad day.</p>

<h2 id="design-guidance">Design guidance</h2>

<p>Code that is designed to be tested is also designed to be reused.
Tests are code using your units.
When figuring out the interaction between code and test,
the API of the unit will probably change.
With great refactoring tools changing multiple tests are quickly done.
But still,
having to repair something,
that has not brought value yet,
is wasteful.</p>

<h2 id="just-the-right-amount-of-tests">Just the right amount of tests</h2>

<p>It can be hard to know how many tests that is enough,
before you start implementing them.
Tests are code that have to be maintained,
and take time to run.
So having just enough tests is really valuable.
If the first step is to invent all tests that might be useful,
our inventive power might make us a bit too productive.
We might create tests that end up being waste.
One effect of red-green-refactor is that
no tests can be written for code that is already implementing
the functionality tested,
since you need to start with a test that is red.
That prevents us from writing duplicate tests.</p>

<p>Just like a backlog contains stories to implement later,
a test file can contain a list of test descriptions,
names,
or corner cases.
That can be our outer loop.
For the inner loop I want red-green-refactor,
for one test at a time,
one step at the time.</p>

<p>ps.
If the code got too clever too early
and you think that you might not have full test coverage
— there is a solution.
To make sure that everything the code does is covered with tests,
mutation testing can be used.
Mutation testing is when you change the code to test if it is covered by a test.
A “mutant” is introduced by changing a constant,
swapping a conditional or something else
that should modify the functionality of the code.
When a mutant is introduced and no tests go red,
you can write a new one that does fail.
That test is then red,
and when the code is restored,
it turns green.
That way there will be only the tests needed,
and hopefully all the tests needed.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><summary type="html"><![CDATA[Three benefits from doing test first, one test at the time are: specific feedback, design guidance and finding the right amount of tests.]]></summary></entry><entry><title type="html">Guided by tests</title><link href="https://chocolatedrivendevelopment.com/2020/11/24/guided-by-tests/" rel="alternate" type="text/html" title="Guided by tests" /><published>2020-11-24T00:00:00+00:00</published><updated>2023-09-12T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2020/11/24/guided-by-tests</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2020/11/24/guided-by-tests/"><![CDATA[<p>In Test Driven Development we write one test at the time.
Why is that? Why not just write all of them,
and then write the code?
One of the main reasons is the mutual interaction
between tests and its code.
To be strict,
we do not have to start with any complete test at all.
The important thing is to have a test that guides the next step we plan to take.
A part of writing code is exploring how it will interact with the rest of the world,
and the tests are our playground for that.
If the code is collaborating well with its tests
it will also play nicely with its friends in the codebase.</p>

<p>It is important to start with a failing test,
also a simple one.
Knowing that feedback is always available,
and easy to reach for,
will enable us to correct our work constantly.
TDD could also have been named Feedback Driven Development.
It is not the final test that is its strongest feature.
If the function is simple enough to write a correct test for at once,
then it is ok.
But the ‘red-green-refactor’ cycle of TDD is also intended to modify the tests.
A first failing test (‘red’) can be to assert that true is false,
just to make sure the test can be run.
A first passing test (‘green’) can be that the function under test exists at all.
Then the tests will evolve together with the code,
always ready to verify the next small step of implementation.</p>

<p>When the feedback is constant,
supporting the iterations and not only there to show the end goal,
we can truly be guided by our tests.
They will be a railing to hold on to,
also when we need to take steps that are smaller than one completed test.</p>

<p>So make sure to have the system for feedback in place first,
and design it to fit only the next step you plan to take.
That way you will not lose your footing.</p>

<p>ps.
Do not forget to refactor your tests.</p>

<p>ps2.
Sometimes we write tests as a part of finding an earlier mistake,
aka bug.
Then the step-by-step test writing 
can also be a way to figure out how the code is actually working.
That way we can slowly figure out how to test it.
Otherwise we might get put down by the expectancy to produce a perfect test
to reproduce the bug from start.
The code where bugs hide are often harder to test.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="quality" /><category term="code" /><summary type="html"><![CDATA[In test driven development the tests, even before they even test something, guides our steps. The trick is to take really small steps, and let code and tests evolve together.]]></summary></entry><entry><title type="html">Test Driven Development in Theory of Constraints terms</title><link href="https://chocolatedrivendevelopment.com/2020/11/24/test-driven-development-in-theory-of-constraints-terms/" rel="alternate" type="text/html" title="Test Driven Development in Theory of Constraints terms" /><published>2020-11-24T00:00:00+00:00</published><updated>2020-11-24T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2020/11/24/test-driven-development-in-theory-of-constraints-terms</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2020/11/24/test-driven-development-in-theory-of-constraints-terms/"><![CDATA[<p>Picture a small system.
Something is produced and then it is verified.
If the producing is more demanding than the verification,
the production step is the constraint.
The production time limits the throughput.
Move the verification step in front of the production step.
Making sure only to spend effort on things that will add value.
Make each iteration, batch, smaller.
Then the waste in the system will go down, and the throughput go up.</p>

<p>This is Test Driven Development (TDD) explained with Theory of Constraints.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="ToC" /><category term="quality" /><category term="code" /><summary type="html"><![CDATA[How Theory of Constraints leads us to move the verification step in front of the production step, and keep shrinking the batch size.]]></summary></entry><entry><title type="html">The power of linting</title><link href="https://chocolatedrivendevelopment.com/2020/10/23/the-power-of-linting/" rel="alternate" type="text/html" title="The power of linting" /><published>2020-10-23T00:00:00+00:00</published><updated>2020-10-23T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2020/10/23/the-power-of-linting</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2020/10/23/the-power-of-linting/"><![CDATA[<blockquote>
  <p>TL;DR; Use a linter for your code!
And fix <em>all</em> errors and warnings. Your brain will thank you.</p>
</blockquote>

<p>In software,
a linter is a static code checker.
It looks at syntax,
code format and white space,
spelling,
coding conventions,
patterns that might cause bugs and other things that is not related to business logic.
A lot of them have configurable rules,
ways to make exceptions
(that can be used for gradual introduction in legacy projects)
and ways to auto-correct your code.</p>

<p>I see a linter as a cognitive tool,
something we use to relieve our brains
so that there is more energy left for things like problem solving.
Here are three ways linting does that:</p>

<h2 id="1-linting-rules-are-a-social-contract">1. Linting rules are a social contract</h2>

<p>Social negotiation takes energy.
When a team has decided on the linting rules the discussion is done,
or at least not constantly debatable.
And it is enforced without any specific person having to take the fight.
Have a pipeline for the code
where linting is checked before code ends up in a flow
shared by other developers.</p>

<h2 id="2-linting-removes-noise">2. Linting removes noise</h2>

<p>Code that is regular is easier to read.
Having a common standard is much more important than what standard you use.
But the removing of noise only works fully if you do not let the linter add noise.
Therefore <em>it is important not to let any errors, or warnings stay</em>.
If you have something in your code that you want to keep,
though the linter is protesting,
make an explicit exception to silence the error or warning.
As an extra,
some linters can also recommend a simpler syntax
for achieving the same behaviour.
That can make your code less verbose
without obfuscating it and then also remove noise.</p>

<h2 id="3-linting-is-automatic">3. Linting is automatic</h2>

<p>A lot of what the linter does is things you would like to do,
but now you do not have to.
As with spell checking,
you can find and fix all the deviations from how you want your code to look,
while reading it and having it reviewed.
But as with spell checking,
that is neither the fun part of writing nor the most energising thing
to give and get feedback about.
Let the computer do the boring stuff.</p>

<h2 id="bonus">Bonus</h2>

<p>Linting might find bugs.
Especially in languages without a compile step,
the checking for risky syntax is very valuable.</p>

<p>So,
go and lint your code!
And add the linting as an automatic step when writing code.
That way you let the machine do a little more of the boring job,
and leave more energy to do fun things,
like problem solving.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="code" /><category term="quality" /><category term="empathy" /><summary type="html"><![CDATA[Use a linter for your code! And fix all(!) errors and warnings. Your brain will thank you.]]></summary></entry><entry><title type="html">Waste In Process and User Research</title><link href="https://chocolatedrivendevelopment.com/2020/07/07/waste-in-process-and-user-research/" rel="alternate" type="text/html" title="Waste In Process and User Research" /><published>2020-07-07T00:00:00+00:00</published><updated>2020-07-07T00:00:00+00:00</updated><id>https://chocolatedrivendevelopment.com/2020/07/07/waste-in-process-and-user-research</id><content type="html" xml:base="https://chocolatedrivendevelopment.com/2020/07/07/waste-in-process-and-user-research/"><![CDATA[<p>Goldratt describes,
in the book The Goal,
how a failing factory is transformed into a success.
One of the steps,
as the purpose of the story is to describe Theory Of Constraints,
is to find the bottlenecks of the production in the factory.
When this is done,
they try to find ways to grow the capacity of the bottlenecks.</p>

<p>They go to the quality assurance team that tests finished products.
There they find a lot of things that passed through a bottleneck,
but got discarded.
since they had shortages in quality.
By moving parts of the QA before the bottleneck,
they save the limiting station from working on things
that are already broken.</p>

<p>What is the equivalent to this in software?</p>

<p>I do TDD and BDD! you might say.
If we assume that the developers are the bottleneck
 I would say that it is rather like making sure that the products
 are not broken during or after they are at the bottleneck.</p>

<p>My suggestion is that we see user research and design sprints
as our way to make sure that we do not have products
that are already broken taking up valuable time at the bottlenecks.
Every feature,
that is not tested against a real user,
risk being waste in process instead of work in progress
already when it reaches the development team.</p>

<p>The best way to increase the capacity of a bottleneck is
to find what it should not do.
By doing <a href="https://www.gv.com/sprint/">design sprints</a> and user research
you can try a lot of ideas
that do not have to go though the full development cycle.
(It has other advantages too.)
By investing in usability and design a lot of redo and undo can be saved.</p>

<p>Make sure that all tasks that get turned into code
has first been checked that they actually should be implemented.
That is how user research limits waste in process.</p>]]></content><author><name>Ester Daniel Ytterbrink</name></author><category term="ToC" /><category term="quality" /><category term="product" /><summary type="html"><![CDATA[User research can save as much effort in the IT-industry as QA before a bottleneck does in manufacturing.]]></summary></entry></feed>