<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://www.yegor256.com/rss.xml" rel="self" type="application/atom+xml" /><link href="https://www.yegor256.com/" rel="alternate" type="text/html" /><updated>2026-05-04T07:39:24+00:00</updated><id>https://www.yegor256.com/rss.xml</id><title type="html">Yegor Bugayenko</title><subtitle>Yegor Bugayenko</subtitle><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><entry><title type="html">Couriers, Not Coders</title><link href="https://www.yegor256.com/2026/05/03/no-mercy.html" rel="alternate" type="text/html" title="Couriers, Not Coders" /><published>2026-05-03T00:00:00+00:00</published><updated>2026-05-03T00:00:00+00:00</updated><id>https://www.yegor256.com/2026/05/03/no-mercy</id><content type="html" xml:base="https://www.yegor256.com/2026/05/03/no-mercy.html"><![CDATA[<p>Someone submitted an issue to one of our open GitHub repositories a week ago,
  suggesting a new feature.
We didn’t respond, since we
  <a href="/2024/04/01/ping-me-please.html">didn’t notice it</a>.
Today, someone else submitted an implementation of the feature in a pull request.
I rejected it and explained that the feature request must first be
  accepted by the
  <a href="/2014/10/12/who-is-software-architect.html">project architect</a>,
  and only then would it be worth
  making a pull request.
The author of the PR got offended.
He won’t be back.
Good.
A year ago, we would have been sad to lose an
  <a href="/2019/01/01/hazardous-enthusiasm.html">enthusiastic</a> contributor.
Today, we don’t care.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Cruel Intentions (1999) by Roger Kumble" src="/images/2026/05/cruel-intentions.jpg" longdesc="#73b21b12" /><figcaption id="73b21b12">Cruel Intentions (1999) by Roger Kumble</figcaption></figure>

<p>For years you sold coding skill at $50 an hour.
AI now codes for cents.
But you still want $50.</p>

<p>We are still ready to pay.
Not for the code—the code is free.
For the <em>delivery</em>.</p>

<p>You take what <a href="https://github.com/anthropics/claude-code">Claude Code</a> wrote and you walk it to our door.
You are the <em>courier</em>, not the coder.</p>

<p>The margin is what we pay for trust:
  that what you deliver, we can merge without re-checking.
So the delivery must be flawless.</p>

<aside class="quote">We pay for the delivery, not the code
</aside>

<p>A PR without a description is a package with no label—refused.
An unfocused PR is two parcels in one box—refused.
A PR too large to read is an oversized package—refused.
A PR sitting in review for weeks is a delivery that never arrived—refused.
A PR for an unapproved feature is a parcel for an address we never accepted—refused.</p>

<p>What we forgave yesterday, when we still needed the code, we no longer forgive.
The market for couriers is huge.
We can afford to choose.
So the bar rises, not falls.</p>

<p>Working code is now the minimum.
We expect discipline, speed of delivery, clear and detailed communication,
  and readiness to re-work.
Above all, we expect you to understand our
  <a href="/2015/10/13/competition-without-rules.html">rules</a>
  and <em>obey</em> them.</p>

<p>No mercy for mess.
Not anymore.</p>

<p>If you want the wage, earn the margin.</p>

<p>Be proud of the delivery, not the code.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="management" /><summary type="html"><![CDATA[Now that AI codes for cents, contributors are paid for the delivery, not the code—so no mercy for sloppy pull requests anymore.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2026/05/cruel-intentions.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2026/05/cruel-intentions.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Fast Software: More Programmers, Not Fewer</title><link href="https://www.yegor256.com/2026/03/05/fast-software.html" rel="alternate" type="text/html" title="Fast Software: More Programmers, Not Fewer" /><published>2026-03-05T00:00:00+00:00</published><updated>2026-03-05T00:00:00+00:00</updated><id>https://www.yegor256.com/2026/03/05/fast-software</id><content type="html" xml:base="https://www.yegor256.com/2026/03/05/fast-software.html"><![CDATA[<p>When I was five years old, I inherited the shoes of my older brother.
Not because our family was poor, but because the shoes were good.
My grandma told me that when she was a fiancée her dowry consisted of a few skirts.
Not because she was poor.
She wasn’t.
Because the skirts were good and rather expensive.
Now, in 2026, to get a new pair of shoes or a new skirt, I just buy them at a mall down the street.
I don’t hesitate to throw away the old ones.
The same will happen with the software, thanks to AI coding agents.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="25th Hour (2002) by Spike Lee" src="/images/2026/03/25th-hour.jpg" longdesc="#5ab67d51" /><figcaption id="5ab67d51">25th Hour (2002) by Spike Lee</figcaption></figure>

<p>A few days ago someone (I lost the link) shared a funny story on LinkedIn.
He showed a message from his former boss.
The boss was asking for a fix to software written twenty years ago.
The author of the story proudly claimed that some software, if written properly, can <em>survive</em> a generation.</p>

<p>The software in the story is similar to the skirt of my grandma.
It was made to survive a few decades.
Because it was <em>expensive to make</em>.</p>

<p>That’s why the boss is not hiring a new programmer to re-write the software.
He asks for a fix.
Just like my grandma would not throw away a skirt if it got a hole.
It would go to a tailor to get a patch.</p>

<p>Many of us wonder what may happen when AI agents, like <a href="https://code.claude.com/">Claude Code</a>, dominate the market.
Programmers, especially junior ones, may be fired en masse.
Look at what Jack Dorsey <a href="https://x.com/jack/status/2027129697092731343">just did</a>: terminating contracts of about 40% of his tech staff.</p>

<p>Large companies indeed will fire programmers, but not because the new world doesn’t need human coders.
It’s because the new world doesn’t need <em>large</em> software companies.</p>

<aside class="quote">We’ll toss our software, not update it
</aside>

<p>What the world is looking forward to is a <em>devaluation</em> of software craftsmanship.
Just like a skirt is no longer valuable, except for some high-end brands, software won’t be either.
Developing a new ERP system would cost a few thousand dollars and take a few days of work.
Just like it <a href="https://x.com/mntruell/status/2011562190286045552">recently took a week</a> to create a new web browser.</p>

<p>Oracle, Adobe, Microsoft, and JetBrains will run out of business.</p>

<p>When someone needs an IDE with new language support, they won’t wait for JetBrains to release it next year, maybe.
They will go to a software shop around the corner, pay a few hundred bucks, and get it next Monday.
When someone needs a new feature in Photoshop, they won’t wait for Adobe.
They will <em>buy a new</em> Photoshop from a friend, with the feature and maybe a few more.
When a company needs their accounting system to support a new logistics optimization scheme, they won’t go to Oracle.
They will <em>re-write</em> the entire Oracle Fusion, for a few thousand dollars.</p>

<p>We won’t wait for new releases of the old software we love.
We’ll toss them away and buy new ones.</p>

<p>The market will need more programmers, not fewer.
In order to sew good skirts for all women, a city may need a few dozen tailors.
Because every skirt costs a lot and is worn for decades.
In order to manufacture throw-away one-time skirts, the same city needs many more people.
Obviously, these new people are not the tailors of the good-old-days quality.
But they make many skirts, thousands per day.</p>

<p>Just like fast fashion replaced tailors with factory workers and machine operators, <strong>fast software</strong> will replace programmers with AI operators.
And the market will demand many of them.
Many more than large software companies employ today.</p>

<p>Large companies will lose their <em>monopoly on complexity</em>.
A small software shop will be able to build a new IDE, a new Photoshop, or even a new Linux.
For a few thousand dollars.</p>

<p>The importance of open source software will <a href="/2020/05/05/open-source-arms-race.html">continue to grow</a>.
It will become the primary provider of ingredients for AI and its operators.</p>

<p>The new world will need more programmers (AI operators) than it needs now.
Because the demand for custom software will soon start growing.
Everyone will want their own Photoshop.
Every developer will want their own IDE and their own Linux.
And they will throw them away without hesitation.
Just like I throw away my shoes every year and get new ones.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="mood" /><summary type="html"><![CDATA[AI coding agents will make software disposable, like fast fashion replaced tailored clothing, creating demand for more programmers, not fewer.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2026/03/25th-hour.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2026/03/25th-hour.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">SPAs Are a Performance Dead End</title><link href="https://www.yegor256.com/2026/01/25/spa-vs-performance.html" rel="alternate" type="text/html" title="SPAs Are a Performance Dead End" /><published>2026-01-25T00:00:00+00:00</published><updated>2026-01-25T00:00:00+00:00</updated><id>https://www.yegor256.com/2026/01/25/spa-vs-performance</id><content type="html" xml:base="https://www.yegor256.com/2026/01/25/spa-vs-performance.html"><![CDATA[<p>It seems to be <a href="https://adamsilver.io/blog/the-problem-with-single-page-applications/">popular</a> to design websites as Single Page Applications (SPA).
Instead of showing a new HTML page on every click, an SPA sends a lightweight skeleton with JavaScript.
The JS makes HTTP requests, receives JSON, and injects data into the DOM.
On each user action, the page doesn’t reload—only the DOM changes.
Such an architecture, once a response to slow browsers and unreliable networks, is now a <a href="https://www.matuzo.at/blog/2023/single-page-applications-criticism/">bottleneck</a>.
The page is built of fragments, each requiring its own HTTP request.
No matter how fast each request is, the multiplication diminishes all optimization efforts.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Bitter Moon (1992) by Roman Polanski" src="/images/2026/01/bitter-moon.jpg" longdesc="#5f60766e" /><figcaption id="5f60766e">Bitter Moon (1992) by Roman Polanski</figcaption></figure>

<p>In 2000, <a href="https://en.wikipedia.org/wiki/Roy_Fielding">Roy Fielding</a>, the author of <a href="https://en.wikipedia.org/wiki/REST">REST</a> and co-author of <a href="https://en.wikipedia.org/wiki/HTTP">HTTP</a>, described the Web in his <a href="https://roy.gbiv.com/pubs/dissertation/fielding_dissertation.pdf">dissertation</a>:</p>

<blockquote>
  <p>A network of web pages, where the user progresses through the application
by selecting links, resulting in the next page being transferred
to the user and rendered for their use.</p>
</blockquote>

<p>Simply put, each action leads to an HTML page reload.</p>

<p>In 1999, Microsoft introduced <a href="https://en.wikipedia.org/wiki/XMLHttpRequest">XMLHttpRequest</a> for <a href="https://en.wikipedia.org/wiki/Outlook_on_the_web">Outlook Web Access</a>, enabling background HTTP requests.
In 2005, <a href="https://en.wikipedia.org/wiki/Jesse_James_Garrett">Jesse James Garrett</a> coined the term <a href="https://en.wikipedia.org/wiki/Ajax_(programming)">AJAX</a> in his essay “<a href="https://designftw.mit.edu/lectures/apis/ajax_adaptive_path.pdf">Ajax: A New Approach to Web Applications</a>.”
This came in handy when full page reloads stopped working well:</p>

<ul>
  <li>Browsers were slow</li>
  <li>Networks were unreliable</li>
  <li>Full page reloads felt wasteful</li>
  <li>Users expected “desktop-like” interactivity</li>
</ul>

<p><em>AJAX</em> paved the way for the <a href="https://en.wikipedia.org/wiki/Single-page_application">SPA</a>: instead of HTML, the server sends <a href="https://en.wikipedia.org/wiki/JSON">JSON</a>, and the browser reconstructs the page locally.
Then came the frameworks: <a href="https://angular.io/">Angular</a> (2010), <a href="https://react.dev/">React</a> (2013), <a href="https://vuejs.org/">Vue</a> (2014).
Each formalizes the same idea: the browser hosts the application, the server delivers data.</p>

<p>Imagine a simple online calculator where a user enters “2+3,” clicks “Submit,” and sees the result right next to the input field.
No page reload.
The <a href="https://en.wikipedia.org/wiki/Document_Object_Model">DOM</a> remains the same.
The JS inside the browser changes only the result of calculation, in a single <code class="language-plaintext highlighter-rouge">&lt;div/&gt;</code>.</p>

<p>The primary justification for this architecture is <em>performance</em>.
If servers are slow, rendering a full HTML page takes longer than just a JSON with the result of calculation.
If the network is unreliable, re-delivering the entire HTML takes longer than just a small JSON document.
Also, if browsers are slow, making a tiny change in the DOM works faster than a full page reload.</p>

<p>This is true, for a trivial example.
However, when an SPA gets larger, the frontend has to make <em>dozens of round-trips</em> to the backend.
Look at what Facebook and LinkedIn are doing while rendering your home page.
A rather simple UI with just a list of recent posts gets filled up by multiple pieces, each leading to its own HTTP request,
  sometimes taking more than a few seconds to complete rendering a page.
Their UX sucks, if you ask me.</p>

<p>Their architects are stupid?
Nope.</p>

<p>The very idea of SPA is flawed.
The architects of Facebook and LinkedIn are the hostages of it.
They can’t make their websites run faster, because they, by design, are built of fragments retrievable from the backend.
They must make <em>multiple</em> HTTP round-trips.</p>

<p>The performance penalty of SPAs is structural, not accidental.
Even if HTTP/2 <a href="https://stackoverflow.com/questions/36835972/is-the-per-host-connection-limit-raised-with-http-2/36847527#36847527">multiplexes</a> requests, the UI still waits for JSON to arrive in order—classic
  <a href="https://en.wikipedia.org/wiki/Head-of-line_blocking">head-of-line blocking</a> at the application layer.
Worse, one request often reveals permissions, feature flags, or entity identifiers needed for the next, turning parallel calls into a waterfall.
Caching doesn’t help either: dozens of endpoints, each with its own TTL, rarely produce a full cache hit,
  and partial hits still force the browser to assemble and reconcile the page at runtime
Meanwhile, the browser must juggle layout stabilization, loading indicators, and partial failures—all before meaningful content becomes visible.</p>

<p>What was once a solution for small DOM updates, in an era of slow browsers and unreliable networks, has turned into a dead-end for web design.</p>

<aside class="quote">State belongs on the server while HTML is the primary delivery artifact, not JSON
</aside>

<p>Most web architects simply can’t make their websites as fast as <a href="https://stackoverflow.com/">Stack Overflow</a>, which is not an SPA.
It delivers the entire HTML page, <a href="https://scaleyourapp.com/svelte-at-stack-overflow/">rendered</a> on the server using <a href="https://en.wikipedia.org/wiki/ASP.NET_Razor">Razor</a>, in one <a href="https://highscalability.com/stackoverflow-update-560m-pageviews-a-month-25-servers-and-i/">&lt;50ms</a> request.
It does use client-side JS components selectively, but these are isolated and don’t negate the central role of server HTML for the initial experience.
Their UX is one of the best on the modern web, if you ask me.</p>

<p>Rendering a full page on the server may still be a slow operation.
It may, and it often will.
However, this problem is <em>solvable</em>, for example, with the help of caching.
The server is in charge of the data and the state of navigation, making caching possible.</p>

<p>Literally every large, content-heavy, consumer-facing SPA I can think of is horrible in terms of UX.
Even <a href="https://gmail.com">Gmail</a> is not an exception.
Their UX would be noticeably better if they followed the principles of Roy Fielding and reloaded the page every time an email is opened.
I’m not kidding.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="mood" /><summary type="html"><![CDATA[Single Page Applications, once a solution for slow browsers, are now a performance bottleneck due to multiple HTTP round-trips.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2026/01/bitter-moon.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2026/01/bitter-moon.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Comments Considered Harmful in the Age of LLMs</title><link href="https://www.yegor256.com/2026/01/11/no-documentation-comments.html" rel="alternate" type="text/html" title="Comments Considered Harmful in the Age of LLMs" /><published>2026-01-11T00:00:00+00:00</published><updated>2026-01-11T00:00:00+00:00</updated><id>https://www.yegor256.com/2026/01/11/no-documentation-comments</id><content type="html" xml:base="https://www.yegor256.com/2026/01/11/no-documentation-comments.html"><![CDATA[<p>Writing code documentation is a pain.
Not writing it leads to even bigger pain—we can’t comprehend the code.
However, writing it and then forgetting to update it causes the ultimate pain: it lies and confuses us.
How about we cure all three pains at once: <em>prohibit all comments!</em>
How do we know what the intent of the code is if we don’t have any comments?
We ask an LLM to explain it to us.
What if the LLM fails to explain and confesses its inability?
Then, we automatically fail the build and blame the author of the code.
Thus, we introduce a new quality gate: <em>Code Interpretability Score</em>.
The build passes only if this score is high enough.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Full Metal Jacket (1987) by Stanley Kubrick" src="/images/2026/01/full-metal-jacket.jpg" longdesc="#dc7c81cb" /><figcaption id="dc7c81cb">Full Metal Jacket (1987) by Stanley Kubrick</figcaption></figure>

<p>The best minds in software engineering have long dreamed of self-documenting code.
In 1974, <a href="https://en.wikipedia.org/wiki/Brian_W._Kernighan">Brian Kernighan</a> and <a href="https://en.wikipedia.org/wiki/P._J._Plauger">Phillip James Plauger</a> <a href="https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style">said</a> that
  “the only reliable documentation of a computer program is the code itself.”
In 2004, <a href="https://en.wikipedia.org/wiki/Steve_McConnell">Steven McConnell</a> in <a href="https://amzn.to/2cs4cXW"><em>Code Complete</em></a> claimed that
  “the main contributor to code-level documentation isn’t comments, but good programming style.”
In 2008, <a href="https://en.wikipedia.org/wiki/Robert_C._Martin">Robert Martin</a> in <a href="https://amzn.to/2m7LmaA"><em>Clean Code</em></a> suggested that
  “if our programming languages were expressive enough, or if we had the talent to subtly wield those languages to express our intent,
  we would not need comments very much—perhaps not at all.”
They all wanted the same thing: code that explains itself.
They just lacked the tools to enforce it.</p>

<p>Why do we write comments at all?
A Java method of a hundred lines may take hours to understand.
A tiny Javadoc block saves this time:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
 * Recursively finds the shortest
 * path between two nodes in the graph.
 */</span>
<span class="kt">int</span><span class="o">[]</span> <span class="nf">shortest</span><span class="o">(</span><span class="kt">int</span><span class="o">[][]</span> <span class="n">g</span><span class="o">,</span> <span class="kt">int</span> <span class="n">a</span><span class="o">,</span> <span class="kt">int</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
  <span class="c1">// A hundred lines of code go</span>
  <span class="c1">// here, which we have no desire</span>
  <span class="c1">// to read and understand.</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Comments promise to help us but fail in two distinct ways.</p>

<p>First, they are <em>unclear</em>.
<a href="https://en.wikipedia.org/wiki/David_Parnas">David Parnas</a> once <a href="https://doi.org/10.1109/icse.1994.296790">said</a> that
  “documentation that seems clear and adequate to its authors is often about <em>as clear as mud</em> to the
  programmer who must maintain the code six months or six years later.”
What the author considers obvious, the reader finds cryptic.</p>

<p>Second, they <em>decay</em>.
Being static metadata, comments do not evolve automatically with the code.
If the implementation of the <code class="language-plaintext highlighter-rouge">shortest()</code> function stops being recursive, we may forget to update the Javadoc block.
Such negligence leads to <em>hallucinating documentation</em> that causes bugs, broken trust, and wasted debugging time.
In 1999, <a href="https://en.wikipedia.org/wiki/Andy_Hunt_(author)">Andrew Hunt</a> and <a href="https://en.wikipedia.org/wiki/Dave_Thomas_(programmer)">Dave Thomas</a> in <a href="https://en.wikipedia.org/wiki/The_Pragmatic_Programmer"><em>The Pragmatic Programmer</em></a> warned that
  “<em>untrustworthy</em> comments are <em>worse</em> than no comments at all.”
A recent <a href="https://doi.org/10.1145/3663529.3664458">analysis</a> of 13 open source projects
  demonstrated that out-of-date comments are not rare but common.</p>

<p>Now we have a tool that solves both problems: the LLM.</p>

<p>Instead of writing the Javadoc block manually, we let the IDE generate it on-demand.
The LLM reads the hundred lines of code, comprehends it, and summarizes the intent in a single English sentence.
Modern models accomplish this task better than most humans.
The documentation is always fresh because it is generated from the current code, not from a stale comment written months ago.</p>

<p>But we can go further.
We can integrate an LLM into the build pipeline and ask it to assess the <em>Code Interpretability Score</em> (CIS) of every function.
If the model has low confidence in explaining the logic, this signals that the code is too clever or convoluted.
The compiler can enforce a threshold: if the CIS is too low, the build fails.
This transforms readability from a subjective preference into an objective, measurable quality gate.</p>

<p>Once this gate exists, manual comments become not just unnecessary but <em>harmful</em>.
They introduce a second source of truth that can contradict the code.
The logical conclusion: prohibit them entirely.
This forces developers to write clean, structured logic that is inherently machine-interpretable.</p>

<p>Robert Martin wished for more expressive languages.
He didn’t know about LLMs.
Today, we don’t need better languages—we need an LLM that can interpret any language.
If the LLM can’t explain the code, we blame the programmer and stop the build.</p>

<hr />

<p>We are thinking about making <a href="https://www.eolang.org">EO</a>, our experimental object-oriented language, this restrictive.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="quality" /><summary type="html"><![CDATA[Instead of writing code comments that decay and mislead, let LLMs generate documentation on-demand and fail the build when code is too obscure for them to explain.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2026/01/full-metal-jacket.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2026/01/full-metal-jacket.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The Fall of JavaScript</title><link href="https://www.yegor256.com/2025/12/28/fall-of-javascript.html" rel="alternate" type="text/html" title="The Fall of JavaScript" /><published>2025-12-28T00:00:00+00:00</published><updated>2025-12-28T00:00:00+00:00</updated><id>https://www.yegor256.com/2025/12/28/fall-of-javascript</id><content type="html" xml:base="https://www.yegor256.com/2025/12/28/fall-of-javascript.html"><![CDATA[<p>In 1995, <a href="https://github.com/BrendanEich">Brendan Eich</a> was hired by <a href="https://en.wikipedia.org/wiki/Netscape">Netscape</a> and asked to create a language for their HTML browser.
Rumors say, he designed Mocha in <a href="https://exploringjs.com/es5/ch04.html">10 days</a>, later renamed to <a href="https://stackoverflow.com/questions/2018731">LiveScript</a>, and then to <a href="https://en.wikipedia.org/wiki/JavaScript">JavaScript</a>.
It was <a href="https://brendaneich.com/2008/04/popularity/">planned</a> to make it similar to <a href="https://www.scheme.org/">Scheme</a>, a LISP-syntax language.
Instead, to <a href="https://brendaneich.com/2008/04/popularity/">please</a> the crowd of C++/Java coders, it was made syntactically similar to Java.
In 2008, Brendan made a tragic mistake: he <a href="https://www.theguardian.com/technology/2014/apr/02/controversial-mozilla-ceo-made-donations-right-wing-candidates-brendan-eich">donated</a> $1,000 in support of Californian anti-gay marriage <a href="https://en.wikipedia.org/wiki/2008_California_Proposition_8">law</a>.
In 2014, he joined <a href="https://www.mozilla.org/">Mozilla</a> as a CEO and the crowd <a href="https://www.cbc.ca/news/science/okcupid-protests-new-mozilla-ceo-s-anti-gay-marriage-donation-1.2593629">remembered</a> his anti-diversity gesture.
He had to <a href="https://blog.mozilla.org/en/mozilla/brendan-eich-steps-down-as-mozilla-ceo/">step down</a> and founded Brave Software, the developer of the <a href="https://brave.com/">Brave</a> browser.
Somewhere around that time they started to kill JavaScript.
Still doing it pretty good, thanks to recent <a href="https://en.wikipedia.org/wiki/ECMAScript">ECMAScript</a> updates and <a href="https://www.typescriptlang.org/">TypeScript</a>.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Platoon (1986) by Oliver Stone" src="/images/2025/12/platoon.jpg" longdesc="#aeacd232" /><figcaption id="aeacd232">Platoon (1986) by Oliver Stone</figcaption></figure>

<p>In the JavaScript created 30 years ago, objects were primitive associative arrays of properties.
Either data, a function, or another object may be attached to a property of an object.
Let’s see what Brendan <a href="https://brendaneich.com/2008/04/popularity/">said</a> about JS in 2008:</p>

<blockquote>
  <p>I’m happy that I chose Scheme-ish first-class functions and Self-ish prototypes as the main ingredients.</p>
</blockquote>

<p>First-class functions mean that it’s possible to use a function as a value assignable to a variable.
And then he <a href="https://brendaneich.com/2008/04/popularity/">concluded</a> (pay attention, it’s C not C++):</p>

<blockquote>
  <p>Yet many curse it, including me. I still think of it as a quickie love-child of C and Self.</p>
</blockquote>

<p><a href="https://selflanguage.org/">Self</a>, which he refers to a few times, is a prototype-based object-oriented language
  designed by <a href="https://en.wikipedia.org/wiki/David_Ungar">David Ungar</a> and <a href="https://www.linkedin.com/in/randallsmith1/">Randall Smith</a> in <a href="https://en.wikipedia.org/wiki/PARC_(company)">Xerox PARC</a>, then <a href="https://www.stanford.edu/">Stanford University</a>, and then <a href="https://en.wikipedia.org/wiki/Sun_Microsystems">Sun Microsystems</a>.
Self doesn’t have classes, unlike Java or C++.
Instead, it only has objects.
To create a new object in Self we make a copy of an existing object, known as prototype, and then modify some of its slots (attributes).</p>

<p>In Self, objects don’t have types: all method calls are dispatched in runtime.
For example, we ask a book to rename itself:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>book rename: "Object Thinking".
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">rename</code> is the method of the <code class="language-plaintext highlighter-rouge">book</code> that we call with a single string argument.
The computer doesn’t know anything about the <code class="language-plaintext highlighter-rouge">book</code> until it’s time to call the <code class="language-plaintext highlighter-rouge">rename</code> method.
Obviously, such a <a href="https://en.wikipedia.org/wiki/Duck_typing">duck typing</a> has its performance drawback.
Every <code class="language-plaintext highlighter-rouge">rename</code> leads to a search in a <a href="https://en.wikipedia.org/wiki/Dispatch_table">virtual table</a> of <code class="language-plaintext highlighter-rouge">book</code>.
To the contrary, C++, where types are known in compile time, can dispatch <code class="language-plaintext highlighter-rouge">rename()</code> instantly:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Book b;
b.rename("Object Thinking");
</code></pre></div></div>

<p>Types (classes in C++ and interfaces in Java) and <a href="/2025/08/17/type-annotations.html">type annotations</a> are helpful—to the compiler.
To us humans they are a burden.
They require us to do the work of the compiler.
We have to pollute our code with messages like: “This object <code class="language-plaintext highlighter-rouge">b</code> is of type <code class="language-plaintext highlighter-rouge">Book</code>, please remember.”
The compiler must be smart enough to understand it without our hints.</p>

<p>This is a debatable topic though.
Some believe that type annotations help programmers better understand the code and make fewer mistakes.
I’m also in favor of fewer mistakes, but would rather expect the compiler to infer types automatically, without my annotations.
If I do <code class="language-plaintext highlighter-rouge">b.rename()</code> and <code class="language-plaintext highlighter-rouge">b</code> is known to be a car instead of a book, I would expect the compiler to figure this out on its own and refuse to compile.</p>

<p>Anyway, JavaScript was designed as a prototype-based dynamically typed language with a minimalistic syntax that resembles Java.
It worked perfectly fine until the industry decided to “fix” it.</p>

<aside class="quote">JavaScript worked perfectly fine until the industry decided to fix it
</aside>

<p>In 2008, <a href="https://www.mozilla.org/">Mozilla</a> and others <a href="https://auth0.com/blog/the-real-story-behind-es4/">proposed</a> ECMAScript 4, which included classes, modules, and other features.
<a href="https://www.microsoft.com/">Microsoft</a> took an <a href="https://www.theregister.com/2008/08/15/adobe_microsoft_ecma_javascript/">extreme position</a>, refusing to accept any part of ES4.
Chris Wilson, Microsoft’s Internet Explorer platform architect, <a href="https://www.theregister.com/2008/08/15/adobe_microsoft_ecma_javascript/">criticized</a> ES4 for trying to introduce too many changes.
Brendan Eich <a href="https://www.theregister.com/2008/08/15/adobe_microsoft_ecma_javascript/">accused</a> Wilson of spreading falsehoods and playing political games.
ES4 was <a href="https://auth0.com/blog/the-real-story-behind-es4/">abandoned</a>, and classes were dropped.</p>

<p>Then, in 2012, Microsoft created <a href="https://www.typescriptlang.org/">TypeScript</a>, a JavaScript with type annotations and classes.
Since classes weren’t in the standard, Microsoft made their own.</p>

<p>Finally, in 2015, <a href="https://262.ecma-international.org/6.0/">ECMAScript 6</a> added classes (among other features) to the JavaScript specification.
Many ES4 features, including classes, were <a href="https://auth0.com/blog/the-real-story-behind-es4/">revived</a> in a “maximally minimal” form.
The crowd of Java/C++ developers got what they wanted.</p>

<p>Let’s hear what <a href="https://www.crockford.com/pronto.html">Douglas Crockford</a>, the creator of <a href="https://en.wikipedia.org/wiki/JSON">JSON</a> and <a href="https://github.com/jslint-org/jslint">JSLint</a>, <a href="https://www.youtube.com/watch?v=PSGEjv3Tqo0&amp;t=360s">said</a> in 2014:</p>

<blockquote>
  <p>Class-free programming is JavaScript’s contribution to humanity.</p>
</blockquote>

<p>Unfortunately, not anymore.
It looks like the developers of recent versions of JS believe in something else.
Or maybe they don’t want to make a contribution to humanity anymore.
Maybe they just want to make the crowd happy.</p>

<p>Type annotations and classes don’t match with the concept of class-free object-based programming of JavaScript.
They came from Java or C++ but don’t fit in.
Some programmers may find them helpful, but only because they are used to seeing them in other languages.
JavaScript is not Java, even though the names look similar.</p>

<p>Java, with its
  <a href="/2016/09/20/oop-without-classes.html">classes</a>,
  <a href="/2016/09/13/inheritance-is-procedural.html">implementation inheritance</a>,
  and
  <a href="/2014/05/05/oop-alternative-to-utility-classes.html">static methods</a>,
  is OOP for dummies.
It’s object-oriented programming for those who, according to <a href="https://www.youtube.com/watch?v=PSGEjv3Tqo0&amp;t=360s">Douglas Crockford</a>, don’t know what
  <a href="/2016/08/15/what-is-wrong-object-oriented-programming.html">object-oriented programming</a> is.
JavaScript, on the other hand, is a member of conceptually solid OO languages, like <a href="https://en.wikipedia.org/wiki/Smalltalk">Smalltalk</a> and Self.
Blending Java flavors into JavaScript only ruins the flavor of the latter.</p>

<p>It’s sad to see how a once straight object-centric language paradigm turned into a diversity of unmatchable and suboptimal features.</p>

<p>P.S. JavaScript is still a great language if you ignore classes and type annotations.
When I write in JavaScript, I don’t use them.
Look at the code in the <a href="https://github.com/yegor256/jo">yegor256/jo</a> repository.
It illustrates the <a href="/junior-objects.html">Junior Objects</a> book of mine.
I’m proud of this code.</p>

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">“People using classes in JavaScript will go to their graves never knowing how miserable they were” - Douglas Crockford <a href="https://t.co/D2Hpegn0vY">https://t.co/D2Hpegn0vY</a></p>&mdash; Yegor Bugayenko (@yegor256) <a href="https://twitter.com/yegor256/status/2010297169899913568?ref_src=twsrc%5Etfw">January 11, 2026</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="oop" /><summary type="html"><![CDATA[JavaScript was an elegant prototype-based class-free language until TypeScript and ES6 classes ruined it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2025/12/platoon.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2025/12/platoon.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">You Are the Low-Hanging Fruit</title><link href="https://www.yegor256.com/2025/11/30/internal-vs-external-obstacles.html" rel="alternate" type="text/html" title="You Are the Low-Hanging Fruit" /><published>2025-11-30T00:00:00+00:00</published><updated>2025-11-30T00:00:00+00:00</updated><id>https://www.yegor256.com/2025/11/30/internal-vs-external-obstacles</id><content type="html" xml:base="https://www.yegor256.com/2025/11/30/internal-vs-external-obstacles.html"><![CDATA[<p>Let’s say, you are a startup founder, like <a href="https://www.zerocracy.com">myself</a>.
Try to hire a sales guy.
Offer him a commission-only payment scheme.
Listen to his reaction: he will demand that you pay a fixed salary too, on top of commission.
Try to convince him that commission-only is a more reasonable and <a href="/2014/09/24/why-monetary-awards-dont-work.html">motivating</a> setup.
Goto 1.
After a number of iterations you realize that the mission is impossible.
Sales people are good at selling and the best thing they sell is the idea that their <em>time</em> must be compensated.
Even if they don’t sell the product to your customers.
If you don’t buy the idea, they go find another loser who will.
Something similar happens when you try to pay programmers by result.
They easily convince you to pay for <a href="/2015/07/21/hourly-pay-modern-slavery.html">their time</a>.
And you do.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="City of God (2002) by Kátia Lund" src="/images/2025/11/city-of-god.jpg" longdesc="#1e31b0ff" /><figcaption id="1e31b0ff">City of God (2002) by Kátia Lund</figcaption></figure>

<p>A sales rep doesn’t know how to write code.
Most of them don’t even know how computers work.
However, he <em>perfectly</em> knows how to bullshit people.
That’s exactly why we need him.
Because we don’t know how to bullshit people and we don’t want to learn it.</p>

<p>Now, two strategies lie in front of him.
He can use the skill against the prospects on the market and turn them into paying customers.
He can also use the same selling skill against you, the owner of the startup.
Instead of selling the product to the market he can sell <em>himself</em> to you.
He can sell the idea that even if he fails to sell the product to the customers he still deserves a decent weekly paycheck.</p>

<p>What do you think, which sale is easier to make?
What would you do in his shoes?
The answer is obvious.
The customers are far away and they have no mercy.
If they don’t like the offer, they simply hang up on him and that’s it.
You, on the other hand, sit next to him in the same office and can’t hang up.
You are the <em>low-hanging fruit</em>.
You are the <em>weakest</em> prey he can reach out to.</p>

<aside class="quote">In order to make him focus on external obstacles, you should make internal ones harder to overcome
</aside>

<p>A customer is an <em>external</em> obstacle that he must overcome in order to get paid, as a sales commission.
You are an <em>internal</em> obstacle, which he may also overcome to get a fixed weekly payment.
You need him to fight the external obstacle.
However, he is free to choose the <em>easiest</em> path.</p>

<p>In order to make him focus on external obstacles, you should make internal ones <em>harder</em> to overcome.
Joseph Stalin once <a href="https://www.goodreads.com/quotes/338750-in-the-soviet-army-it-takes-more-courage-to-retreat">said</a> that “in the Soviet army it takes more courage to retreat than advance.”
This war-time concept seems relevant to the sales guys you hire.
It must be harder for them to talk you into paying them a fixed salary than to convince a prospect to buy your product.</p>

<p>Emotionally, for you it may be rather challenging to constantly push him back.
Just like it’s often hard to say “No” to a vagrant begging for a dollar at the corner.
Beggars, unless they are physically disabled, also, just like sales people, have two possible life strategies.
Either find a job or beg at the corner.
The begging strategy, for the vagrant and for the sales rep, is <em>easier</em> to pursue.</p>

<p>Programmers are not much different.
They also have two strategies.
They can solve technical problems by merging qualified pull requests.
They can also persuade you that you must pay for their time, not their pull requests.
Which obstacle is going to be harder for them to overcome depends on <em>you</em>.</p>

<p>First, you set up a formula for measuring their contribution.
Second, you bind their paychecks to it: they get paid <a href="/2016/05/24/who-is-project-manager.html">not by you</a>,
  but by <em>merged pull requests</em>.
Finally, you taboo the very possibility of discussing time-based compensation.</p>

<aside class="quote">Taboo the very possibility of discussing time-based compensation
</aside>

<p>What you get is a technical team focused on resolving external problems.
The team will <em>advance</em> because it will be <a href="/2018/07/24/bugs-or-pull-requests.html">pointless</a> to <em>retreat</em>.
You simply <a href="/2015/07/21/hourly-pay-modern-slavery.html">won’t pay</a> them for their time.
No matter how many times they repeat “I was working hard the entire weekend.”</p>

<p>Incentives shape behavior.
If you reward excuses, you buy excuses.
If you reward results, you get results.
As a founder, your job is to eliminate the temptation for your team to <a href="/2019/07/10/inversive-management.html">sell you</a>
  anything other than tangible artifacts.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="management" /><summary type="html"><![CDATA[Sales reps and programmers can either fight external obstacles to earn their pay, or convince you, the founder, to pay for their time regardless of results; make the internal path harder.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2025/11/city-of-god.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2025/11/city-of-god.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Small Repo, High Quality</title><link href="https://www.yegor256.com/2025/11/16/smaller-repository-higher-quality.html" rel="alternate" type="text/html" title="Small Repo, High Quality" /><published>2025-11-16T00:00:00+00:00</published><updated>2025-11-16T00:00:00+00:00</updated><id>https://www.yegor256.com/2025/11/16/smaller-repository-higher-quality</id><content type="html" xml:base="https://www.yegor256.com/2025/11/16/smaller-repository-higher-quality.html"><![CDATA[<p>I don’t like <a href="/2018/09/05/monolithic-repositories.html">monolithic repositories</a>.
They keep multiple projects together, often written in different languages, by different teams.
Unfortunately, <a href="https://dl.acm.org/doi/pdf/10.1145/2854146">Google</a>, <a href="https://engineering.fb.com/2025/10/16/developer-tools/branching-in-a-sapling-monorepo/">Facebook</a>, and <a href="https://shiftmag.dev/mono-repo-infrastructure-yandex-1011/">Yandex</a> favor them.
Primarily, according to them, <a href="https://monorepo.tools/">monorepos</a> reduce integration <a href="https://www.sonarsource.com/resources/library/monorepo/">overhead</a>.
They do, but at the cost of quality.
In smaller repositories we can develop better code.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Морфий (2008) by Алексей Балабанов" src="/images/2025/11/morphine.jpg" longdesc="#04b3173e" /><figcaption id="04b3173e">Морфий (2008) by Алексей Балабанов</figcaption></figure>

<p>When a repository is smaller you can achieve higher quality, for a number of reasons:</p>

<ul>
  <li>
    <p><strong>You can be stricter on style.</strong>
It’s easier to keep a thousand lines consistently formatted than a million.
With a thousand lines, you can configure <a href="https://eslint.org/">ESLint</a> to its maximum, enabling as many rules as you can find.
Stricter <a href="/2014/08/13/strict-code-quality-control.html">control</a> over code stylistics leads to cleaner code.</p>
  </li>
  <li>
    <p><strong>You can write deeper tests.</strong>
Integration (or <a href="/2023/08/22/fast-vs-deep-testing.html">deep</a>) tests are inevitably slow.
In a smaller repository, a good integration test coverage doesn’t mean a slow build.
In a larger repository—it does.
A slow build is something a team tries to avoid, thus jeopardizing the coverage.</p>
  </li>
  <li>
    <p><strong>You can review more pedantically.</strong>
In a larger repository it may be harder to remember all the aspects of design.
A pull request that affects different seemingly unrelated code parts
may be a challenge to <a href="/2015/02/09/serious-code-reviewer.html">review</a>.
Even if you are the <a href="/2014/10/12/who-is-software-architect.html">architect</a>.</p>
  </li>
  <li>
    <p><strong>You can write a README.</strong>
Maybe you have noticed already: large open source projects have short and sketchy <a href="/2019/04/23/elegant-readme.html">README</a> files.
They can’t make them much longer without them becoming as large as a book.
All they can do is redirect the reader to the documentation website.
The inability to explain the entire scope in a single file leads to scope creep.
Contributors struggle to understand the borders of the project.
This leads, among other bad things, to code duplication.</p>
  </li>
  <li>
    <p><strong>You can release frequently.</strong>
In a larger repository, frequent reintegration may be expensive, in both time and money.
In a small repo, a <a href="/2025/04/12/four-builds.html">build</a> of a few seconds is not a dream of programmers, it’s their reality.
Not only CI is cheap, but also CD.
After every small change you can publish a new release, with its own <a href="https://semver.org/">version</a>.
In a monorepo, we tend to wait until a portion of changes accumulate.</p>
  </li>
  <li>
    <p><strong>You can use AI agents effectively.</strong>
It is no secret that modern LLMs have limited <a href="https://docs.claude.com/en/docs/build-with-claude/context-windows">context windows</a>.
A million lines of code can’t fit into even the largest of them.
Even ten thousand lines, let alone a million, is more than an LLM can digest.
By keeping a repository small we do a big favor to our little friends: AI agents.</p>
  </li>
  <li>
    <p><strong>You can on-board faster.</strong>
Larger codebases are usually older and more <a href="/2018/09/12/clear-code.html">chaotic</a>, full of legacy code.
It takes longer to start making meaningful contribution to such a repository.
Monorepos attract
<a href="/2015/12/29/turnover-is-good-for-maintainability.html">long-term</a>
<a href="/2017/05/02/remote-slaves.html">office-based</a>
contributors
who care about job security more than about code quality.</p>
  </li>
  <li>
    <p><strong>You can expect responsibility.</strong>
In larger codebases, the very idea of code ownership is hard to maintain.
Programmers can hardly feel responsible for the code written and modified by others.
Smaller repositories, on the other hand, emotionally attach people to code.</p>
  </li>
  <li>
    <p><strong>You can go open source.</strong>
No matter how much your boss <a href="/2020/05/05/open-source-arms-race.html">loves</a>
open source, you can’t put your entire enterprise monorepo on GitHub.
However, if you extract a small part of it, you can.
The code that is open, visible and criticized by many people,
is <a href="/2015/12/22/why-dont-you-contribute-to-open-source.html">allegedly</a> of a higher quality.</p>
  </li>
</ul>

<p>In summary, you should look for an opportunity to extract a piece of code as a standalone package.
Then, insist on making it <a href="/2017/05/30/why-contribute-to-open-source.html">open source</a>.
Then, promote it in the community.
Then, quit your office job and join <a href="https://www.zerocracy.com">Zerocracy</a>.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="oss" /><summary type="html"><![CDATA[By breaking your software into small open-source packages, you make the entire product easier to maintain—and significantly higher in quality.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2025/11/morphine.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2025/11/morphine.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Can’t Merge? Don’t Despair.</title><link href="https://www.yegor256.com/2025/11/09/help-me-cant-merge.html" rel="alternate" type="text/html" title="Can’t Merge? Don’t Despair." /><published>2025-11-09T00:00:00+00:00</published><updated>2025-11-09T00:00:00+00:00</updated><id>https://www.yegor256.com/2025/11/09/help-me-cant-merge</id><content type="html" xml:base="https://www.yegor256.com/2025/11/09/help-me-cant-merge.html"><![CDATA[<p>You’ve made a pull request, but it won’t merge.
A reviewer says it’s not good or the tests don’t pass.
No matter what, you can’t get it into the master branch.
You keep fixing the branch, keep convincing the reviewer, keep hating the tests.
Stop.
Try <em>smarter</em> tactics.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Amores Perros (2000) by Alejandro González Iñárritu" src="/images/2025/11/amores-perros.jpg" longdesc="#d0b0373b" /><figcaption id="d0b0373b">Amores Perros (2000) by Alejandro González Iñárritu</figcaption></figure>

<h2 id="1-give-up-instantly">1. Give Up Instantly</h2>

<p>First, <a href="https://en.wikipedia.org/wiki/Fail_fast">fail fast</a>.
Give up quickly.
If it doesn’t go through smoothly, <em>close it</em>.
If the reviewers’ complaints are more than stylistic issues, your understanding of the architecture is flawed.</p>

<p>Ask yourself, how did this happen?
Why did you, a smart programmer, get a wrong understanding of the architecture?
Obviously, it’s <a href="/2015/02/16/it-is-not-a-school.html">not your mistake</a>.
It’s a bug in the repository.
Its <a href="/2019/04/23/elegant-readme.html">README</a> isn’t complete, its code isn’t clean enough, its documentation is outdated.</p>

<p>What do you do?
You <a href="/2025/05/25/bug-driven-development.html">blame</a> them by submitting <a href="/2014/04/13/bugs-are-welcome.html">bug reports</a>.
Then, when they fix the repository, you try again, with a new pull request.</p>

<h2 id="2-take-a-smaller-bite">2. Take a Smaller Bite</h2>

<p>Most likely they don’t complain about all the changes you’ve made.
Something looks good to them, while they refuse to accept something else.
Good, remove the bad parts from your pull request.</p>

<p>Don’t waste time trying to sell the entire package in one go.
Instead, give them as much as they’re <em>ready to accept</em>.
In the end, you will merge a few pull requests instead of one.
The more, the better, at least for us in <a href="https://www.zerocracy.com">Zerocracy</a>, where we <a href="/2018/07/24/bugs-or-pull-requests.html">reward</a> each merged pull request.</p>

<h2 id="3-blame-them-wisely">3. Blame Them Wisely</h2>

<p>This may be a defect in their existing codebase.
Pretty often it is.
Your code can’t merge, not because it’s broken, but because one of the existing tests is flaky.
This is tricky and it may get ugly.</p>

<p>Don’t get negative or frustrated.
You know that it’s not your fault.
But they don’t.
They believe that your code is defective and their code is perfect.
Moreover, all CI workflows are <a href="/2014/07/21/read-only-master-branch.html">green</a> on master, while your branch is red.
Who do we <a href="/2025/04/19/dont-merge-into-broken-master.html">blame</a>?
Obviously, you.</p>

<aside class="quote">They won’t listen if you blame them for the failure in your pull request
</aside>

<p>You have to collect <em>enough evidence</em> and submit a bug report.
It should explain what’s wrong in their master branch.
Don’t ever mention your pull request.
It’s a trap!
If you try to use your pull request as a proof of their mistakes, they won’t listen.</p>

<p>Forget about your pull request for a while.
Submit a bug report as if you were a stranger who just found a <em>bug in master</em>.</p>

<p>It may be hard, since master is green.
However, there is no other way around it.
Again, they won’t listen if you blame them for the failure in your pull request.
At best, they will explain to you the basics of continuous integration.</p>

<h2 id="4-move-on">4. Move On</h2>

<p>Just as poker fish (immature players) try to win every hand, junior developers try to merge every pull request.
This is a mistake.
Some problems simply can’t be fixed and some features can’t be implemented right now.
There will be time for them later.</p>

<p>It’s perfectly all right to <em>close</em> a pull request after a negative review.
There’s no need to feel obliged to finish it.
It’s better to spend time on easier bugs to fix and simpler functionality to implement.</p>

<h2 id="5-dont-call-for-help">5. Don’t Call for Help</h2>

<p>No matter how hard it is, don’t ask them to help you.
“I can’t understand why it doesn’t merge!”
Don’t say this.</p>

<p>They <a href="/2015/02/16/it-is-not-a-school.html">may help</a>, but it will be annoying for them.
You won’t look like a reliable programmer.
The more you ask for help, the more you ruin your reputation.
You must know how to solve issues on your own.</p>

<p>A failed PR isn’t a setback.
It’s a <em>lesson</em>.
Fail fast, blame smart, and move on stronger.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="oss" /><category term="etiquette" /><summary type="html"><![CDATA[When your pull request won’t merge, don't fight it—fail fast, split your changes, file bugs, and move on smarter.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2025/11/amores-perros.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2025/11/amores-perros.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Programmers, Don’t Use Windows!</title><link href="https://www.yegor256.com/2025/10/05/windows-vs-macos.html" rel="alternate" type="text/html" title="Programmers, Don’t Use Windows!" /><published>2025-10-05T00:00:00+00:00</published><updated>2025-10-05T00:00:00+00:00</updated><id>https://www.yegor256.com/2025/10/05/windows-vs-macos</id><content type="html" xml:base="https://www.yegor256.com/2025/10/05/windows-vs-macos.html"><![CDATA[<p>In 2020, in the <a href="/junior-objects.html">Junior Objects</a> book I wrote this:
  “<em>Windows is not suitable for programmers.
  If you meet anyone who will tell you otherwise, you must know that you deal with a bad programmer, or a poor one, which are the same things.
  Your computer has to be MacBook.</em>”
Now, five years later, I still hold the same opinion.
This blog post is supposed to be less opinionated and, because of this, more convincing.
The point is still the same: you either use Windows or you are a professional programmer.</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Das Experiment (2001) by Oliver Hirschbiegel" src="/images/2025/10/das-experiment.jpg" longdesc="#f88f9b9a" /><figcaption id="f88f9b9a">Das Experiment (2001) by Oliver Hirschbiegel</figcaption></figure>

<p>First things first.
This is what ChatGPT <a href="https://chatgpt.com/share/68e2770a-79d8-8007-96d1-3722d4d3cfcd">thinks</a> about macOS vs. Windows (I toned it down a bit and sorted by importance, keeping what matters most at the top):</p>

<ul>
  <li>It’s <a href="https://en.wikipedia.org/wiki/POSIX">POSIX</a>-compliant</li>
  <li>Tools like <code class="language-plaintext highlighter-rouge">grep</code>, <code class="language-plaintext highlighter-rouge">awk</code>, <code class="language-plaintext highlighter-rouge">sed</code>, <code class="language-plaintext highlighter-rouge">ssh</code>, and <code class="language-plaintext highlighter-rouge">make</code> work natively</li>
  <li>Proper compiler toolchain: Clang, LLVM, make, <a href="https://git-scm.com/">git</a></li>
  <li>Install everything with <a href="https://brew.sh/">HomeBrew</a>, one command away</li>
  <li>Node, Python, Ruby, Go, Java—just work without PATH hell</li>
  <li>The <a href="https://iterm2.com/">iTerm2</a> doesn’t look like it was built in 1998</li>
  <li><a href="https://www.docker.com/">Docker</a> runs faster and cleaner than on Windows</li>
  <li>SSH keys integrate smoothly with the system keychain</li>
  <li><a href="https://git-scm.com/">Git</a> behaves predictably; no <a href="https://stackoverflow.com/questions/1552749/difference-between-cr-lf-lf-and-cr-line-break-types">CRLF vs LF nightmares</a></li>
</ul>

<p>I can hear you saying:
What do I need it to be POSIX-compliant, and what is POSIX?
Why do I need <code class="language-plaintext highlighter-rouge">grep</code>, <code class="language-plaintext highlighter-rouge">sed</code>, and <code class="language-plaintext highlighter-rouge">awk</code>?
Am I a 60 years old Unix admin?
Why would I ever need <code class="language-plaintext highlighter-rouge">git</code> and <code class="language-plaintext highlighter-rouge">make</code> in the command line?
I don’t use command line at all.
I stay in the <a href="https://code.visualstudio.com/">VS Code</a> that works like a charm and helps me make a living.</p>

<p>I hear you. I do.</p>

<p>Now, hear me out.
You are not a programmer.
You look like one.
You walk like one.
You click the same buttons programmers click.
You even make the same salary they make.
But you are not one of them.
Yet.
Now, read on.</p>

<h2 id="what-is-unix">What Is Unix?</h2>

<p>Programmers are the masters of computers.
They tell machines what to do.
To simplify the task of managing a complex hardware, programmers invented a few layers of abstractions.
The first layer is an operating system.
Instead of dealing with the hard drive and the pixels on the screen directly, programmers invented files and stdout.</p>

<p>They did it in the <a href="https://en.wikipedia.org/wiki/Bell_Labs">Bell Labs</a>, during the late 1960s and early 1970s.
Earlier operating systems, like <a href="https://en.wikipedia.org/wiki/Compatible_Time-Sharing_System">CTSS</a> and <a href="https://en.wikipedia.org/wiki/OS/360_and_successors">OS/360</a>, gave them a good start.
Unix was the first OS to say that <em>everything is a file</em>, including devices, directories, sockets, and processes.
They also invented <em>pipelines</em> and the philosophy: “Write programs that do one thing well, and work together.”
They also invented <em>processes</em> and their forking mechanism.</p>

<p>Their names were <a href="https://en.wikipedia.org/wiki/Ken_Thompson">Ken Thompson</a> and <a href="https://en.wikipedia.org/wiki/Dennis_Ritchie">Dennis Ritchie</a>.</p>

<h2 id="what-is-windows">What Is Windows?</h2>

<p>Five years later, another operating system was created, with different abstractions.
Not everything was a file anymore, processes were not parallel, and there were no pipelines.
The name of the system was <a href="https://en.wikipedia.org/wiki/CP/M">CP/M</a> and the name of the inventor was <a href="https://en.wikipedia.org/wiki/Gary_Kildall">Gary Kildall</a>.
Then, five years later, 24-year-old <a href="https://en.wikipedia.org/wiki/Tim_Paterson">Tim Paterson</a> has made a copy of CP/M and called it <a href="https://en.wikipedia.org/wiki/86-DOS">86-DOS</a>.
<a href="https://www.microsoft.com/">Microsoft</a> purchased a non-exclusive license, rebranded it <a href="https://en.wikipedia.org/wiki/MS-DOS">MS-DOS</a>, and sold it to IBM.
That’s how Windows was born, in 1981.</p>

<p>Why were there no proper files, no processes, and no pipelines?
Because they weren’t trying to build a “real” operating system.
CP/M and MS-DOS were designed for tiny, single-user, single-task microcomputers, not multi-user minicomputers or mainframes.
Unix came out of Bell Labs—researchers, not hobbyists.
CP/M and MS-DOS were made for personal computers: offices and home users.
In other words, <em>MS-DOS never meant to be a proper OS</em>.
It was something that can boot up a small machine and run a single program.</p>

<p>Then, in 1985, <a href="https://en.wikipedia.org/wiki/Windows_1.0">Windows 1.0</a> was built.
It was a fancy <a href="https://en.wikipedia.org/wiki/Graphical_user_interface">GUI</a> on top of MS-DOS, not a new OS.
Later, in 1995, Microsoft introduced 32-bit APIs (<a href="https://en.wikipedia.org/wiki/Windows_API">Win32</a>) and preemptive multitasking.
However, the DOS subsystem was still lurking underneath.
Windows 95 looked modern but was still a half-DOS zombie.</p>

<p>At the same time, in 1993, the team of <a href="https://en.wikipedia.org/wiki/Dave_Cutler">Dave Cutler</a> has built <a href="https://en.wikipedia.org/wiki/Windows_NT">Windows NT</a> that was not based on DOS at all.
Latest Windows versions are descendants of NT, not MS-DOS.
Under the hood it’s conceptually closer to Unix than to CP/M.
There are features like protected memory, kernel/user separation, and file handles.
However, still it’s not Unix.</p>

<h2 id="what-is-macos">What Is macOS?</h2>

<p>In 1984, <a href="https://www.apple.com/">Apple</a> shipped their first <a href="https://en.wikipedia.org/wiki/Macintosh_128K">Macintosh</a> with the “System 1” operating system.
It was no better than MS-DOS: no multitasking, no memory protection, and primitive file system.
No surprise, it didn’t fly.</p>

<p>In 1997, Apple bought <a href="https://en.wikipedia.org/wiki/NeXT">NeXT</a> and adopted <a href="https://en.wikipedia.org/wiki/NeXTSTEP">NeXTSTEP</a> operating system.
They made it the foundation for the new <a href="https://en.wikipedia.org/wiki/MacOS">Mac OS</a>—codenamed <a href="https://en.wikipedia.org/wiki/Rhapsody_(operating_system)">Rhapsody</a>, later “Mac OS X”.</p>

<p>In 2001 they shipped Mac OS X 10.0 (“<a href="https://en.wikipedia.org/wiki/Mac_OS_X_10.0">Cheetah</a>”).
Five years later I threw away my ThinkPad with Windows and bought my first MacBook with <a href="https://en.wikipedia.org/wiki/Mac_OS_X_Leopard">Mac OS X Leopard</a>.</p>

<p>Modern macOS (Catalina, Ventura, Sequoia, etc.) is still built on that NeXT foundation.
It is POSIX-compliant and, of course, it has processes and pipelines.
In other words, it is Unix with a pretty GUI.</p>

<h2 id="abstractions">Abstractions</h2>

<p>Both Windows and macOS, in their current versions, are solid operating systems.
The difference is in the abstractions inside them: files, sockets, processes, memory blocks, users, permissions, and so on.
In Unix (macOS), everything is a <em>file</em>, while in Windows, everything is an <em>object</em>.
Files in Unix are a uniform abstraction, that’s why they can be chained via pipes.
In Windows objects are not unified in practice, they have different interfaces.</p>

<p>This is why <a href="https://en.wikipedia.org/wiki/Unix_shell">Unix shells</a> and small composable tools became so powerful.
The uniformity of “everything is a file” made composition natural.
You can build complex workflows from simple programs.</p>

<p>Windows, on the other hand, evolved around GUI apps and message loops, not shell pipelines.</p>

<h2 id="pipelines">Pipelines</h2>

<p><a href="https://en.wikipedia.org/wiki/Unix">Unix</a> was built around pipelines.
In Unix, everything is a small tool reading stdin, writing stdout.
At the same time, everything is a file, including sockets, devices, and processes.
Programmers, in Unix, see every process as a <em>composition</em> of smaller processes, glued together via pipelines.
This mindset, since 1970s, has proven to be effective, amongst a few generations of software engineering elite.</p>

<p>Say, you want to know which parts of your codebase change the most—maybe for refactoring, testing focus, or bug-hotspot analysis.
This is how you do it Unix-style:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git log <span class="nt">--pretty</span><span class="o">=</span>format: <span class="nt">--name-only</span> | <span class="se">\</span>
  <span class="nb">grep</span> <span class="s1">'\.java$'</span> | <span class="se">\</span>
  <span class="nb">sort</span> | <span class="se">\</span>
  <span class="nb">uniq</span> <span class="nt">-c</span> | <span class="se">\</span>
  <span class="nb">sort</span> <span class="nt">-nr</span> | <span class="se">\</span>
  <span class="nb">head</span> <span class="nt">-20</span>
</code></pre></div></div>

<p>Does this syntax make sense to you?
If it does, I bet you use <a href="https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux">WSL</a>.
Most serious Windows developers end up doing exactly that.</p>

<p>The command line is the bare metal interface to Unix.
The heart of the command line is pipelines.
Thanks to pipelines, command-line tools are inherently composable.
You can chain them and automate tasks in seconds that would take hours by hand.
No <a href="https://en.wikipedia.org/wiki/Integrated_development_environment">IDE</a> plugin can replace this power.</p>

<h2 id="what-are-you">What Are You?</h2>

<p>Now, you know what the difference is between Windows and macOS.
In both of them you can code, browse Internet, and watch movies.
However, in macOS you interact with the computer through Unix abstractions in a <a href="https://en.wikipedia.org/wiki/Unix_shell">shell</a>.
You don’t just use macOS—you inherit <em>fifty years of disciplined abstraction</em>.</p>

<p>In Windows you interact with the computer through draggable GUI elements.
A GUI makes you a consumer; a CLI makes you a creator.
A GUI hides the logic behind gestures and icons; a CLI exposes it as text you can reason about, automate, and combine.
You can’t pipe a button click into another program, you can’t grep a progress bar, and you can’t version-control a mouse movement.
Every click you make dies the moment you make it; every command you write can live forever.</p>

<p>Oh, wait.
In macOS you can’t really play games.
Bummer…
Maybe you shouldn’t, since you are a programmer?</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="mood" /><summary type="html"><![CDATA[Windows turns programmers into mouse operators. macOS, built on Unix, keeps the command line alive—where everything is a file, tools connect through pipelines, and real programmers stay in control.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2025/10/das-experiment.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2025/10/das-experiment.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Red vs. Black</title><link href="https://www.yegor256.com/2025/09/14/red-and-black.html" rel="alternate" type="text/html" title="Red vs. Black" /><published>2025-09-14T00:00:00+00:00</published><updated>2025-09-14T00:00:00+00:00</updated><id>https://www.yegor256.com/2025/09/14/red-and-black</id><content type="html" xml:base="https://www.yegor256.com/2025/09/14/red-and-black.html"><![CDATA[<p>In Soviet Russia, prisoner camps were divided into two categories: red and black.
In a red camp, the power belonged to the prisoners who cooperated with the administration and helped it maintain discipline.
In a black one, the power was in the hands of criminals who resented the rules, in permanent confrontation with the administration.
It seems that in software companies we may also categorize employees into red and black.
A <strong>red employee</strong> enjoys obeying the rules and climbs up the career ladder by <a href="/2015/01/26/happy-boss-false-objective.html">making the boss happy</a>.
To the contrary, a <strong>black employee</strong>, while understanding the inevitability, despises the necessity to obey.
Their career growth is driven by <a href="/2015/02/23/haircut.html">making the customer happy</a>.
Which one are you?</p>

<!--more-->

<figure class="jb_picture"><img itemprop="image" alt="Холодное лето пятьдесят третьего (1987) by Александр Прошкин" src="/images/2025/09/cold-summer-1953.jpg" longdesc="#ded7ba65" /><figcaption id="ded7ba65">Холодное лето пятьдесят третьего (1987) by Александр Прошкин</figcaption></figure>

<p>An organization cannot exist without policies and regulations.
Especially if it’s a large organization where the percentage of underperformers is highest.
The clock-watchers must be disciplined so that they produce at least something.
Let’s assume you are not one of them.</p>

<p>However, even if you are not a nine-to-five clock-watcher, you can’t ignore the policies.
A few examples of the rules you may need to obey:</p>

<ul>
  <li>All reports must follow the official PowerPoint template</li>
  <li>Every meeting requires written minutes sent to all participants</li>
  <li>Job candidates must pass through the full HR pipeline</li>
  <li>Employees must re-certify their skills on a fixed schedule</li>
</ul>

<p>All of the above seem reasonable—just like prison rules.
The difference is your attitude toward them.</p>

<p>They are either a <strong>framework</strong> for your career or an inevitable <strong>evil</strong>.
You either feel happy when you do what’s required, or feel annoyed and do it just because it’s required.
You either fill out all the forms completely, or you cut every possible corner to get back to the real work.
You either read an email copied to 25 people to not miss anything or immediately delete it.
You either attend all meetings or learn to be creative in finding reasons why you can’t.</p>

<p>You are either red or black.
Once you find your <strong>identity</strong>, you start despising the other side.</p>

<aside class="quote">Minimize contact, keep your head down when necessary, and focus on delivering real value where it matters
</aside>

<p>If you are red, you don’t understand the black employees who are constantly rebelling.
They rebel against the rules you so much enjoy following.
You see them as dishonest, disloyal, and selfish sociopaths.</p>

<p>If you are black, you despise the red employees who are trying so hard to associate themselves with the system.
They study the rules and compete against each other—who knows them better.
You see them as <a href="/2017/08/22/to-be-nice-or-not.html">shallow</a> and incompetent <a href="/2021/03/03/imposters-to-win.html">impostors</a>.</p>

<p>Peace is not possible.
In any large organization, reds will always dominate—it’s inevitable.
The system needs them, and they thrive inside it.
Blacks will always be a minority, surviving at the edges.</p>

<p>If you are black, don’t waste energy trying to convert or fight the reds.
You won’t win.
The only strategy is distance.
Minimize contact, keep your head down when necessary, and focus on delivering real value where it matters.
Reds will spend their lives climbing the corporate ladder.
Blacks must learn to survive in the shadows of that ladder, working for the customer, not the boss.</p>]]></content><author><name>Yegor Bugayenko</name><email>yegor256@gmail.com</email></author><category term="management" /><category term="mood" /><summary type="html"><![CDATA[In big organizations, reds obey bosses while blacks serve customers—and blacks survive only by keeping their distance.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.yegor256.com/images/2025/09/cold-summer-1953.jpg" /><media:content medium="image" url="https://www.yegor256.com/images/2025/09/cold-summer-1953.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>