<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://blog.legires.fr/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.legires.fr/" rel="alternate" type="text/html" /><updated>2026-02-11T21:42:38+00:00</updated><id>https://blog.legires.fr/feed.xml</id><title type="html">suivez le guide</title><subtitle>personal blog</subtitle><author><name>le guide</name></author><entry><title type="html">upgrade debian</title><link href="https://blog.legires.fr/2026/01/29/upgrade_debian.html" rel="alternate" type="text/html" title="upgrade debian" /><published>2026-01-29T00:00:00+00:00</published><updated>2026-01-29T00:00:00+00:00</updated><id>https://blog.legires.fr/2026/01/29/upgrade_debian</id><content type="html" xml:base="https://blog.legires.fr/2026/01/29/upgrade_debian.html"><![CDATA[<p>bon, faut upgrade debian de 12 à 13.</p>

<p>ce qui veut dire tout wipe.</p>

<p>prévoyons.</p>

<h2 id="enfermé-dehors-">enfermé dehors ?</h2>

<p>j’ai surtout peur que ça m’écrase mes settings ssh.</p>

<p>enfin bon, j’ai
<a href="https://blog.legires.fr/2024/12/11/monter_serveur.html">déjà documenté</a>
mon setup s’il faut refaire des clés.</p>

<p>et 
<a href="https://www.youtube.com/watch?v=WwGRGfLy6q8">bread</a>
a une très bonne vidéo ssh si besoin.</p>

<p>ma config en gros :</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PermitRootLogin no
AllowUsers le
Port XXX
PubkeyAuthentication <span class="nb">yes
</span>AuthenticationMethods publickey
PasswordAuthentication no
</code></pre></div></div>

<h2 id="sauvegardes">sauvegardes</h2>

<p>j’ai zippé mes sites et ils sont sur github.
comme je veux rewrite je m’en fous un peu.</p>

<h2 id="dot-files-">dot files ?</h2>

<p>non, je sais pas encore m’en servir.</p>

<p>je vais devoir remettre les trucs dont je me sers :</p>

<ul>
  <li>oh my posh</li>
  <li><a href="https://blog.legires.fr/2025/10/24/micro_config.html">micro</a></li>
  <li>htop</li>
</ul>

<p>pour oh my posh, penser à rajouter dans .bashrc :</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#ohmyposh</span>
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:/home/le/.local/bin
<span class="nb">eval</span> <span class="s2">"</span><span class="si">$(</span>oh-my-posh init bash<span class="si">)</span><span class="s2">"</span>
</code></pre></div></div>

<blockquote>
  <p>retour d’xp: je pensais que micro buggait, mais c’est juste que la déf des keybinds avait évolué.
ça fail silently donc faut faire gaffe.</p>
</blockquote>

<h2 id="alias">alias</h2>

<p>tant qu’on est dedans…
j’en utilise que deux :</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">alias </span><span class="nv">update</span><span class="o">=</span><span class="s1">'sudo apt update &amp;&amp; sudo apt upgrade -y'</span>
<span class="nb">alias </span><span class="nv">gitup</span><span class="o">=</span><span class="s1">'git add . &amp;&amp; git commit -m "dev" &amp;&amp; git push'</span>
</code></pre></div></div>

<blockquote>
  <p>retour d’xp: quand on set les locales sur .bashrc, faut le faire en début de file. askip.</p>
</blockquote>

<p>et aussi uncomment <code class="language-plaintext highlighter-rouge">la</code>.</p>

<h2 id="un-peu-daide-">un peu d’aide ?</h2>

<p>oui je veux bien.</p>

<p>je vais redonner une chance à vibe by mistral.
petit assistant serveur.</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You are an agent helping the maintainer of a Debian server. 
The purpose of this server is to host Python apps.

Always plan first. No yapping.
Prefer lists and markdown formatting.

If you propose code: no comments, no classes.
Code should be simple, straightforward and secure.
</code></pre></div></div>

<h2 id="firewall">firewall</h2>

<p>simple :</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
XXX/tcp                   ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
25/tcp                     ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
XXX/tcp (v6)              ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)
25/tcp (v6)                ALLOW       Anywhere (v6)
</code></pre></div></div>

<p>je crois que j’ai ouvert le 25 pour recevoir des mails mais je peux drop ça.</p>

<blockquote>
  <p>retour d’xp : j’ai oublié le XXX. quand on change son port ssh, faut le dire à ufw.
sinon on est enfermés dehors et faut tout réinstaller.</p>
</blockquote>

<h2 id="quelle-stack-">quelle stack ?</h2>

<p>python déjà.</p>

<p><code class="language-plaintext highlighter-rouge">uv python install 3.14 --force</code></p>

<p>ensuite sanic j’aime vraiment bien.
on garde mais faut faire des blueprints.</p>

<p>ensuite pour la database il est l’heure d’être un grand garçon.
on va passer sur le combo sqlite + peewee + harlequin.</p>

<p>et un autre grand saut dans l’inconnu mais bon :
on va ditch redis et passer sur nats.</p>

<p>le dernier point épineux c’est la génération html.
j’aime bien htpy mais bon…
en main ?? et puis la gueule du rewrite.</p>

<blockquote>
  <p>retour d’xp : stario ftw.</p>
</blockquote>

<h2 id="caddy">caddy</h2>

<p>bah ça va être vachement plus simple.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(app_config) {
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options SAMEORIGIN
        X-XSS-Protection "1; mode=block"
        Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        Referrer-Policy strict-origin-when-cross-origin
        Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()"
        -Server
    }

    @static path *.jpg *.jpeg *.png *.gif *.ico *.css *.js *.woff *.woff2 *.opus *.mp4 *.webp *.svg
    header @static Cache-Control "public, max-age=2592000, immutable"

    encode
}

leg.ovh, www.leg.ovh {
    reverse_proxy unix/home/le/legovh/legovh.sock
    import app_config
}
</code></pre></div></div>

<p>je crois qu’on peut l’améliorer un peu mais c’est déjà très bien.</p>

<blockquote>
  <p>retour d’xp : en fait, j’avais donné à caddy le droit de traverser mon home folder en faisant ça.
maintenant je mets les sockets dans un folder dédié dans /run/legovh/legovh.sock en 775.</p>
</blockquote>

<h2 id="déployer">déployer</h2>

<p>quand je faisais quart, j’avais :</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>Unit]
<span class="nv">Description</span><span class="o">=</span>Hypercorn instance to serve 10schat
<span class="nv">After</span><span class="o">=</span>network.target

<span class="o">[</span>Service]
<span class="nv">User</span><span class="o">=</span>le
<span class="nv">Group</span><span class="o">=</span>www-data
<span class="nv">WorkingDirectory</span><span class="o">=</span>/home/le/10schat
<span class="nv">ExecStart</span><span class="o">=</span>/home/le/10schat/.venv/bin/python <span class="nt">-m</span> hypercorn <span class="nt">-c</span> hypercorn.conf app:app

<span class="o">[</span>Install]
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</code></pre></div></div>

<p>mais c’est encore plus simple avec sanic qui porte la config :</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>Unit]
<span class="nv">Description</span><span class="o">=</span>Sanic instance to serve draft
<span class="nv">After</span><span class="o">=</span>network.target

<span class="o">[</span>Service]
<span class="nv">User</span><span class="o">=</span>le
<span class="nv">Group</span><span class="o">=</span>www-data
<span class="nv">WorkingDirectory</span><span class="o">=</span>/home/le/draft
<span class="nv">ExecStart</span><span class="o">=</span>/home/le/.local/bin/uv run app.py

<span class="o">[</span>Install]
<span class="nv">WantedBy</span><span class="o">=</span>multi-user.target
</code></pre></div></div>

<p>pas d’overhead à utiliser uv.
enable, start et roule ma poule.</p>

<blockquote>
  <p>retour d’xp : ouais ça prend du temps.
pour vous faire une idée, je sais tout sur fnaf maintenant.</p>
</blockquote>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[bon, faut upgrade debian de 12 à 13.]]></summary></entry><entry><title type="html">dur comme fer</title><link href="https://blog.legires.fr/2026/01/16/dur_comme_fer.html" rel="alternate" type="text/html" title="dur comme fer" /><published>2026-01-16T00:00:00+00:00</published><updated>2026-01-16T00:00:00+00:00</updated><id>https://blog.legires.fr/2026/01/16/dur_comme_fer</id><content type="html" xml:base="https://blog.legires.fr/2026/01/16/dur_comme_fer.html"><![CDATA[<p>ce post résume un bouquin de scott adams
sur les “reframes”.</p>

<p>qu’est-ce qu’un reframe ?</p>

<p>en gros, c’est un changement de narratif,
une phrase que tu répètes pour te permettre d’avancer,
de dépasser des choses qui te bloquent.</p>

<p>prenons un exemple :</p>

<blockquote>
  <p>il n’y a pas de mauvaise publicité</p>
</blockquote>

<p>imagine que tu es responsable de com’
d’un candidat politique.</p>

<p>la tension monte, et tu es paralysé par les choix :
faire ça ou pas, dire ça ou non, etc.</p>

<p>si tu te dis “il n’y a pas de mauvaise publicité”,
tu es d’un coup libre : ok !
on va faire ce qui maximise le buzz, un point c’est tout.</p>

<h2 id="oui-mais">oui mais</h2>

<p>oui mais (tu vas dire),
c’est pas vrai !
ça <strong>existe</strong>, la mauvaise publicité.</p>

<p>à quoi scott adams répond :</p>

<blockquote>
  <p>on s’en fout</p>
</blockquote>

<p>vraiment !
“i have no idea if that is true, and i don’t plan to research it because 
<strong>accuracy is not an active ingredient in reframes</strong>”.</p>

<p>un reframe / nouveau <em>narratif</em>, c’est un outil.
pas besoin d’être vrai, pas besoin d’être logique
(ça peut ! mais pas besoin),
tout ce qui compte, c’est que ça marche.
que ça te donne un avantage dans <strong>ta</strong> situation.
que ça t’aide.</p>

<p>exemple:
il n’y a pas de mauvaise publicité
ce qui ne te tue pas te rend plus fort</p>

<p>il y en a une que j’aime bien :
avant : mes chances sont faibles
après : j’estime mal mes chances</p>

<p>c’est une philosophie optimiste,
“j’ai choisi d’être heureux, c’est meilleur pour la santé”</p>

<h2 id="ok">ok…</h2>

<p>c’est presque tout.
avant de conclure,
quelques <em>reframes</em> du bouquin que j’aime bien.</p>

<p>tu es paralysé par tes échecs ?</p>

<p><em>j’échoue 9 trucs sur 10</em>
-&gt; si 1 projet sur 10 marche je suis gucci</p>

<p>tu doutes de ce qu’il faut faire ?</p>

<p><em>je veux faire x</em>
-&gt; j’ai décidé de faire x</p>

<p>et hop, ça enlève la composante “doute”
et roule raoul.</p>

<p>tu as l’impression de manquer de temps ?</p>

<p><em>gérer son temps</em>
-&gt; gérer son énergie</p>

<p>au lieu de faire de la place pour les choses,
les mettre au bon endroit.
par exemple : le matin travail créatif ou difficile, l’aprèm chill ou manuel.
surveiller son énergie au lieu de son temps
pour se dire qu’on donne le meilleur à chaque fois.</p>

<p>tu te sens souvent mal à l’aise dans des situations sociales ?
on va faire un reframe puissant.
on s’en fout si c’est vrai, mets les gaz !</p>

<p><em>tout le monde à cette soirée va me juger</em>
-&gt; je vais à une soirée où les gens ont été sélectionnés pour être gênants sauf moi</p>

<p>ou alors</p>

<p>-&gt; chaque personne ce soir a un problème que seul moi peut résoudre</p>

<p>tout ce qui compte, c’est que ça marche.</p>

<h2 id="on-dirait-du-self-help-baaaasique">on dirait du self-help baaaasique</h2>

<p>pas faux,
mais ça peut aussi aider dans le contexte pro.</p>

<p>par exemple :</p>

<p>est-ce que “x” est une bonne décision ?
-&gt; est-ce qu’on peut tester “x” à petite échelle ? en petit poc ?</p>

<p>et hop tu as <em>ta</em> manière de procéder.
autre exemple :</p>

<p>celui qui commande c’est le patron
-&gt; celui qui commande c’est celui qui a les meilleures idées</p>

<p>ça peut aider si tu as du mal à t’affirmer
ou si tu ne te sens pas importante.</p>

<p>donc voilà, ça peut servir pour le boulot.</p>

<p>moi mon préféré c’est celui-là :</p>

<p>l’art c’est du divertissement
-&gt; l’art est une puissante drogue psychique</p>

<p>et il ajoute “spielberg aurait dû me payer
comme <strong>cobaye</strong> pour voir la liste de schindler”.</p>

<p>je trouve ça marrant.
je me dis que si tu y crois vraiment
tu dois voir la réalité autrement,
et trouver un avantage / réduire le stress des décisions.</p>

<h2 id="je-vois-je-dois-lire-le-truc-">je vois. je dois lire le truc ?</h2>

<p>non tkt.</p>

<p>y’a de tout dont des trucs de trouduc,
très “biais du survivant”
ou pas originaux,
donc j’ai choisi le meilleur.</p>

<p>je mets une dernière citation du bouquin :</p>

<blockquote>
  <p>voilà ce qu’est un reframe : des mises à jour logicielles de votre cerveau. 
ils provoquent des changements physiques dans votre cerveau, comme toute expérience d’apprentissage.
une fois que vous acceptez la nature programmable de votre propre cerveau, vous pouvez 
devenir ce que j’appelle l’auteur de votre propre expérience. cela
remplace l’idée courante selon laquelle nous sommes le produit de nos expériences, de nos gènes
et de toute une série de facteurs que seul le destin contrôle.
cadre habituel : vous êtes le produit de vos expériences et de vos gènes.
-&gt; recadrage : vous êtes l’auteur de votre expérience.</p>
</blockquote>

<p>si on y réfléchit… ouais, pas de raison que ça ne marche pas.</p>

<h2 id="en-pratique">en pratique</h2>

<p>une fois que tu as trouvé un “mantra” qui te plaît,
comment l’utiliser ?</p>

<p>j’ai trouvé un moyen mémotechnique,
il faut y croire
<strong>dur comme f.e.r.</strong> :</p>

<ul>
  <li><strong>f</strong>ocus</li>
  <li><strong>é</strong>motion</li>
  <li><strong>r</strong>épétition</li>
</ul>

<p>en gros, dire la phrase (en vrai ou dans sa tête)
en se concentrant sur la phrase,
en y associant une émotion
(par exemple comment tu te sentiras bien quand tu l’auras fait),
et le répéter souvent jusqu’à ce que la neuroplasticité fasse son travail.</p>

<p>voilà bibi c’est tout. love u &lt;3</p>

<blockquote>
  <p>post-scriptum</p>
</blockquote>

<p>scott adams died while i was writing this.
i looked at x and it seems americans 
had a lot to unload.
first, this article wasn’t meant to you,
as you guessed by it not being written in the language you speak.
then, i don’t see what the fuss is about.
it is my opinion that you should get away from people
as much as people.
no matter the color, humans are psychotic apes
and you’re better off alone.
lastly, i liked dilbert.
it’s funny.
and the man was proud of having left books behind.
that i understand.
go write your book or plant your tree.
now shoo.</p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[ce post résume un bouquin de scott adams sur les “reframes”.]]></summary></entry><entry><title type="html">everybody codes 2025</title><link href="https://blog.legires.fr/2025/12/01/everybody_codes.html" rel="alternate" type="text/html" title="everybody codes 2025" /><published>2025-12-01T00:00:00+00:00</published><updated>2025-12-01T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/12/01/everybody_codes</id><content type="html" xml:base="https://blog.legires.fr/2025/12/01/everybody_codes.html"><![CDATA[<p>i enjoyed 
<a href="https://everybody.codes/events">everybody code</a> 
a lot!</p>

<p>good problems and
<a href="https://aoc.leg.ovh/">easter eggs</a>,
what’s not to like?</p>

<p>what’s important for me in these code events:</p>
<ul>
  <li>realize early what can and cannot work</li>
  <li>have fun</li>
  <li>read other people code</li>
  <li>re-read your solutions</li>
  <li>see your innefficiencies</li>
</ul>

<p>it’s very important to read other’s code.
you already figured out the “what” by solving the problem,
so you’re more efficient on the “how”.</p>

<p>so here is my review of some shared python code:</p>

<h2 id="yldraw">yldraw</h2>

<p><a href="https://github.com/Yldrax/everybody-codes/tree/master/2025">repo link</a></p>

<p>i found the very useful
<a href="https://tqdm.github.io/">tqdm</a>
library.
get a loading bar for your loops!</p>

<p>i also see that <code class="language-plaintext highlighter-rouge">cmp_to_key</code> was not needed for day 5
and a simple lambda sort would have worked.</p>

<p>i brute forced day 6 (sorry).
it’s nice he figured out the “wrap”.</p>

<p>nice recursion on day 7.
let’s do a quick set cheatsheet:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center"><strong>Code</strong></th>
      <th style="text-align: center"><strong>Means</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">a |= b</td>
      <td style="text-align: center">a = a.union(b)</td>
    </tr>
    <tr>
      <td style="text-align: center">a &amp;= b</td>
      <td style="text-align: center">a = a.intersection(b)</td>
    </tr>
    <tr>
      <td style="text-align: center">a -= b</td>
      <td style="text-align: center">a = a.difference(b)</td>
    </tr>
    <tr>
      <td style="text-align: center">a ^= b</td>
      <td style="text-align: center">a = a.symmetric_difference(b)</td>
    </tr>
  </tbody>
</table>

<p>yes for day 8, you don’t need to store every strike.
this “max update” pattern, i should use it more often.</p>

<p>ok he stopped around where i stopped.
i won’t check after day 11 anyway.</p>

<h2 id="danagle">danagle</h2>

<p><a href="https://github.com/danagle/everybody-codes-challenges/tree/main/2025-the-songs-of-ducks-and-dragons">repo link</a></p>

<p>he “washed” his code, meaning he cleaned it
and added any “efficient” tricks
(like a modulo trick you don’t see in your first pass
but understand afterwards).</p>

<p>but it’s a bit too washed.
almost golfed.</p>

<p>he uses 
<a href="https://numba.pydata.org/">numba</a> 
to speed up his loops. interesting.</p>

<p>nice use of <code class="language-plaintext highlighter-rouge">Counter.most_common()</code>.</p>

<p>string padding on day 6, why not.
i wondered if someone used <code class="language-plaintext highlighter-rouge">cycle</code>.</p>

<p>oh itertools 
<a href="https://docs.python.org/3/library/itertools.html#itertools.pairwise">pairwise</a>,
nice!</p>

<p>oh and a 
<a href="https://en.wikipedia.org/wiki/Trie">trie</a>?!
ok… a prefix tree.
useful for autocomplete, spell check and ip routing.
even better is a 
<a href="https://en.wikipedia.org/wiki/Radix_tree">radix tree</a>,
ok ok.</p>

<p>oh so 
<a href="https://docs.python.org/3/library/profile.html">that’s how</a>
you profile python code.
might be useful for my dod posts.</p>

<p>oh and now a
<a href="https://en.wikipedia.org/wiki/Fenwick_tree">fenwick tree</a>,
watch out we’ve got a badass over there.
hmmm ok i don’t think i’ll ever use that.</p>

<p>day 9 he uses a trie again.
and so he doesn’t do bfs like i did.
man i need to level up my trees.</p>

<p>ok, i learned about <code class="language-plaintext highlighter-rouge">nonlocal</code> in imbricated functions.
i don’t think i should use it.</p>

<p>i still can’t figure out what went wrong in day 10.
day 11, i also tried that and it didn’t work. oh well.</p>

<p>nice, he made visualizations!
using <code class="language-plaintext highlighter-rouge">PIL.Image.fromarray()</code> is tight.</p>

<h2 id="alex11br">alex11br</h2>

<p><a href="https://github.com/ALEX11BR/everybodyCodes2025/tree/main/d3">repo link</a></p>

<p>oh shit. numpy arrays,
<code class="language-plaintext highlighter-rouge">functools.reduce</code>,
we’ve got a madman.</p>

<p>yeah, no, bad code.</p>

<h2 id="r01f">r01f</h2>

<p><a href="https://github.com/r0f1/everybody_codes_2025/tree/main">repo link</a></p>

<p>nothing fancy.</p>

<p>i really like his:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">trees</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">{</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">c</span><span class="p">[</span><span class="mi">0</span><span class="p">]}</span>
    <span class="k">for</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">permutations</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">b</span> <span class="o">&gt;</span> <span class="n">c</span> <span class="ow">and</span> <span class="n">is_child</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">c</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="p">]</span>
</code></pre></div></div>

<p>quite effective.</p>

<h2 id="elandor">elandor</h2>

<p><a href="https://github.com/theElandor/ec2025/tree/main/DeD">repo link</a></p>

<p>yuck.</p>

<hr />

<p>if you want to see what i did,
<a href="https://github.com/1363V4/evc25">here’s my code</a>.</p>

<p>now, let’s do the same for aoc!</p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[i enjoyed everybody code a lot!]]></summary></entry><entry><title type="html">a good class - part 3</title><link href="https://blog.legires.fr/2025/11/29/good_class3.html" rel="alternate" type="text/html" title="a good class - part 3" /><published>2025-11-29T00:00:00+00:00</published><updated>2025-11-29T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/11/29/good_class3</id><content type="html" xml:base="https://blog.legires.fr/2025/11/29/good_class3.html"><![CDATA[<p><strong>note:</strong> this is part 3 in a series of posts about oop.
<a href="https://blog.legires.fr/2025/11/15/good_class.html">part 1</a>,
<a href="https://blog.legires.fr/2025/11/18/good_class_2.html">part 2</a>.</p>

<hr />

<p>ok, so the first step in data-oriented design is this one:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">array</span> <span class="kn">import</span> <span class="n">array</span>
</code></pre></div></div>

<p>with this, we will use tightly packed c structures
to store our data.</p>

<p>next is this array cheatsheet:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center"><strong>Code</strong></th>
      <th style="text-align: center"><strong>Range</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">b</td>
      <td style="text-align: center">[-127, 127]</td>
    </tr>
    <tr>
      <td style="text-align: center">B</td>
      <td style="text-align: center">[0, 255]</td>
    </tr>
    <tr>
      <td style="text-align: center">H</td>
      <td style="text-align: center">[0, 65535]</td>
    </tr>
    <tr>
      <td style="text-align: center">L</td>
      <td style="text-align: center">[0, 4 BILLIONS]</td>
    </tr>
    <tr>
      <td style="text-align: center">Q</td>
      <td style="text-align: center">you don’t even</td>
    </tr>
  </tbody>
</table>

<p>some things worth noting here:</p>

<ul>
  <li>lowercase letter for signed, uppercase for unsigned (so signed short is ‘h’).</li>
  <li>‘b’ takes the same space as ‘B’ (1 byte).</li>
  <li>i like to use mostly uppercase.</li>
</ul>

<p>that’s because one of the strengths of dod is that you can store the index of an entity as a reference to it. and i don’t want negative indexes ever.</p>

<p>some absences worth noting:</p>

<ul>
  <li>‘i’ for int has platform-dependent size, which kinda breaks dod’s predictability, so i don’t use them.</li>
  <li>floating points calculations are ‘f’ and ‘d’. try not to use them if you can (if you do physics, you might have to, else just scale and normalize everything).</li>
  <li>python also has ‘u’ and ‘w’ for text characters, but <a href="https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/">try not to use strings</a> if a human isn’t gonna read it.</li>
</ul>

<p>now, some things you should <strong>really</strong> note:</p>

<ul>
  <li>‘B’ gives you 256 values. do you realize how big that is? you can probably encode all types of your game monsters in <em>one</em> byte.</li>
  <li>no, really, do you see how insane this is?</li>
  <li>with two bytes, you raise to 65535. you’re mostly covered.</li>
  <li>okok, ‘Q’? [0, 18446744073709551615]. 18 billion billion, motherfucker. eight bytes.</li>
  <li>the cpu cache line is 64 bytes. this means an array of 16 longs can be brought to the cpu in one trip.</li>
</ul>

<p>so, for example, if you have 10 players in a game,
you can encode every one of their properties on 4 billion values,
and treat each transformation in one cpu roundtrip.</p>

<p>if you think about it, it’s <strong>insane</strong>.</p>

<hr />

<p>ok, now let’s see how i tried to do dod on a real-worl example.</p>

<p>this is from
<a href="https://everybody.codes/event/2025/quests/10">everybody codes 2025 day 10</a>
so go check it out.</p>

<p>i’ll just show the commented code:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">array</span> <span class="kn">import</span> <span class="n">array</span>

<span class="n">data</span> <span class="o">=</span> <span class="s">'''...SSS.......
.S......S.SS.
..S....S...S.
..........SS.
..SSSS...S...
.....SS..S..S
SS....D.S....
S.S..S..S....
....S.......S
.SSS..SS.....
.........S...
.......S....S
SS.....S..S..'''</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="p">.</span><span class="n">splitlines</span><span class="p">()</span> <span class="c1"># formatting the data
</span><span class="n">h</span><span class="p">,</span> <span class="n">w</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>

<span class="n">deepl</span> <span class="o">=</span> <span class="p">{</span><span class="s">'.'</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s">'D'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s">'S'</span><span class="p">:</span> <span class="mi">2</span><span class="p">}</span> <span class="c1"># changing chars to int values
</span>
<span class="c1"># prepare encoding, one array per property
</span><span class="n">grid</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'x'</span><span class="p">:</span> <span class="n">array</span><span class="p">(</span><span class="s">'B'</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">h</span> <span class="o">*</span> <span class="n">w</span><span class="p">),</span>
    <span class="s">'y'</span><span class="p">:</span> <span class="n">array</span><span class="p">(</span><span class="s">'B'</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">h</span> <span class="o">*</span> <span class="n">w</span><span class="p">),</span>
    <span class="s">'cell'</span><span class="p">:</span> <span class="n">array</span><span class="p">(</span><span class="s">'B'</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">h</span> <span class="o">*</span> <span class="n">w</span><span class="p">),</span>
    <span class="s">'moves'</span><span class="p">:</span> <span class="n">array</span><span class="p">(</span><span class="s">'H'</span><span class="p">),</span> <span class="c1"># we need more than 255 for the moves (21*21) so 65535 it is!
</span>    <span class="s">'count'</span><span class="p">:</span> <span class="n">h</span> <span class="o">*</span> <span class="n">w</span> <span class="c1"># so we don't have to call len() each time
</span><span class="p">}</span>

<span class="n">data</span><span class="p">.</span><span class="n">reverse</span><span class="p">()</span>
<span class="c1"># actual encoding
</span><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">j</span><span class="p">,</span> <span class="n">cell</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
        <span class="n">grid</span><span class="p">[</span><span class="s">'x'</span><span class="p">][</span><span class="n">w</span><span class="o">*</span><span class="n">i</span> <span class="o">+</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">j</span>
        <span class="n">grid</span><span class="p">[</span><span class="s">'y'</span><span class="p">][</span><span class="n">w</span><span class="o">*</span><span class="n">i</span> <span class="o">+</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span>
        <span class="n">grid</span><span class="p">[</span><span class="s">'cell'</span><span class="p">][</span><span class="n">w</span><span class="o">*</span><span class="n">i</span> <span class="o">+</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">deepl</span><span class="p">[</span><span class="n">cell</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">cell</span> <span class="o">==</span> <span class="s">'D'</span><span class="p">:</span>
            <span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">].</span><span class="n">append</span><span class="p">(</span><span class="n">w</span><span class="o">*</span><span class="n">i</span> <span class="o">+</span> <span class="n">j</span><span class="p">)</span>

<span class="n">knight_moves</span> <span class="o">=</span> <span class="p">{</span>
    <span class="c1"># small b cause its signed
</span>    <span class="s">'x'</span><span class="p">:</span> <span class="n">array</span><span class="p">(</span><span class="s">"b"</span><span class="p">,</span> <span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">]),</span>
    <span class="s">'y'</span><span class="p">:</span> <span class="n">array</span><span class="p">(</span><span class="s">"b"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">]),</span>
    <span class="s">'count'</span><span class="p">:</span> <span class="mi">8</span>
<span class="p">}</span>

<span class="n">dragon_moves</span> <span class="o">=</span> <span class="mi">4</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">dragon_moves</span><span class="p">):</span>
    <span class="c1"># we'll be modifying the array during the loop but we don't even care lololol
</span>    <span class="n">start_len</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">])</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">start_len</span><span class="p">):</span>
        <span class="n">index</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="c1"># the index **is** the entity
</span>        <span class="n">x</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="s">'x'</span><span class="p">][</span><span class="n">index</span><span class="p">]</span>
        <span class="n">y</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="s">'y'</span><span class="p">][</span><span class="n">index</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">knight_index</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">knight_moves</span><span class="p">[</span><span class="s">'count'</span><span class="p">]):</span>
            <span class="n">dx</span> <span class="o">=</span> <span class="n">knight_moves</span><span class="p">[</span><span class="s">'x'</span><span class="p">][</span><span class="n">knight_index</span><span class="p">]</span>
            <span class="n">dy</span> <span class="o">=</span> <span class="n">knight_moves</span><span class="p">[</span><span class="s">'y'</span><span class="p">][</span><span class="n">knight_index</span><span class="p">]</span>
            <span class="n">nx</span><span class="p">,</span> <span class="n">ny</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">dx</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="n">dy</span>
            <span class="k">if</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">nx</span> <span class="o">&lt;</span> <span class="n">w</span> <span class="ow">and</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">ny</span> <span class="o">&lt;</span> <span class="n">h</span><span class="p">:</span>
                <span class="n">test_index</span> <span class="o">=</span> <span class="n">w</span> <span class="o">*</span> <span class="n">ny</span> <span class="o">+</span> <span class="n">nx</span>
                    <span class="k">if</span> <span class="n">test_index</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">]:</span>
                        <span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">].</span><span class="n">append</span><span class="p">(</span><span class="n">test_index</span><span class="p">)</span>

<span class="n">eaten</span> <span class="o">=</span> <span class="mi">0</span>
<span class="c1"># i did some tests
# sorting is not that costly
# but can greatly improve performance
# maybe the cpu optimization prefers to read arrays in order
</span><span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">]</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">])</span>
<span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="n">grid</span><span class="p">[</span><span class="s">'moves'</span><span class="p">]:</span>
    <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="s">'cell'</span><span class="p">][</span><span class="n">index</span><span class="p">]</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
        <span class="n">eaten</span> <span class="o">+=</span> <span class="mi">1</span>

<span class="k">print</span><span class="p">(</span><span class="n">eaten</span><span class="p">)</span>
</code></pre></div></div>

<hr />

<p>so the key point here is that the index <strong>is</strong> the entity.
this means you can store indexes in an array
as a very effective way to reference entity.</p>

<p>in short, you need to become an array master.</p>

<p>some more tips that were revealed to me by prophecy:</p>
<ul>
  <li>never use booleans, use existence-based arrays instead</li>
  <li>(basically, don’t use an “alive” boolean but make two arrays alive_entities and dead_entities)</li>
  <li>learn how minecraft works</li>
  <li>use <a href="https://github.com/Altanis/generational_indices?tab=readme-ov-file">generational indexes </a></li>
  <li>use sparse sets</li>
  <li>(which are swapback with generational indexes)</li>
  <li>learn how minecraft works</li>
  <li>track and optimize your sparse sets</li>
  <li>read the first three chapters of <a href="https://existentialprogramming.blogspot.com/">existential programming</a></li>
  <li>learn how age of empire works</li>
  <li>advanced: learn how to do pathfinding dod-style</li>
  <li>learn <a href="https://fr.wikipedia.org/wiki/Arbre_B">b trees</a> and <a href="https://fr.wikipedia.org/wiki/Quadtree">quad trees</a></li>
  <li>advanced: learn the <a href="https://martinfowler.com/articles/lmax.html">disruptor pattern</a></li>
  <li>(which is an ephemeral buffer with a fixed size)</li>
  <li>sparse set + disruptor = very fast</li>
  <li>games are all about reusing buffers</li>
  <li>relations are not a problem with generational indexes</li>
  <li>learn how minecraft works</li>
  <li>advanced: learn profile guided optimization</li>
</ul>

<p>i should report back on my findings,
but you do the homework too.</p>

<hr />

<p>finally, do remind that everything 
is not a nail to hammer dod on.</p>

<p>for example, in the above code,
i should have use <code class="language-plaintext highlighter-rouge">grid['moves] = set()</code>
instead of an <code class="language-plaintext highlighter-rouge">O(n)</code> check every time
(but i’m sure you noticed).</p>

<p>another example is
if you have billions of entities (like particles),
maybe use seeded shaders over time.</p>

<p>optimize for the right part of the computer.</p>

<hr />

<p>now that we saw arrays, what if we want to persist the data?</p>

<p>how do you do proper dod with sqlite?</p>

<p>should you use orms?</p>

<p>head on to part 4.</p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[note: this is part 3 in a series of posts about oop. part 1, part 2.]]></summary></entry><entry><title type="html">a good class - part 2</title><link href="https://blog.legires.fr/2025/11/18/good_class_2.html" rel="alternate" type="text/html" title="a good class - part 2" /><published>2025-11-18T00:00:00+00:00</published><updated>2025-11-18T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/11/18/good_class_2</id><content type="html" xml:base="https://blog.legires.fr/2025/11/18/good_class_2.html"><![CDATA[<p><strong>note:</strong> this is part 2 in a series of posts about oop.
<a href="https://blog.legires.fr/2025/11/15/good_class.html">part 1</a>.</p>

<hr />

<p>i asked claude what he thought about my previous article and…</p>

<p><img src="/img/class/claude.png" alt="claude" /></p>

<p>now, the good thing with ai roasting is that it cannot quit the conversation.
you can continue to trade blows. and i did.</p>

<h2 id="what-i-learned">what i learned</h2>

<p>it’s simple:</p>

<p><strong>there are no good classes.</strong></p>

<p>i tried saving the idea as hard as i could,
but all my points were moot.</p>

<p>immutability? you don’t get that. not with python.
even with <code class="language-plaintext highlighter-rouge">frozen</code>, if your class has a list, won’t work…</p>

<p>the <code class="language-plaintext highlighter-rouge">read()</code> function?
it’s an overcomplicated setter.
the real “message passing” should be done by a <strong>system</strong>
(more on that later).</p>

<p><code class="language-plaintext highlighter-rouge">slots</code> won’t improve your control over your data structure,
hot data, block size:
you’re better off with an <code class="language-plaintext highlighter-rouge">array</code>…</p>

<p>last but not least: the <code class="language-plaintext highlighter-rouge">property</code> check?
yeah but why would you want that?</p>

<p><em>why would you want to give up on the ability</em>
<em>to freely compose data whenever you want,</em>
<em>whenever you need?</em></p>

<p>in other words…</p>

<h2 id="data-is-just-data">data is just data</h2>

<p>and it belongs in a database.</p>

<p>not in a class, in a <strong>database</strong>.</p>

<p><em>your code shouldn’t have state and your data shouldn’t have behaviors.</em></p>

<p>or as they say in the video <a href="https://www.youtube.com/watch?v=Ks98kE3cs30">overwatch architecture</a>:</p>

<blockquote>
  <p>systems have no state, components have no behavior</p>
</blockquote>

<p>this is the root of <strong>entity component system</strong>,
or ecs in short.</p>

<h2 id="e-c-s-baby">e-c-s, baby</h2>

<p>the best video you’re going to see about ecs
is <a href="https://www.youtube.com/watch?v=WwkuAqObplU">this one</a>. please watch it.</p>

<p>i mentioned 
<a href="https://docs.python.org/fr/3/library/array.html">the array library</a>
earlier.
because i love python,
and i try to write python <strong>as a c wrapper</strong>
as much as possible.</p>

<p>and i’m not gonna ruin it by writing classes, no no no.</p>

<p>so <strong>what is ecs?</strong></p>

<p>in one sentence:</p>

<blockquote>
  <p>a struct of arrays instead of an array of structs</p>
</blockquote>

<p>in one picture:</p>

<p><img src="/img/class/ecs.png" alt="ecs" /></p>

<p>don’t write vertical “classes”. write horizontal “data slices”.</p>

<p>easier to store, easier to load,
and paradoxically, easier to reason about.</p>

<p>if it didn’t click for you, more homework:</p>
<ul>
  <li><a href="https://skypjack.github.io/2019-02-14-ecs-baf-part-1/">ecs megathread</a></li>
  <li><a href="https://skypjack.github.io/2020-08-02-ecs-baf-part-9/">sparse/dense indexing</a></li>
  <li><a href="https://gameprogrammingpatterns.com/data-locality.html">data locality</a></li>
  <li><a href="https://en.wikipedia.org/wiki/Observer_pattern">observer pattern</a></li>
</ul>

<h2 id="the-last-nail-in-oops-coffin">the last nail in oop’s coffin</h2>

<p>i’ll leave you now with one very important quote.</p>

<p>while trying to argue that classes could work
for <em>some</em> use cases with delaney
(who’s way nicer than claude, surprisingly),
i tried the:</p>

<blockquote>
  <p>what if you only need it once? just once!
for fixed parameters! we have tools for that,
but what should we use? enums, named tuples?
dataclass with frozen and slots?</p>
</blockquote>

<p>and the master said:</p>

<blockquote>
  <p>if you think you’re gonna need it once, <strong>you’re wrong.</strong></p>
</blockquote>

<p>and the student was enlightened.</p>

<hr />

<p>start with an array of length 1.
it’s gonna become 2 soon enough.</p>

<p>input control? you’re gonna netcode it.
config file? you’re gonna have a test environment.
camera system? what about a killcam?</p>

<p>it’s arrays all the way down.</p>

<p>so start with them.
then you’ll build structs.
of arrays.</p>

<p><strong>not</strong> arrays of structs.</p>

<p>oop <em>feels</em> organized.
to you.</p>

<p>but to your cpu? not that much.</p>

<hr />

<p>next up: 
<a href="https://blog.legires.fr/2025/11/29/good_class3.html">a practical look</a>
at dod in python.</p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[note: this is part 2 in a series of posts about oop. part 1.]]></summary></entry><entry><title type="html">a good class - part 1</title><link href="https://blog.legires.fr/2025/11/15/good_class.html" rel="alternate" type="text/html" title="a good class - part 1" /><published>2025-11-15T00:00:00+00:00</published><updated>2025-11-15T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/11/15/good_class</id><content type="html" xml:base="https://blog.legires.fr/2025/11/15/good_class.html"><![CDATA[<p><strong>note:</strong> this is part 1 in a series of posts about oop.
<a href="https://blog.legires.fr/2025/11/18/good_class_2.html">part 2</a>.</p>

<hr />

<blockquote>
  <p>consider how humans, or any other autonomous creatures of nature, operate with their model of the world. we all have our own model of the world contained in our own heads, i.e. we have a copy of the world state for our own use. we mutate the state in our heads based on inputs (events/messages) we receive via our senses. as we process these inputs and apply them to our model we may take action that produces outputs, which others can take as their own inputs. none of us reach directly into each other’s heads and mess with the neurons. if we did this it would be a serious breach of encapsulation! originally, object oriented (oo) design was all about message passing, and somehow along the way we bastardized the message passing to be method calls and even allowed direct field manipulation – yuck! whose bright idea was it to allow public access to fields of an object? you deserve your own special hell.</p>
</blockquote>

<blockquote>
  <p>mechanical sympathy</p>
</blockquote>

<p>i recently watched good videos about object-oriented programming:</p>
<ul>
  <li><a href="https://www.youtube.com/watch?v=QM1iUe6IofM">oop is bad</a></li>
  <li><a href="https://www.youtube.com/watch?v=IRTfhkiAqPw">oop is embarassing</a></li>
  <li><a href="https://www.youtube.com/watch?v=V6VP-2aIcSc">oop is garbage</a></li>
</ul>

<p>bottom line:
<strong>most classes are bad.</strong></p>

<p>so… how do you make a <strong>good</strong> class?</p>

<p>i propose you check for these 3 things:</p>
<ul>
  <li>dataclass + slots</li>
  <li>@property</li>
  <li>frozen or read()</li>
</ul>

<p>let’s explain.</p>

<h2 id="dataclass--slots">dataclass + slots</h2>

<p>first of all, <strong>please use dataclasses.</strong></p>

<p>there’s zero (0) reason not to use them:
you reduce the boilerplate,
you improve readability,
you type attributes…</p>

<p>and you don’t lose <strong>anything</strong> except footguns.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>

<span class="o">@</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">Rectangle</span><span class="p">:</span>
    <span class="n">width</span><span class="p">:</span> <span class="nb">float</span>
    <span class="n">height</span><span class="p">:</span> <span class="nb">float</span>
</code></pre></div></div>

<p>the next step is activating <code class="language-plaintext highlighter-rouge">slots</code>.</p>

<p>this will really boost performance (because of c shenanigans)
at the cost of not being able to add attributes at runtime,
<strong>which you shouldn’t do anyway.</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">dataclass</span><span class="p">(</span><span class="n">slots</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Rectangle</span><span class="p">:</span>
    <span class="n">width</span><span class="p">:</span> <span class="nb">float</span>
    <span class="n">height</span><span class="p">:</span> <span class="nb">float</span>
</code></pre></div></div>

<p>next is the property check.</p>

<h2 id="property">@property</h2>

<p>a class is just grouped data,
in other words <strong>data that belongs together.</strong></p>

<p>if this data <em>reeaaaally</em> belongs together,
you should be able to compute something out of it.</p>

<p>in other words, you should have a <strong>property</strong>:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">dataclass</span><span class="p">(</span><span class="n">slots</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Rectangle</span><span class="p">:</span>
    <span class="n">width</span><span class="p">:</span> <span class="nb">float</span>
    <span class="n">height</span><span class="p">:</span> <span class="nb">float</span>

    <span class="o">@</span><span class="nb">property</span>
    <span class="k">def</span> <span class="nf">area</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">width</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">height</span>
</code></pre></div></div>

<p>no property is a bad tell,
ask yourself why you grouped this data in the first place.
maybe your class isn’t really useful.</p>

<p>the only exception where it’s ok to not have a property
is if your class is <strong>frozen</strong>,
which we’re gonna see in the next chapter.</p>

<h2 id="frozen-or-read">frozen or read()</h2>

<p>alright,
now you have to make a choice.</p>

<p>either you freeze your dataclass,
because you wanted immutability on the data,
for example, config parameters of a script:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span>

<span class="o">@</span><span class="n">dataclass</span><span class="p">(</span><span class="n">frozen</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">slots</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">AppConfig</span><span class="p">:</span>
    <span class="n">host</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">port</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">debug</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="bp">False</span>

    <span class="o">@</span><span class="nb">property</span>
    <span class="k">def</span> <span class="nf">url</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="sa">f</span><span class="s">"http://</span><span class="si">{</span><span class="bp">self</span><span class="p">.</span><span class="n">host</span><span class="si">}</span><span class="s">:</span><span class="si">{</span><span class="bp">self</span><span class="p">.</span><span class="n">port</span><span class="si">}</span><span class="s">"</span>
</code></pre></div></div>

<p>and that’s ok.
this is a <strong>perfectly acceptable class.</strong>
thanks for coming to my ted talk.</p>

<hr />

<p>oh, i know what you’re going to say:</p>

<p><em>“but that’s not why i make classes! i want to model entities and modify their attributes!”</em></p>

<p>i know.</p>

<p>you want to make a class “monster”
to make little monsters in your game,
give them weapons, armor, attack damage,
reduce their hp when they take a hit,
apply status effects…</p>

<p>look, the only status effect you’re gonna get
is “poisoned” when your state is all over the place.
<strong>you’re gonna die from oop.</strong></p>

<p>please reread the citation at the beginning.</p>

<p>if your class isn’t frozen,
its attributes should <strong>only be changed by this class</strong>.</p>

<p>the way you’d do this is with a <code class="language-plaintext highlighter-rouge">read()</code> method:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">dataclass</span><span class="p">(</span><span class="n">slots</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Rectangle</span><span class="p">:</span>
    <span class="n">width</span><span class="p">:</span> <span class="nb">float</span>
    <span class="n">height</span><span class="p">:</span> <span class="nb">float</span>

    <span class="o">@</span><span class="nb">property</span>
    <span class="k">def</span> <span class="nf">area</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">width</span> <span class="o">*</span> <span class="bp">self</span><span class="p">.</span><span class="n">height</span>

    <span class="k">def</span> <span class="nf">read</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
        <span class="s">"""message receiver: decodes message and updates state"""</span>
        <span class="n">msg_type</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'type'</span><span class="p">)</span>
        
        <span class="k">if</span> <span class="n">msg_type</span> <span class="o">==</span> <span class="s">'resize'</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">width</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'width'</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">width</span><span class="p">)</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">height</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'height'</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">height</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">msg_type</span> <span class="o">==</span> <span class="s">'scale'</span><span class="p">:</span>
            <span class="n">factor</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'factor'</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">)</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">width</span> <span class="o">*=</span> <span class="n">factor</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">height</span> <span class="o">*=</span> <span class="n">factor</span>
        <span class="k">elif</span> <span class="n">msg_type</span> <span class="o">==</span> <span class="s">'set_width'</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">width</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'width'</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">msg_type</span> <span class="o">==</span> <span class="s">'set_height'</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">height</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'height'</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">raise</span> <span class="nb">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s">"unknown message type: </span><span class="si">{</span><span class="n">msg_type</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>

<blockquote>
  <p>nb: 
people sometimes advocate for the syntax <code class="language-plaintext highlighter-rouge">_method()</code>
as a pythonic way to indicate a “private” method.
i think it looks awful, and because it doesn’t <em>actually</em> enforce anything,
you’d be better off with nice comments in plain english.</p>
</blockquote>

<p>of course, you can also write a <code class="language-plaintext highlighter-rouge">send()</code> method 
if you want your class to emit messages.</p>

<p>but, in a nutshell,
<strong>this is how you do proper oop.</strong></p>

<h2 id="red-flags">red flags</h2>

<p>to conclude, some red flags.
if you see:</p>

<ul>
  <li>state being modified outside the class</li>
  <li>any form of inheritance</li>
  <li>any form of factory (whatever that means)</li>
  <li>any getter or setter</li>
  <li>any class that fails these 3 checks</li>
</ul>

<p>burn the code to the ground and rewrite functional.</p>

<hr />

<p>next up, you’ll see why
<a href="https://blog.legires.fr/2025/11/18/good_class_2.html">everything you just read is bullshit.</a></p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[note: this is part 1 in a series of posts about oop. part 2.]]></summary></entry><entry><title type="html">background noise</title><link href="https://blog.legires.fr/2025/11/08/background_noise.html" rel="alternate" type="text/html" title="background noise" /><published>2025-11-08T00:00:00+00:00</published><updated>2025-11-08T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/11/08/background_noise</id><content type="html" xml:base="https://blog.legires.fr/2025/11/08/background_noise.html"><![CDATA[<p>i realize that when i listen to music,
or watch a video,
it’s for <em>receiving.</em></p>

<p>but it’s hard when i create.
i spend more time choosing the songs than working.
and i focus on the songs.</p>

<p>i figured radio would help,
because you don’t have to select the songs.
but i spend time selecting the radio, lol.
so many radios in the garden.</p>

<p>and it’s ok.</p>

<p>i love receiving knowledge,
lettin it go through me.
but the world is gonna claim its due, right?</p>

<p>so yeah, background ambiance it is.</p>

<p><a href="https://asoftmurmur.com/?lang=en">a soft murmur</a>
is cool.</p>

<p>just typing background noise and rolling.</p>

<p>but i have to develop the reflex.</p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[i realize that when i listen to music, or watch a video, it’s for receiving.]]></summary></entry><entry><title type="html">my micro editor config</title><link href="https://blog.legires.fr/2025/10/24/micro_config.html" rel="alternate" type="text/html" title="my micro editor config" /><published>2025-10-24T00:00:00+00:00</published><updated>2025-10-24T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/10/24/micro_config</id><content type="html" xml:base="https://blog.legires.fr/2025/10/24/micro_config.html"><![CDATA[<p>lately i had trouble with vs code server.</p>

<p>i tried notepad++ with a ftp configuration,
which is cool for file uploads
but not so much for live edits.</p>

<p>fortunately,
i find the <code class="language-plaintext highlighter-rouge">micro</code> editor
to be quite pleasant.</p>

<p>here is my config file
to feel at home:</p>

<h2 id="bindingsjson">bindings.json</h2>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"Alt-/"</span><span class="p">:</span><span class="w"> </span><span class="s2">"lua:comment.comment"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"Alt-Ctrl-Up"</span><span class="p">:</span><span class="w"> </span><span class="s2">"SpawnMultiCursorUp"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"Alt-Ctrl-Down"</span><span class="p">:</span><span class="w"> </span><span class="s2">"SpawnMultiCursorDown"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"Alt-&lt;"</span><span class="p">:</span><span class="w"> </span><span class="s2">"NextTab"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"CtrlUnderscore"</span><span class="p">:</span><span class="w"> </span><span class="s2">"lua:comment.comment"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>comment and multi-cursor kinda like vs code.</p>

<p>still using <code class="language-plaintext highlighter-rouge">alt-n</code> for FindNext because overriding <code class="language-plaintext highlighter-rouge">ctrl-d</code>
does not work for some reason.</p>

<p>i like the split view, still getting used to it,
but i cycle through tabs with <code class="language-plaintext highlighter-rouge">alt-&lt;</code>
like i cycle views with <code class="language-plaintext highlighter-rouge">ctrl-w</code> (double view lol).</p>

<p><code class="language-plaintext highlighter-rouge">ctrl-e</code> is very nice,
especially with the autocomplete.</p>

<h2 id="settingsjson">settings.json</h2>

<p>very important to set the clipboard to terminal 
as i mostly use micro when ssh’ed.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"clipboard"</span><span class="p">:</span><span class="w"> </span><span class="s2">"terminal"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"colorscheme"</span><span class="p">:</span><span class="w"> </span><span class="s2">"gruvbox"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"rmtrailingws"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[lately i had trouble with vs code server.]]></summary></entry><entry><title type="html">just fucking use datastar</title><link href="https://blog.legires.fr/2025/10/11/just_fucking_use_datastar.html" rel="alternate" type="text/html" title="just fucking use datastar" /><published>2025-10-11T00:00:00+00:00</published><updated>2025-10-11T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/10/11/just_fucking_use_datastar</id><content type="html" xml:base="https://blog.legires.fr/2025/10/11/just_fucking_use_datastar.html"><![CDATA[<p>the plan was simple:</p>
<ul>
  <li>use <a href="https://data-star.dev/">datastar</a></li>
  <li>build anything you fucking want</li>
</ul>

<p>but no, you dimwits had to have some second thoughts.</p>

<p>so let’s have this discussion, shall we?</p>

<blockquote>
  <p>context: i made a 
<a href="https://leg.ovh/">shit-ton of projects</a> with datastar and 
<a href="https://www.youtube.com/channel/UCSD9LvJNyHGgWw5XipRuohA">20+ youtube videos about it</a> 
so yeah i’m biased, duh.</p>
</blockquote>

<h2 id="react-is-fine">“react is fine”</h2>

<p>no it’s not, you scum.</p>

<p>you make users download 
<a href="https://infrequently.org/series/performance-inequality/">megabytes of data</a> 
for spinners that never fucking load.</p>

<p>you build services so fragile that the slightest error
sends all your infra in <a href="https://blog.cloudflare.com/deep-dive-into-cloudflares-sept-12-dashboard-and-api-outage/">a roller coaster to hell.</a></p>

<p>you shame us all with abhorrent code.
what’s a junior dev to think when you show’em 
<a href="https://github.com/ladifire-opensource/facebook-codebase/blob/8fb37667acd68b1b19b0e99405ab157ede5786a3/36.js">your stinky codebase?</a>
total fucking disgust, correct.</p>

<p>but the worst of your sins is your sync engine.
excuse me but 
<em>what do you need to fucking sync exactly</em>?
the server and the client?
did you try, um, i don’t know, using 
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP">htt-fucking-p</a> 
to exchange data?!</p>

<p>oh you did, you sent a skeleton-ass page and instructions to download more javascript at the nearest black market.
fair, you don’t build websites, you build 
<a href="https://socket.dev/blog/malicious-npm-packages-target-react-vue-and-vite-ecosystems-with-destructive-payloads">trojan bombs</a>, so
sync my ass.</p>

<h2 id="ackhually">“ackhually…”</h2>

<p>if you were going to say “next.js”: congrats larry 
<a href="https://projectdiscovery.io/blog/nextjs-middleware-authorization-bypass">you’re a comedian</a>.</p>

<p>look, i don’t care if you use
svelte, vue, vite, vroom, nuxt, angular, bozo.js
or any other “i have nodes in my brain” clown-ass frameworks.</p>

<p>you build a pile of hot garbage on javascript. period.</p>

<p>because you never understood that javascript is a way to interact with the browser and the markup,
because you never understood the browser,
because you never understood the markup,
because you don’t fucking read.</p>

<p>maybe start with 
<a href="https://www.dummies.com/book/technology/programming-web-design/general-programming-web-design/web-coding-development-all-in-one-for-dummies-281889/">“hypermedia for dummies”</a>?</p>

<h2 id="sikes-i-use-htmx">“sikes! i use htmx”</h2>

<p>sikes on you, you fuck.</p>

<p>does this look like a blog rant of peace?</p>

<p>this is war, motherfucker.</p>

<p>you come to battle with your megatron-ass voltron-build 
glued with <code class="language-plaintext highlighter-rouge">htmx</code>, <code class="language-plaintext highlighter-rouge">alpine.js</code>, <code class="language-plaintext highlighter-rouge">htmx-sse</code>, <code class="language-plaintext highlighter-rouge">htmx-head-support</code>, <code class="language-plaintext highlighter-rouge">htmx-idiomorph</code>, <code class="language-plaintext highlighter-rouge">htmx-alpine-morph</code>, <code class="language-plaintext highlighter-rouge">htmx-multi-swap</code>…</p>

<p>you look like a janky knight in a cyber conflict.</p>

<p>we’re gonna laser beam your rusty helm with half the code
and a fraction of the complexity. hold still
<em>(or don’t, doesn’t matter).</em></p>

<h2 id="whats-the-big-fucking-deal">what’s the big fucking deal</h2>

<p>datastar is not miracle fucking water.</p>

<p>it’s simply:</p>
<ul>
  <li>htmx with oob default <a href="https://data-star.dev/essays/event_streams_all_the_way_down">(the correct one btw)</a> and a better morph</li>
  <li>data-attributes made reactive with <a href="https://data-star.dev/guide/reactive_signals">signals</a></li>
  <li>(<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/Use_data_attributes">attributes are hypermedia</a> by the fucking way)</li>
  <li>and <a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events">sse support</a></li>
</ul>

<p>here “sse support” just means using the fucking 
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">fetch api</a>,
but with quality-of-life defaults like auto-reconnect and exponential backoffs.</p>

<p>your browser is already a fucking jet engine:
datastar doesn’t reinvent the wheel,
it just puts four of them under the rocket so you can get fucking moving.</p>

<h2 id="its-just-the-new-fad">“it’s just the new fad”</h2>

<p>the web doesn’t break 
<a href="https://www.w3.org/People/Bos/DesignGuide/compatibility.html">backward compatibility</a> you dumbass.</p>

<p>datastar websites are forever.
this is what you get by building on fucking specs.</p>

<p>with datastar, you only manage the backend, not the backend + frontend.
<a href="https://grugbrain.dev/">complexity is a poison</a>, 
if you want to manage both,
please shove this
<a href="https://en.wikipedia.org/wiki/Median_lethal_dose">median lethal dose</a>
down your throat, thank ya.</p>

<p>and btw: never a breaking change.
datastar is just 
<a href="https://github.com/starfederation/datastar/blob/develop/library/src/engine/engine.ts">a few thousand lines of typescript</a>
and it’s v1 forever baby.</p>

<h2 id="sorry-i-said-that-im-an-old-fart">“sorry i said that, i’m an old fart”</h2>

<p>ok sensei, congrats on your mastery of php and jquery.</p>

<p>no, sincerely i mean it, you fucking zen monk.
you like code that reads and stuff that works.
well, the future is now and you’ll be fine.
heck, you’ll love it!</p>

<p>you’re gonna be writing so much awk and so little javascript
you’ll feel one step closer to heaven, you lucky fuck.</p>

<h2 id="dont-fucking-use-datastar-pro">don’t fucking use datastar pro</h2>

<p>let me say it loudly for the morons in the back
who think they can hack the fbi but can’t put two and two together:
<strong>it’s just so that your fucking company can support the project!!</strong></p>

<p>convince these lobotomized suits they might need <code class="language-plaintext highlighter-rouge">data-persist</code> in the future 
or whatever other bullshit
and snatch the damn credit card.</p>

<p>no you’re never ever gonna need any feature in pro and it’s total bait,
but these guys need to eat goddammit.</p>

<h2 id="dont-fucking-use-datastar">don’t fucking use datastar</h2>

<p>take a wild fucking guess: does this page use datastar?</p>

<p>no! it’s a blog post, dumb as rocks text-on-a-page goodness!</p>

<p>you got multiple pages worth of information?
let me doubt that first, most of you are building landing pages
for the ceo of 
<a href="https://www.litter-robot.com/">bluetooth-cat-litter-inc</a> 
who needs a rotating marquee of sponsors.
doesn’t qualify as “information”, does it?</p>

<p>but even then, let’s say you <strong>do</strong> have multiple pages:
please build an mpa.
you might even want to check the definition to that, who fucking knows.</p>

<p>for the remaining cases: 99% of the time
your job is to build a 
<a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete">crud app</a>
without adding more misery to the world.
yet you keep inventing ever more spectacular ways to fail at that.</p>

<p>we gave you 
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods">request methods</a>
and you’re still looking at the square peg and the round hole with intense dedication, 
you dozy ape.</p>

<p>god forbid you came from 
<a href="https://news.ycombinator.com/">the hn website</a>.
the comments don’t even auto-update!
barely usable and probably zero users, i bet you that.</p>

<h2 id="closing-thoughts">closing thoughts</h2>

<p>yes this is fucking parody.</p>

<p>it’s inspired by <a href="https://motherfuckingwebsite.com/">this glorious shit</a>.</p>

<p>and it’s made <strong>against</strong>
<a href="https://justfuckingusereact.com/">this poop pile</a>,
<a href="https://reactisfuckingcool.com/">this ai babble</a>,
<a href="https://justfuckingusehtml.com/">that big stain</a>
and <em>(jesus, how many abominations must these people shit before the js god is appeased)</em>
<a href="https://justfuckingusesolid.com/">that other thing</a>.</p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[the plan was simple: use datastar build anything you fucking want]]></summary></entry><entry><title type="html">relapse</title><link href="https://blog.legires.fr/2025/09/18/relapse.html" rel="alternate" type="text/html" title="relapse" /><published>2025-09-18T00:00:00+00:00</published><updated>2025-09-18T00:00:00+00:00</updated><id>https://blog.legires.fr/2025/09/18/relapse</id><content type="html" xml:base="https://blog.legires.fr/2025/09/18/relapse.html"><![CDATA[<p>i relapsed today.</p>

<p>i shall rewrite here the important words of visakan.</p>

<hr />

<p>idk if i was <em>gravely</em> ‘mentally’ ill,
but i was down ominously bad
(false hope, impossible desires, intense grievance)
– i feel like this has parallels with
being a heavy cigarette smoker then going off of them.
my favourite way of describing <em>that</em> is
“quitting punctuation”</p>

<hr />

<p>i used to use cigarettes to punctuate my life.
started the day with them.
kept time with them.
regulated my moods with them.
finished meals with them.
socialized with them.
cigarettes kept my life in order.
they provided structure. rhythm.
i looked forward to the next one.</p>

<hr />

<p>when i went off of them the punctuation marks fell out of my life
and all of a sudden i was falling spinning circling
everything is chaotic and makes no sense
where am i going who am i
even what is happening oh god
it’s all too much and its everything at once
help help help</p>

<hr />

<p>it took time for me to figure out new ways of arranging my life</p>

<p>without the punctuation marks i had grown accustomed to leaning on</p>

<p>turns out for example that you can use linebreaks as a form of punctuation</p>

<p>i had never considered that when all i knew was fullstops</p>

<hr />

<p>similarly, the basic flavor of sanity seems disappointing,
mundane, boring, when you’re used to excitement
in the form of intense mental activity</p>

<p>it’s like going from walls of heavy distorted guitars and crashing cymbals
to a single solo piano.
at first it seems thin, weak, flat</p>

<hr />

<p>but its just a different instrument,
a different aesthetic,
something you have to learn anew.
there’s infinite nuance within that seemingly boring simplicity.
it just takes time and patience to allow yourself
to learn to appreciate it.
you have to relearn everything</p>

<hr />

<p>appreciation is a skill that can be cultivated</p>

<p>you can learn to appreciate the elegance and simplicity
of having less anguished mental activity</p>

<p>this might sound weird to anyone who’s never used that anguish as a comfort blanket</p>

<p>you can learn to relax in the emptiness</p>

<p><img src="/img/visakan.jpeg" alt="visakan" /></p>]]></content><author><name>le guide</name></author><summary type="html"><![CDATA[i relapsed today.]]></summary></entry></feed>