<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>matklad.github.io</title>
  <subtitle>Browse aymeric&#39;s, an independent, searchable archive of readable snapshots from followed feeds, preserved in Git with aggr.</subtitle>
  <id>https://aggr.aymericbeaumet.com/sources/matklad.github.io/</id>
  <link rel="alternate" type="text/html" href="https://aggr.aymericbeaumet.com/sources/matklad.github.io/"/>
  <link rel="self" type="application/atom+xml" href="https://aggr.aymericbeaumet.com/sources/matklad.github.io/atom.xml"/>
  <updated>2026-10-31T18:05:03+00:00</updated>
  <author>
    <name>aymeric&#39;s</name>
  </author>
  <generator version="2.0.0" uri="https://github.com/aymericbeaumet/aggr">aggr</generator>
  <entry>
    <id>urn:aggr:item:407c18c38932cbcc0908294a349853e2e86391d0</id>
    <title type="text">Avoid Public Functions Calling Other Public Functions</title>
    <link rel="alternate" type="text/html" href="https://aggr.aymericbeaumet.com/items/lobste-rs/2026-10-31-avoid-public-functions-calling-other-public-functions/"/>
    <link rel="via" type="text/html" href="https://matklad.github.io/2026/10/29/pub-calls-pub.html"/>
    <published>2026-10-31T18:05:03+00:00</published>
    <updated>2026-10-31T18:05:03+00:00</updated>
    <author>
      <name>matklad.github.io via telemachus</name>
    </author>
    <category term="news"/>
    <category term="api"/>
    <category term="programming"/>
    <source>
      <title>Lobsters: Top Stories of the Past Week</title>
    </source>
    <summary type="text">Comments</summary>
    <content type="html">&lt;p&gt;Oct 29, 2026&lt;/p&gt;
&lt;p&gt;A small-scale rule of thumb. This article will land much better with a concrete example, but I am drawing a blank here, so you gotta just blindly trust my say so!&lt;/p&gt;
&lt;p&gt;When implementing a software module, it’s often a case that you are writing a public function &lt;code&gt;foo&lt;/code&gt;, and at least part of what &lt;code&gt;foo&lt;/code&gt; does is already handled by another public function &lt;code&gt;bar&lt;/code&gt;. The DRY instinct encourages you to call &lt;code&gt;bar()&lt;/code&gt; from within &lt;code&gt;foo&lt;/code&gt;. This usually creates problems down the line. Instead, create a new &lt;em&gt;private&lt;/em&gt; function and refactor both &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; to call that shared helper:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;CSS&quot;&gt;&lt;span class=&quot;syntax-source syntax-css&quot;&gt;//&lt;span class=&quot;syntax-meta syntax-selector syntax-css&quot;&gt; BAD
pub fn foo(&lt;/span&gt;)&lt;span class=&quot;syntax-meta syntax-selector syntax-css&quot;&gt; void &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-property-list syntax-css&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-property-list syntax-css&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-property-name syntax-css&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-property-name syntax-css&quot;&gt;bar&lt;/span&gt;(.{ .&lt;span class=&quot;syntax-meta syntax-property-name syntax-css&quot;&gt;frobnicate&lt;/span&gt; = &lt;span class=&quot;syntax-meta syntax-property-name syntax-css&quot;&gt;true&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-punctuation syntax-section syntax-property-list syntax-css&quot;&gt;}&lt;/span&gt;);
}

&lt;span class=&quot;syntax-meta syntax-selector syntax-css&quot;&gt;pub fn bar(options: struct &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-property-list syntax-css&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-property-list syntax-css&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-property-name syntax-css&quot;&gt;frobnicate&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-key-value syntax-css&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-property-value syntax-css&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-property-value syntax-css&quot;&gt;bool = false,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-property-list syntax-css&quot;&gt;}&lt;/span&gt;)&lt;span class=&quot;syntax-meta syntax-selector syntax-css&quot;&gt; void &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-property-list syntax-css&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-property-list syntax-css&quot;&gt;{&lt;/span&gt;
    // ...
&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-property-list syntax-css&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;code-snippet&quot;&gt;// GOOD
pub fn foo() void {
    return helper(.frobnicate);
}

pub fn bar() void {
    return helper(.transmogrify);
}

fn helper(mode: enum { frobnicate, transmogrify }) void {
    // ...
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rationale: the goal of a public API is to provide an interface that works best at the call site. If parts of public API are re-used to implement the rest of the API, then there’s a tension between making the interface convenient for the outside user and making it convenient to use from within abstraction itself. Namely, functions tend to grow optional parameters that should never be set by the user. Crucially, the parameter growth and interface degradation can happen &lt;em&gt;after&lt;/em&gt; the original code sharing.&lt;/p&gt;
&lt;p&gt;By proactively making the shared implementation private, the tension is defused. You still might need to tinker with &lt;code&gt;helper&lt;/code&gt; signature until it does everything it needs to do, but, because the helper is private, this is a cheap, local change.&lt;/p&gt;
&lt;p&gt;A notable exception to this rule of thumb are “shortcut” APIs, where a public function is &lt;em&gt;defined&lt;/em&gt; as a commonly used chain of calls to other public functions. There, the rule is the opposite — &lt;em&gt;no&lt;/em&gt; private calls are allowed, to make sure that it is a genuine shortcut, and not a midlayer mistake.&lt;/p&gt;
&lt;p&gt;P.S. While researching if anyone wrote a better blog post already, I stumbled upon a fun stack overflow question, asking, paraphrasing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’ve heard that it is bad when a public function calls another public function. Is this really so?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The most upvoted answer explains that it is indeed bad, because this makes mocking to test a single method in isolation more complicated. Which is, imo, a natural, but horrible consequence of misguided approach to testing. You shouldn’t be mocking your methods, you should mock your IO. And, similarly, you shouldn’t test methods, but rather software functionality (unless you are building a public library with a stable API, which is a fun and important, but very narrow fraction of software development).&lt;/p&gt;
&lt;p&gt;The accepted answer says that this recommendation makes no sense if it is not backed by an industry wide or an organizational standard. Which somehow manages to make even less sense — you shouldn’t follow the guideline rules because they are written in sanctified ink! Rather, you should apply each particular rule because of the underlying reasons that motivate the rule. Guidelines and best practices articles can concentrate lots of good reasoning in a single place, but they don’t absolve you from thinking!&lt;/p&gt;
</content>
  </entry>
</feed>
