<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Florent Guilleux]]></title><description><![CDATA[Florent Guilleux]]></description><link>https://www.florentguilleux.fr</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 19:44:05 GMT</lastBuildDate><atom:link href="https://www.florentguilleux.fr/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Documenting Features for Developers]]></title><description><![CDATA[Code alone rarely explains a feature well enough to extend it or debug it quickly. Even when it does, understanding it through code only can take unnecessary time and effort. Good documentation can help tremendously.
Write as if the reader never atte...]]></description><link>https://www.florentguilleux.fr/documenting-features-for-developers</link><guid isPermaLink="true">https://www.florentguilleux.fr/documenting-features-for-developers</guid><category><![CDATA[documentation]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Florent Guilleux]]></dc:creator><pubDate>Sat, 27 Dec 2025 10:56:34 GMT</pubDate><content:encoded><![CDATA[<p>Code alone rarely explains a feature well enough to extend it or debug it quickly. Even when it does, understanding it through code only can take unnecessary time and effort. Good documentation can help tremendously.</p>
<p><strong>Write as if the reader never attended design meetings, never read the implementation tickets, or even never used the feature.</strong> The goal is to make them productive fast.</p>
<p>What to include:</p>
<ol>
<li><p>What the feature does, its benefits and the problems it addresses</p>
</li>
<li><p>How to use it locally</p>
</li>
</ol>
<ul>
<li><p>application settings to enable</p>
</li>
<li><p>if any third-party service is required, how to set it up and get its credentials</p>
</li>
<li><p>data to create or seed</p>
</li>
<li><p>exact steps to follow to use the feature</p>
</li>
<li><p>expected results</p>
</li>
</ul>
<p><strong>This section is critical.</strong> Developers often spend more time figuring out how to use a feature than fixing the bug itself.</p>
<ol start="3">
<li>How it is designed and how it works</li>
</ol>
<p>Describe the architecture and the reasoning behind it:</p>
<ul>
<li><p>key components and data flow</p>
</li>
<li><p>links to important classes, modules, and methods</p>
</li>
<li><p>trade-offs, rejected alternatives, known limitations</p>
</li>
</ul>
<ol start="4">
<li>Troubleshooting</li>
</ol>
<p>Provide a practical playbook:</p>
<ul>
<li><p>typical symptoms</p>
</li>
<li><p>likely causes: internal services, external APIs, configuration issues, end-users misunderstandings...</p>
</li>
<li><p>logs to check and where to find them</p>
</li>
<li><p>relevant metrics and dashboards</p>
</li>
<li><p>concrete steps to confirm and fix</p>
</li>
</ul>
<ol start="5">
<li>Maintenance</li>
</ol>
<p>Document recurring tasks:</p>
<ul>
<li><p>upgrades (libraries, services, dependencies)</p>
</li>
<li><p>checks to perform after upgrades</p>
</li>
<li><p>anything that requires periodic attention</p>
</li>
</ul>
<ol start="6">
<li>References</li>
</ol>
<p>Link to useful resources:</p>
<ul>
<li><p>external APIs</p>
</li>
<li><p>original design documents</p>
</li>
<li><p>related tickets, tests, diagrams, specs</p>
</li>
</ul>
<p>and link to the doc from the relevant pieces of code to make it more discoverable.</p>
<p>Finally, treat documentation as code: keep it in the repository, version it, and review it in every PR. This "Docs-as-Code" approach prevents knowledge rot and provides AI tools with the context they need to better support development.</p>
]]></content:encoded></item><item><title><![CDATA[How to Use Meta-Tests to Future-Proof Your Business Logic]]></title><description><![CDATA[You can write simple tests to ensure future changes in your codebase don’t silently break existing business logic.
Take this example: your application allows users to copy a product. Some associations should be copied (like category mappings), while ...]]></description><link>https://www.florentguilleux.fr/how-to-use-meta-tests-to-future-proof-your-business-logic</link><guid isPermaLink="true">https://www.florentguilleux.fr/how-to-use-meta-tests-to-future-proof-your-business-logic</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Florent Guilleux]]></dc:creator><pubDate>Wed, 22 Oct 2025 15:43:29 GMT</pubDate><content:encoded><![CDATA[<p>You can write simple tests to ensure future changes in your codebase don’t silently break existing business logic.</p>
<p>Take this example: your application allows users to copy a product. Some associations should be copied (like category mappings), while others should not (like customer comments).</p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Product</span> &lt; ApplicationRecord</span>
  has_many <span class="hljs-symbol">:category_mappings</span>, <span class="hljs-symbol">dependent:</span> <span class="hljs-symbol">:destroy</span>
  has_many <span class="hljs-symbol">:customer_comments</span>, <span class="hljs-symbol">dependent:</span> <span class="hljs-symbol">:destroy</span>


  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">copy</span></span>
    Product.transaction <span class="hljs-keyword">do</span>
      copy = dup.save!

      category_mappings.find_each <span class="hljs-keyword">do</span> <span class="hljs-params">|mapping|</span>
        copy.category_mappings.create!(mapping.attributes.except(<span class="hljs-string">'id'</span>, <span class="hljs-string">'product_id'</span>, <span class="hljs-string">'created_at'</span>, <span class="hljs-string">'updated_at'</span>))
      <span class="hljs-keyword">end</span>

      copy
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>When implementing such a feature, you'll review each existing association and decide whether it should be copied. But when a new association is added later, it’s easy to forget to update the copy logic.</p>
<p>You can prevent this by adding a meta-test that fails whenever a new association hasn’t been explicitly accounted for:</p>
<pre><code class="lang-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">"test_helper"</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductTest</span> &lt; ActiveSupport::TestCase</span>
  test <span class="hljs-string">"all associations have been accounted for in copy logic"</span> <span class="hljs-keyword">do</span>
    accounted_associations = %i[category_mappings customer_comments]
    unaccounted_associations = Product.reflect_on_all_associations.map(&amp;<span class="hljs-symbol">:name</span>) - accounted_associations

    assert unaccounted_associations.empty?,
      <span class="hljs-string">"Please account whether these associations should be included in Product#copy \
       and then add them to the accounted_associations variable of this test: 
       <span class="hljs-subst">#{unaccounted_associations.join(<span class="hljs-string">', '</span>)}</span>"</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>Now, if someone adds for example <code>has_many :variants</code> to Product without updating the test, it fails, reminding them to make an intentional decision.</p>
<p>This pattern applies anywhere you maintain an explicit list of elements that define behavior.</p>
<p>For instance, you can add similar tests to ensure all attributes or states are consciously handled:</p>
<ul>
<li><p>API exposure: every attribute of a model is either exposed or explicitly hidden</p>
</li>
<li><p>Audit logging: every field change that matters is intentionally logged</p>
</li>
<li><p>Exports: CSV or JSON exports always include all relevant fields</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>