<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Vini Coppi</title>
    <description>The latest articles on Forem by Vini Coppi (@vinicoppi_dev).</description>
    <link>https://forem.com/vinicoppi_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1668112%2Fa42f7388-a6b9-499e-9185-b68625cf02a4.jpg</url>
      <title>Forem: Vini Coppi</title>
      <link>https://forem.com/vinicoppi_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/vinicoppi_dev"/>
    <language>en</language>
    <item>
      <title>Legacy code: How bad are comments (really)?</title>
      <dc:creator>Vini Coppi</dc:creator>
      <pubDate>Tue, 05 Aug 2025 14:35:22 +0000</pubDate>
      <link>https://forem.com/vinicoppi_dev/legacy-code-how-bad-are-comments-really-4kai</link>
      <guid>https://forem.com/vinicoppi_dev/legacy-code-how-bad-are-comments-really-4kai</guid>
      <description>&lt;p&gt;You have probably heard the commandment: "good code doesn't need comments." The idea, which has become almost a dogma, is that the code should be so clear, expressive, and self-explanatory that any comment would be redundant. And, in an ideal world, this statement would be absolutely correct. But in reality, as is almost always the case in software engineering, it is not that simple to achieve. For a team that manages, evolves, and operates software in production, the journey to completely eliminate the practice of commenting the source code is long and arduous. It is not just about writing cleaner code, but about a profound evolution in processes, software architecture, and team culture. Reaching a state where comments are genuinely unnecessary requires an effort and time that we often underestimate.&lt;/p&gt;

&lt;p&gt;There was a time when commenting code was not only acceptable but actively encouraged. Before the popularization of agile methodologies and the focus on expressive code, development processes were more linear (like the Waterfall model). The documentation was a separate and dense artifact, and the comments in the code served as an instruction manual right at the source.&lt;/p&gt;

&lt;p&gt;Imagine a piece of code in COBOL or Fortran from the 1980s. It was common to find blocks of comments at the top of each function, explaining what it did, what parameters it received, and what it returned, as the language itself did not offer the same expressiveness that we have today.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*--------------------------------------------------*
* SUBROUTINE: CALCULATE_PROGRESSIVE_DISCOUNT       *
* AUTHOR: J. SILVA                                 *
* DATE: 06/15/1985                                 *
*--------------------------------------------------*
* OBJECTIVE:                                       *
* APPLY DISCOUNT TO THE TOTAL ORDER VALUE BASED    *
* ON THE QUANTITY OF ITEMS PURCHASED.              *
*                                                  *
* PARAMETERS:                                      *
* - P_TOTAL_VALUE (NUMERIC)                        *
* - P_ITEM_QTY (INTEGER)                           *
*                                                  *
* RETURN:                                          *
* - P_FINAL_VALUE (NUMERIC)                        *
*--------------------------------------------------*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was the standard. The call to this subroutine might be something like &lt;code&gt;CALL "CALCDESC" USING ORDER-VALUE, ORDER-ITEMS GIVING ORDER-FINAL&lt;/code&gt;. Without the comment block, the rule of applying progressive discounts from &lt;code&gt;CALCDESC&lt;/code&gt; would be obscure. Comments were the main way to transfer knowledge in an era with radically different tools and culture.&lt;/p&gt;

&lt;p&gt;With the rise of agile methodologies, the philosophy of software development underwent a transformation. The focus shifted from extensive documentation to functional software, and collaboration and responsiveness to change became paramount. In this new context, a strong school of thought emerged that advocated for the clarity of the code as the main form of documentation. The idea that comments represent a "code smell" — a symptom that the code has failed to communicate its intention — gained traction. The community began to value names of variables, functions, and classes that described their purpose unequivocally. The prevailing view became that if the code needs a comment to be understood, it probably needs to be rewritten. This interpretation, sometimes rigid, left little room for the exceptions and nuances of the real world.&lt;/p&gt;

&lt;p&gt;At this point, the discussion reaches a terrain known to all experienced developers: the difference between the "what" and the "why." For many, it is not new that a good comment explains the reason behind a design decision, and not what the code is literally doing. However, in the incessant search for "pure" code, this principle can be forgotten. The code, however expressive, is an artifact that responds to business constraints, technical limitations, time commitments, among other things. It rarely manages to tell the whole story.&lt;/p&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paymentData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paymentData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid payment payload.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// TODO: Remove this forced pause when the billing API is optimized (TICKET-123)&lt;/span&gt;
    &lt;span class="c1"&gt;// The external billing API has a very aggressive rate limit and returns a 503 error&lt;/span&gt;
    &lt;span class="c1"&gt;// if we receive more than 5 requests per second. A 300ms pause here&lt;/span&gt;
    &lt;span class="c1"&gt;// avoids hitting the limit in batch processing scenarios.&lt;/span&gt;
    &lt;span class="c1"&gt;// There is already a plan to migrate to an API with queues (SQS).&lt;/span&gt;
    &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;billingAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paymentData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code clearly shows a 300ms pause. The comment explains why this pause, which seems inefficient, is crucial for the stability of the system. It transforms what would be "bad code" into a conscious and documented engineering decision, protecting the system from premature optimizations, even if well-intentioned.&lt;/p&gt;

&lt;p&gt;Even with this distinction between comments that explain "what" and those that explain "why," some people will still argue that even the context comment in the example above is a "code smell." For them, the code and the ecosystem around it should be sufficient to provide all the necessary context. Reaching this level of clarity is the ultimate goal, but, as we will see, the road is long. Some of the techniques that assist this process are &lt;strong&gt;BDD/TDD&lt;/strong&gt; (Behavior-Driven-Development/Test-Driven-Development), &lt;strong&gt;Clean architecture&lt;/strong&gt; (Use Cases as filenames, for example &lt;code&gt;ProcessPayment.ts&lt;/code&gt;, facilitate contextualization), &lt;strong&gt;Docs as Code&lt;/strong&gt; (Markdown documentation files together with the source code), &lt;strong&gt;significant commit messages&lt;/strong&gt; (&lt;code&gt;feat(auth): add Google login to close TICKET-451&lt;/code&gt;), among others. However, the adoption of these practices is far from trivial, especially in teams dealing with legacy software. Introducing BDD into a codebase with low test coverage is a monumental task. Refactoring a monolithic system to a clean architecture can be a project of months or years, often without a clear return on investment for the business in the short term. Implementing "Docs as Code" or standardizing commits requires a cultural change, discipline, and the consent of the entire team, something difficult to achieve under the pressure of constant deliveries. For legacy systems, the cost and risk associated with these changes often outweigh the perceived benefits, making incremental improvement and the strategic use of comments a much more pragmatic approach.&lt;/p&gt;

&lt;p&gt;It is precisely in the terrain of legacy code that the debate about comments becomes more pragmatic and less philosophical. For systems that have been in production for years, that support critical operations, and whose original development is a distant memory, an aversion to comments is an unsustainable luxury. In these environments, a well-placed comment is not a "code smell"; it is a strategic risk management tool. The reality of the teams that maintain these systems is dictated by limited budgets, tight deadlines, and a justified fear of breaking what is working. The idea of a large-scale refactoring to "clean up" the code is often unfeasible. In these cases, using comments to map complex areas, explain workarounds, and document inexplicable "magic" is the most responsible approach. It is a way to transfer tacit knowledge and protect the business with an unbeatable cost-benefit ratio. To ignore this reality in the name of an ideal of purity is to neglect the engineer's fiduciary duty to the stability of the software.&lt;/p&gt;

&lt;p&gt;The discussion about comments in code needs to evolve from a binary debate of "right vs. wrong" to a conversation about process maturity, pragmatism, and context. A dogmatic aversion to comments is often a sign of an immature view of software engineering, which ignores the complex realities of long-term development and maintenance. The real issue does not lie in blindly following the rules of "clean code," but in understanding when and why to break them. A well-written comment is not an admission of failure; it is an act of empathy towards future developers (including yourself). It is an investment in the sustainability of the project and the sanity of the team. Instead of demonizing comments, we should see them for what they really are: a powerful tool in an engineer's arsenal. In the end, the goal should not be to create code without comments, but rather a robust, sustainable, and, above all, understandable software. And, to get there, a good comment can be your best ally.&lt;/p&gt;

&lt;p&gt;Do you agree with me? Please leave a comment and let's help others evolve legacy code.&lt;/p&gt;

&lt;p&gt;Thank you for your time, have a great day!&lt;/p&gt;

</description>
      <category>legacycode</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
