Kartones Bloghttps://blog.kartones.net/2024-03-16T12:05:00+01:00Be the change you want to see in this worldBook Review: Elon Musk2024-03-16T12:05:00+01:002024-03-16T12:05:00+01:00Kartonestag:blog.kartones.net,2024-03-16:/post/book-review-elon-musk-walter-isaacson/<h3>Review</h3>
<p><picture><source srcset="https://images.kartones.net/posts/kartonesblog/book_elon_musk.webp" type="image/webp"/><img alt="Elon Musk book cover" height="200" loading="lazy" src="https://images.kartones.net/posts/kartonesblog/book_elon_musk.jpg" width="131"/></picture></p>
<p><strong>Title</strong>: <a href="https://app.thestorygraph.com/books/2aeb3592-b6ca-449b-ad9e-345f9709dc3b">Elon Musk</a></p>
<p><strong>Author(s)</strong>: Walter Isaacson</p>
<p>Most people on Earth probably have heard about Elon Musk, and most will probably also think he is as eccentric as clever; at times looking so intelligent and creative, other times such a disrespectful public figure. Combined with a well known biographies …</p><h3>Review</h3>
<p><picture><source srcset="https://images.kartones.net/posts/kartonesblog/book_elon_musk.webp" type="image/webp"/><img alt="Elon Musk book cover" height="200" loading="lazy" src="https://images.kartones.net/posts/kartonesblog/book_elon_musk.jpg" width="131"/></picture></p>
<p><strong>Title</strong>: <a href="https://app.thestorygraph.com/books/2aeb3592-b6ca-449b-ad9e-345f9709dc3b">Elon Musk</a></p>
<p><strong>Author(s)</strong>: Walter Isaacson</p>
<p>Most people on Earth probably have heard about Elon Musk, and most will probably also think he is as eccentric as clever; at times looking so intelligent and creative, other times such a disrespectful public figure. Combined with a well known biographies writer, Walter Isaacson, this book made for an appealing reading.</p>
<p>I am as happy to have read it, as I am sad of the conclusions I take from it.</p>
<p>The TL;DR is that yes, the book mostly confirms what everyone thinks about Musk: An amazing visionary and strategist, that is pushing humanity ahead technologically in multiple fronts, but also a hypocritical, Steve Jobs-like distorted reality viewer, unsocial and terrible people manager, plus apparently a social media addict [1].</p>
<p>I learned a lot about his <code>X.com</code> and Paypal years, about how Tesla came to be (he wasn't a founder, more of an activist investor), SpaceX (impressive story), OpenAI (the less surprising story, mostly what we already know), bits about The Boring Company and Neuralink (less successful adventures have less attention in the book), and of course the Twitter drama. All of them quite interesting, and very revealing of how he thinks and likes to manage, and directly control, <strong>everything</strong>.</p>
<p>I have no doubt he is intelligent, and he has really innovative approaches to managing companies, like being ruthless in questioning every procedure, every step and every requirement to try to optimize it, or the "idiot index" (despite the unfortunate name), by which if some piece's source materials costs way less than the sell price, it can be optimized. Or his radical approach of flattening organizations, so that technical managers must have hands-on experience, and engineers have to work very closely with design and product.</p>
<p>But then, you have the people management "procedures"... Making people work 24-7 just because he lives in a permanent state of paranoia that, in his mind, if he stops everything will fall apart (when things are calm he makes up something). This is very unhealthy, and along the book we'll find examples of how most of his lieutenants and close circle go-to persons are people who basically put work above everything else [2]. And then, despite of this extremely hardcore work attitude, still being so ruthless with people around him, for them to have "kind words" such as the following:</p>
<p><em>"He can be quick to personalize blame when something goes wrong"</em></p>
<p><em>"Elon is just not a very nice person and didn’t treat people well"</em></p>
<p><em>"He could be a bully and brutal"</em></p>
<p>We also get a (maybe too long) glimpse of his troubled infancy, which could be the source of his horrible social skills and dictatorial attitude. But to me, it feels he has not tried to solve them, so they are not an excuse for treating others so badly.</p>
<p>And, after reading how mr. Musk iterates at times so dangerously on his optimization procedures, I think that I will never use a "first version" of any product of his companies; he first removes too much, then brings back what was really needed, but that includes disregarding all safety measures, from space rocket components to handling computer servers, so I'll let others "test" and pick a v2 or v3 when things are more mature.</p>
<p>It is a very good book, way more surprising than Steve Jobs' biography, but at times it is not a pleasant reading because what it tells. Advancing humanity is good, but to me the how is as important as the why.</p>
<p>[1]: Unfiltered/Not thinking before writing on social media has been, and still is as of early 2024, problematic for both him and for the companies he manages.</p>
<p>[2]: The work-centered obsession reached absurd extremes, like having your family live with you inside Twitter offices, being in a constant 24-7 on-call during years, being frowned upon if taking any vacation...</p>A Gazelle extension featuring LifecycleManager2024-03-12T22:15:00+01:002024-03-12T22:15:00+01:00Kartonestag:blog.kartones.net,2024-03-12:/post/gazelle-extension-featuring-lifecyclemanager/<p>One of the biggest caveats of working with Bazel's tool <a href="https://github.com/bazelbuild/bazel-gazelle">Gazelle</a> is the lack of up to date documentation. Yes, the tool is still at version <code>0.x</code>, but the docs are quite obsolete: often they don't mention few features, there are missing configuration settings, and in general there is …</p><p>One of the biggest caveats of working with Bazel's tool <a href="https://github.com/bazelbuild/bazel-gazelle">Gazelle</a> is the lack of up to date documentation. Yes, the tool is still at version <code>0.x</code>, but the docs are quite obsolete: often they don't mention few features, there are missing configuration settings, and in general there is a lack of examples of how to use anything other than directives. There is even a "hidden tool", <code>autogazelle</code>, not even mentioned in the main README. [1]</p>
<p>In the end, what always works is reading the source code... and when present, the tests. And it is while checking Gazelle's tests (searching for an example of using the <code>LifecycleManager</code> extensions interface), that I found a nice little test with some special properties; The test is <code>test_load_for_packed_rules</code> (located <a href="https://github.com/bazelbuild/bazel-gazelle/blob/f590ca1488eff5063a9549a3edba8266a6ce6134/internal/language/test_load_for_packed_rules/lang.go">here</a>), and I think it is relevant because:</p>
<ul>
<li>It showcases how to build a tiny Gazelle extension. It is almost empty, but all the critical parts are present</li>
<li>Despite beeing small, it shows all the relevant interface methods you should implement for a valid/complete extension. It does use the now deprecated <a href="https://github.com/bazelbuild/bazel-gazelle/blob/f590ca1488eff5063a9549a3edba8266a6ce6134/language/lang.go#L92-L93">Loads()</a> instead of Bzlmod's <a href="https://github.com/bazelbuild/bazel-gazelle/blob/f590ca1488eff5063a9549a3edba8266a6ce6134/language/lang.go#L137">ApparentLoads()</a>, but Bzlmod needs to mature a bit so not a big deal (yet)</li>
<li>And finally, it includes a working example of <code>LifecycleManager</code>, which is what I was looking for</li>
</ul>
<p>Once you have seen an example, it becomes trivial to add support of the new lifecycle interface functions to an existing extension, but at least for a non-Gopher like me, that first sample was helpful.</p>
<p>[1] But, if you find it, it contains <a href="https://github.com/bazelbuild/bazel-gazelle/blob/f590ca1488eff5063a9549a3edba8266a6ce6134/cmd/autogazelle/README.rst">its own README</a>.</p>Books read list and StoryGraph2024-02-28T07:00:00+01:002024-02-28T07:00:00+01:00Kartonestag:blog.kartones.net,2024-02-28:/post/books-read-list-and-storygraph/<p>I maintain <a href="https://blog.kartones.net/page/reviews/">a list of the books I read</a> since a few years; well, In reality, I maintain two, because fiction and comics <a href="https://theelderthoughts.blogs.kartones.net/page/reviews/">go separate ways</a> from non-fiction and technical books.</p>
<p>The point is that I recently knew about <a href="https://app.thestorygraph.com/">The StoryGraph</a> thanks to <a href="https://www.hanselminutes.com/932/local-ai-empowers-startups-with-storygraphs-rob-frelow">a podcast episode</a>, and got attracted by …</p><p>I maintain <a href="https://blog.kartones.net/page/reviews/">a list of the books I read</a> since a few years; well, In reality, I maintain two, because fiction and comics <a href="https://theelderthoughts.blogs.kartones.net/page/reviews/">go separate ways</a> from non-fiction and technical books.</p>
<p>The point is that I recently knew about <a href="https://app.thestorygraph.com/">The StoryGraph</a> thanks to <a href="https://www.hanselminutes.com/932/local-ai-empowers-startups-with-storygraphs-rob-frelow">a podcast episode</a>, and got attracted by the fact that it's made by fans, for fans, not owned by a giant commercial corporation. I and tend to not give too much weight to opinions until I test things, but Scott, the podcast host, was also praising the recommendations algorithm. So I decided try the service and create an account (there's a membership tier, but almost everything is free).</p>
<p>A few hours of manually adding my read books & comics I tracked/could remember (254 items 😆), and taking the basic survey to get some recommendations, I can summarize it as "wow!". It is giving me some nice recommendations, and many others to explore; the search is quite good, and when a title is missing I usually find it by author or, at times, by series, and I tried adding some titles by ISBN code and except two, it quickly found them.</p>
<p>The site is fast, free of clutter, and while there are a lot of features I might not use (e.g. I don't plan to track my reading progress, just pending, wip and done), it is still very simple to use and does exactly what I want. Plus I can export a nice CSV with all my data any time I want, which is great for me as a source of structured data (vs my blogs' plain review lists).</p>
<p>I aim to maintain the list updated, so feel free to add me <a href="https://app.thestorygraph.com/profile/kartones">at StoryGraph</a> if you want.</p>My macOS Cheatsheet2024-01-28T14:45:00+01:002024-01-28T14:45:00+01:00Kartonestag:blog.kartones.net,2024-01-28:/post/my-macos-cheatsheet/<p>I learn better by creating cheatsheets and summaries, so adding <a href="https://blog.kartones.net/archives.html">to my list</a>, I recently took an old macos cheatsheet I had with a few shortcuts, and I've been improving and expanding it. I wrote it while at Eventbrite, when I had to switch from Linux to Mac, and now …</p><p>I learn better by creating cheatsheets and summaries, so adding <a href="https://blog.kartones.net/archives.html">to my list</a>, I recently took an old macos cheatsheet I had with a few shortcuts, and I've been improving and expanding it. I wrote it while at Eventbrite, when I had to switch from Linux to Mac, and now I'm facing a very similar scenario at Spotify; I need to build/compile iOS binaries from time to tim, so instead of having two work laptops, I made the switch.</p>
<p>It lives at <a href="https://blog.kartones.net/page/macos-cheatsheet/">https://blog.kartones.net/page/macos-cheatsheet/</a>, and the content is a mix of three kinds:</p>
<ul>
<li>Shortcuts: Both operating system and application-specific</li>
<li>Tips/Fixes/Tweaks</li>
<li>Tools: To complement <a href="https://blog.kartones.net/page/command-line-tools/">my command-line tools list</a>, GUI tools, with the restriction of being either free or open-source [1].</li>
</ul>
<p>I must admit that, at the time of writing this post, the list of tools is pretty scarce, so I'm more than open to more suggestions. Just take into account that I'm searching for applications to either improving macos-usage in general, or development-specific.</p>
<p>[1] I won't pay for any software I'm only going to use at work, and I already have licenses for required tools like IntelliJ.</p>Debugging Typescript errors in Bazel2024-01-21T17:05:00+01:002024-01-21T17:05:00+01:00Kartonestag:blog.kartones.net,2024-01-21:/post/debugging-typescript-errors-in-bazel/<p>Typescript errors are not always easy to debug. Add Bazel to the mix, and some errors can feel a nightmare to understand and resolve. Thankfully, there are two steps that will help a lot with triaging.</p>
<p>Let's imagine we have the following action, which transpiles some typescript and then runs …</p><p>Typescript errors are not always easy to debug. Add Bazel to the mix, and some errors can feel a nightmare to understand and resolve. Thankfully, there are two steps that will help a lot with triaging.</p>
<p>Let's imagine we have the following action, which transpiles some typescript and then runs it via NodeJS (you can find it at <a href="https://github.com/Kartones/bazel-web-template">my Github bazel-web-template repo</a>):</p>
<div class="highlight"><pre><span></span><code>bazel<span class="w"> </span>run<span class="w"> </span>src/ts:run_d
</code></pre></div>
<p>This action calls a <code>js_binary</code>, to a transpiled <code>d.mjs</code> file, which imports from <code>c.mjs</code>. I have on purpose modified the import to wrongly ask for <code>e.mjs</code>, so when we run it, inside the Bazel execution output, we'll get the following error:</p>
<div class="highlight"><pre><span></span><code>src/ts/d.mts<span class="o">(</span><span class="m">1</span>,28<span class="o">)</span>:<span class="w"> </span>error<span class="w"> </span>TS2307:<span class="w"> </span>Cannot<span class="w"> </span>find<span class="w"> </span>module<span class="w"> </span><span class="s1">'./e.mjs'</span><span class="w"> </span>or<span class="w"> </span>its<span class="w"> </span>corresponding<span class="w"> </span><span class="nb">type</span><span class="w"> </span>declarations.
</code></pre></div>
<p>Now let's keep imagining that we have no clue where could that error come from; We just know that something is trying to import <code>e.mjs</code> and fails to do so.</p>
<p>The first step to ease debugging, is to tell Bazel to keep the sandbox when the execution ends, so we can inspect and replicate what it ran. For that, we can use the <a href="https://bazel.build/docs/sandboxing#debugging-build-failures">sandbox_debug flag</a>:</p>
<div class="highlight"><pre><span></span><code>bazel<span class="w"> </span>run<span class="w"> </span>src/ts:run_d<span class="w"> </span>--sandbox_debug
</code></pre></div>
<p>Now, the output will be more verbose, and we will notice that, around where it outputs the error, there will be something referring to a failure/error executing a command, followed by a long execution line. In this example, calling a <code>tsc</code> wrapper script.</p>
<p>Note: I've simplified a bit the paths [1] and added some new lines for legibility.</p>
<div class="highlight"><pre><span></span><code>linux-sandbox<span class="w"> </span>failed:<span class="w"> </span>error<span class="w"> </span>executing<span class="w"> </span>TsProject<span class="w"> </span><span class="nb">command</span><span class="w"> </span>
<span class="o">(</span><span class="nb">cd</span><span class="w"> </span>/bazel/sandbox/linux-sandbox/226/execroot/_main<span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="se">\</span>
<span class="nb">exec</span><span class="w"> </span>env<span class="w"> </span>-<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="nv">BAZEL_BINDIR</span><span class="o">=</span>bazel-out/k8-fastbuild/bin<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="nv">TMPDIR</span><span class="o">=</span>/tmp<span class="w"> </span><span class="se">\</span>
/bazel/install/linux-sandbox<span class="w"> </span>-W<span class="w"> </span>/tmp/<span class="w"> </span>-t<span class="w"> </span><span class="m">15</span><span class="w"> </span>-w<span class="w"> </span>/dev/shm<span class="w"> </span>-w<span class="w"> </span>/tmp<span class="w"> </span>-w<span class="w"> </span>/tmp/
<span class="w"> </span>bazel-execroot/_main<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/execroot<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-execroot<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/execroot<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-working-directory<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/external/aspect_rules_js<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-source-roots/0<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/external/nodejs_linux_amd64<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-source-roots/1<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/tmp<span class="w"> </span>-S<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/stats.out<span class="w"> </span>
<span class="w"> </span>-N<span class="w"> </span>-D<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/debug.out<span class="w"> </span>
<span class="w"> </span>--<span class="w"> </span>bazel-out/k8-opt-exec/bin/external/npm_typescript/tsc.sh<span class="w"> </span>
<span class="w"> </span>--project<span class="w"> </span>tsconfig.json<span class="w"> </span>
<span class="w"> </span>--outDir<span class="w"> </span>src/ts<span class="w"> </span>
<span class="w"> </span>--rootDir<span class="w"> </span>src/ts<span class="w"> </span>
<span class="w"> </span>--declarationDir<span class="w"> </span>src/ts<span class="w"> </span>
<span class="w"> </span>--tsBuildInfoFile<span class="w"> </span>src/ts/d.tsbuildinfo<span class="o">)</span>
</code></pre></div>
<p>If we re-execute in the command line that big command, we can replay very similarly what Bazel did: In our case, apparently some transpilation taking place at <code>src/ts</code>. But not only that, we can also alter it, by adding for example the <a href="https://www.typescriptlang.org/tsconfig#traceResolution">traceResolution flag</a> so that <code>tsc</code> emits more details.</p>
<p>Let's add it to the end, for example as <code>--traceResolution >> out.txt</code>:</p>
<div class="highlight"><pre><span></span><code><span class="nb">cd</span><span class="w"> </span>/bazel/sandbox/linux-sandbox/226/execroot/_main<span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="se">\</span>
<span class="nb">exec</span><span class="w"> </span>env<span class="w"> </span>-<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="nv">BAZEL_BINDIR</span><span class="o">=</span>bazel-out/k8-fastbuild/bin<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="nv">TMPDIR</span><span class="o">=</span>/tmp<span class="w"> </span><span class="se">\</span>
/bazel/install/linux-sandbox<span class="w"> </span>-W<span class="w"> </span>/tmp/<span class="w"> </span>-t<span class="w"> </span><span class="m">15</span><span class="w"> </span>-w<span class="w"> </span>/dev/shm<span class="w"> </span>-w<span class="w"> </span>/tmp<span class="w"> </span>-w<span class="w"> </span>/tmp/
<span class="w"> </span>bazel-execroot/_main<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/execroot<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-execroot<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/execroot<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-working-directory<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/external/aspect_rules_js<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-source-roots/0<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/external/nodejs_linux_amd64<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp/bazel-source-roots/1<span class="w"> </span>
<span class="w"> </span>-M<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/_hermetic_tmp<span class="w"> </span>
<span class="w"> </span>-m<span class="w"> </span>/tmp<span class="w"> </span>-S<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/stats.out<span class="w"> </span>
<span class="w"> </span>-N<span class="w"> </span>-D<span class="w"> </span>/bazel/sandbox/linux-sandbox/226/debug.out<span class="w"> </span>
<span class="w"> </span>--<span class="w"> </span>bazel-out/k8-opt-exec/bin/external/npm_typescript/tsc.sh<span class="w"> </span>
<span class="w"> </span>--project<span class="w"> </span>tsconfig.json<span class="w"> </span>
<span class="w"> </span>--outDir<span class="w"> </span>src/ts<span class="w"> </span>
<span class="w"> </span>--rootDir<span class="w"> </span>src/ts<span class="w"> </span>
<span class="w"> </span>--declarationDir<span class="w"> </span>src/ts<span class="w"> </span>
<span class="w"> </span>--tsBuildInfoFile<span class="w"> </span>src/ts/d.tsbuildinfo
<span class="w"> </span>--traceResolution<span class="w"> </span>>><span class="w"> </span>out.txt
</code></pre></div>
<p>Executing that command, we will get a very detailed <code>tsc</code> module resolution trace. I Highly recommended to output it to a file, as even with simple examples it is quite large!</p>
<p>Analysing the trace resolution, we search for <code>e.mjs</code> and something-something resolution...</p>
<div class="highlight"><pre><span></span><code><span class="o">========</span><span class="w"> </span>Resolving<span class="w"> </span>module<span class="w"> </span><span class="s1">'./e.mjs'</span><span class="w"> </span>
<span class="w"> </span>from<span class="w"> </span><span class="s1">'/tmp//bazel-out/k8-fastbuild/bin/src/ts/d.mts'</span>.<span class="w"> </span><span class="o">========</span>
Explicitly<span class="w"> </span>specified<span class="w"> </span>module<span class="w"> </span>resolution<span class="w"> </span>kind:<span class="w"> </span><span class="s1">'NodeNext'</span>.
Resolving<span class="w"> </span><span class="k">in</span><span class="w"> </span>ESM<span class="w"> </span>mode<span class="w"> </span>with<span class="w"> </span>conditions<span class="w"> </span><span class="s1">'import'</span>,<span class="w"> </span><span class="s1">'types'</span>,<span class="w"> </span><span class="s1">'node'</span>.
Loading<span class="w"> </span>module<span class="w"> </span>as<span class="w"> </span>file<span class="w"> </span>/<span class="w"> </span>folder,<span class="w"> </span>
<span class="w"> </span>candidate<span class="w"> </span>module<span class="w"> </span>location<span class="w"> </span><span class="s1">'/tmp//bazel-out/k8-fastbuild/bin/src/ts/e.mjs'</span>,<span class="w"> </span>
<span class="w"> </span>target<span class="w"> </span>file<span class="w"> </span>types:<span class="w"> </span>TypeScript,<span class="w"> </span>JavaScript,<span class="w"> </span>Declaration,<span class="w"> </span>JSON.
File<span class="w"> </span>name<span class="w"> </span><span class="s1">'/tmp//bazel-out/k8-fastbuild/bin/src/ts/e.mjs'</span><span class="w"> </span>has<span class="w"> </span>a<span class="w"> </span><span class="s1">'.mjs'</span><span class="w"> </span>extension
<span class="w"> </span>-<span class="w"> </span>stripping<span class="w"> </span>it.
File<span class="w"> </span><span class="s1">'/tmp//bazel-out/k8-fastbuild/bin/src/ts/e.mts'</span><span class="w"> </span>does<span class="w"> </span>not<span class="w"> </span>exist.
File<span class="w"> </span><span class="s1">'/tmp//bazel-out/k8-fastbuild/bin/src/ts/e.d.mts'</span><span class="w"> </span>does<span class="w"> </span>not<span class="w"> </span>exist.
File<span class="w"> </span><span class="s1">'/tmp//bazel-out/k8-fastbuild/bin/src/ts/e.mjs'</span><span class="w"> </span>does<span class="w"> </span>not<span class="w"> </span>exist.
Directory<span class="w"> </span><span class="s1">'/tmp//bazel-out/k8-fastbuild/bin/src/ts/e.mjs'</span><span class="w"> </span>does<span class="w"> </span>not<span class="w"> </span>exist,<span class="w"> </span>
<span class="w"> </span>skipping<span class="w"> </span>all<span class="w"> </span>lookups<span class="w"> </span><span class="k">in</span><span class="w"> </span>it.
<span class="o">========</span><span class="w"> </span>Module<span class="w"> </span>name<span class="w"> </span><span class="s1">'./e.mjs'</span><span class="w"> </span>was<span class="w"> </span>not<span class="w"> </span>resolved.<span class="w"> </span><span class="o">========</span>
</code></pre></div>
<p>And there it is, we see that the resolution comes from <code>from [...] src/ts/d.mts</code>. We can also see all the variants that it tried (TS/JS + type definitions), and if this was a potential package dependency, we would see it also crawl up, searching for <code>node_modules</code> folders and looking inside them if present.</p>
<p>As a summary, by enabling the sandbox persistence, and then re-playing the executed command with some extra flags, we can debug way better most Typescript errors.</p>
<p>Before wrapping up this post, I also want to mention some more generic debugging advices:</p>
<p>Checking <code>bazel-out</code> to see which files you have can be very helpful. Just remember to run a <code>bazel clean</code> if want to be certain that all files you're seeing are from your last execution, and not from past ones. Web rules tend to leave a lot of leftovers.</p>
<p>Many times, the source of the error is file visibility-related: You are transpiling the correct files, but then either you're not exposing them at the intended target (e.g. via <code>data</code> or as a dependency), or maybe your <code>tsconfig.json</code> is not properly set and as an example module resolution is not correctly configured, or you're missing some <code>rootDir</code>/<code>rootDirs</code>. About <code>rootDirs</code>, they are not that problematic in Bazel <em>unless</em> you use yarn/pnpm/etc. workspaces.</p>
<p>And finally, your mileage and preferences might vary, but in Bazel I prefer a classic approach of transpiling everything to Javascript, and then running binaries and tests against JS-only file sets, versus using <code>ts-node</code>, <code>babel</code> and similar under-the-hood transformations. Being able to check at each step if you have the proper files eases debugging and simplifies configuration a lot (specially during migrations).</p>
<p>[1] : Sandbox paths including the action tend to be quite long; A few times, long enough to cause issues under Windows.</p>My Generative AI and ML usages (as of 2023)2023-12-30T11:30:00+01:002023-12-30T11:30:00+01:00Kartonestag:blog.kartones.net,2023-12-30:/post/my-generative-ai-and-ml-usages-2023/<p>As I was writing <a href="https://blog.kartones.net/post/2023-wrap-up/">my 2023 wrap-up post</a>, I noticed I have scattered around different posts some of the generative AI and machine learning scenarios that I'm actively using (the so-called "AI" term). It is a good idea to summarize them because my general advice from 2023 echoes what has …</p><p>As I was writing <a href="https://blog.kartones.net/post/2023-wrap-up/">my 2023 wrap-up post</a>, I noticed I have scattered around different posts some of the generative AI and machine learning scenarios that I'm actively using (the so-called "AI" term). It is a good idea to summarize them because my general advice from 2023 echoes what has been said a lot during the year: <strong>You should experiment and test with AI technologies</strong>.</p>
<p>I will focus only on technologies/APIs, but an increasing number of tools are "AI-Assisted" now, from Spotify's radio DJ to Grammarly/Language Tool.</p>
<h3>Github Copilot</h3>
<p><strong>I use it as an auto-complete and smart linting helper</strong>. It allows me to switch between languages almost on the fly: JS/TS, Python, Go and Bash scripts, in my case.</p>
<p>Depending on the task, it is either incredibly useful or a terrible mess for more serious <strong>code generation</strong>: It took me less than 15 minutes to build some React-based animations and SCSS styling changes. On the other hand, even with the tricks of leaving open other tabs with related source files (as context), at times, Copilot struggles to understand what I want to build; even with 3 line long descriptive comments. But it is still worth a try, as it is a decent speed boost for non-complex tasks.</p>
<p>A related task where it is proving excellent is <strong>writing tests for your code</strong>. It probably depends on the language, but for Javascript, I keep the file containing the class under test open and write the first one or two tests. Then I just write the starting `it("blablabla"`` line, and it auto-completes it with a perfectly valid body based on the test description.</p>
<p>The Github Copilot Chat feature is excellent, as it removes the need to ask GPT to roleplay a developer, etc., and can give back examples directly adapted to your programming language and even your open source code files. Try it if you haven't yet. <strong>For technical questions, it became my new "Stack Overflow"</strong>.</p>
<h3>ChatGPT</h3>
<p><strong>Learning languages</strong>: for English, I'd instead go to specialized sites, but for Swedish, it is a fabulous quick learning tool.</p>
<p>It is <strong>my new Google + Wikipedia</strong>.Knowing that it might not always be correct, as long as I ask it about topics that I know exist, the information has always been correct (I still fact-check everything, just in case). Or I directly got a <code>"up to my training data of xxxx, I don't know about that"</code> [1].</p>
<p>I also use it a lot for <strong>random, trivia-like questions</strong>. My "trick" is to think if my question is available somewhere on the public internet in trusted places. I'm confident it will adequately answer all my nature, physics, and similar science questions, but beware of more niche answers. e.g. it was able to very precisely answer the question "at the end of the first Dune book, which of the characters are still alive?". But then, when asked something about the second book, it confused some facts with other volumes and hallucinated.</p>
<p>I've also noticed it is prone to be too gentle, both here and in Copilot-related tasks. If you tell it it was wrong, it will try very hard to please you, often inverting the previous response, even if the new outcome is false/incorrect. This fact and some basic prompting skills are still required to some extent, but I think this is a matter of pure iteration and refinement until those details get solved.</p>
<p>Another use is to <strong>"spice up" specific messages</strong>: e.g. we hosted an internal hackathon at work, and I used it to "cheer up" all the announcements/updates I had to write. It might tend to overuse emojis, but you can also tell it not to use any. It is the same with making a sentence or paragraph more formal or more technical.</p>
<p>My last usage, often API-driven, is to <strong>summarize content</strong>: From <a href="https://github.com/Kartones/python/blob/master/youtube-summarizer/youtube-summarize.py">Youtube videos</a> to complete articles and PDFs, it is excellent at interpreting data, and, via API, you can set its temperature to 0, and then it will be less creative (aka, less prone to hallucinate). The resulting summary is sometimes repetitive and dull, but digesting a 45-minute video into a three-paragraph text is a great time-saving technique.</p>
<h3>DALL-E 3</h3>
<p>"In the past" (as if it were a decade ago 😉), I played with DALL-E and the first versions of Stable Diffusion. A nice toy, and an incredible helper for <strong>specific tasks like assisting in Dungeon Mastering RPG sessions</strong> (although Midjourney is probably better for both player and NPC portraits), but it was either too prone to flaws and imperfections or too direct copying artist styles.</p>
<p>But then, Microsoft quickly added DALL-3 to Bing as soon as OpenAI announced it, and wow, the results are way better now. The images have fewer artifacts/errors (but look carefully; they still do at times!), it understands the prompts way better [2], and the quality of the images can be outstanding with fewer attempts.</p>
<p>As an example, with decent but far from advanced prompts, I was able to help a family member <strong>design a small poster</strong>. It took us 30 minutes of back and forth through an instant messaging app, me generating the images and sending them, her replying with the best one, and other things to tweak/change. The results were quite good; we didn't need to buy any paid clipart or ask for professional help.</p>
<p>I've also used the OpenAI DALL-E 3 API. There, my experience is that the results are prone to flaws (e.g., missing body parts happens a lot), so <strong>I would wait to fully automate image generation</strong>, placing an intermediate human review and approval step in the workflow for now.</p>
<h3>Closing Words</h3>
<p>Usefulness aside, which is coming close to many science-fiction books regarding AI assistants in concept [3], what impresses me most is the mathematical and technical complexity. LLMs are a huge multi-dimensional Markov chain (oversimplification!), statistically queried, but the text2image diffusion models feel mindblowing to me; It feels magical that we have devised a way to teach computers to convert image patterns and fragments to series of numbers, and even more incredible if we factor that they learn from shapes ("a cat") and fragments ("with tiger stripes") to colors ("orange") and drawing styles that apply to the whole image ("pixel art", "coloring book"...).</p>
<p>[1] Pseudo-offtopic note: ChatGPT 3.5 is now reporting to have training data until Jan 2022, so they have advanced from the original Sept 2021 mark.</p>
<p>[2] DALL-E 3 overrides and enriches your prompts. Often, it is good, but if you want more fine-grained control, <a href="https://platform.openai.com/docs/guides/images/prompting">you can force it to not re-write</a>.</p>
<p>[3] Execution is still in the early stages, but I have zero doubt we'll get to a perfectly working speech-driven "user interface." Whether it is a single assistant or multiple ones, I'll leave it to futurologists.</p>2023 Wrap-up2023-12-27T19:50:00+01:002023-12-27T19:50:00+01:00Kartonestag:blog.kartones.net,2023-12-27:/post/2023-wrap-up/<p>Wrapping up the year, it would be good to write a short summary.</p>
<p>Lots of <a href="https://bazel.build/">Bazel</a> (and other build systems), tooling, and automation. Bazel is quite complex and surprisingly rough on some edges, but I think it is a very powerful tool.</p>
<p>I went through (and survived) two rounds of …</p><p>Wrapping up the year, it would be good to write a short summary.</p>
<p>Lots of <a href="https://bazel.build/">Bazel</a> (and other build systems), tooling, and automation. Bazel is quite complex and surprisingly rough on some edges, but I think it is a very powerful tool.</p>
<p>I went through (and survived) two rounds of lay-offs at work this year; technically, 3, but the middle was focused on a single product. I'm not going to dig into details or opinions, other than I'm quite unhappy with the tech industry as a whole.</p>
<p>Read and experimented with some of the basic foundations of LLMs, plus code generation and text and image generation (mostly ChatGPT and DALL-E 3). Despite being too brute-force based, I think LLMs and the AI topic, in general, can significantly change tech. From frequently using GitHub Copilot, to almost daily using ChatGPT [1], and helping friends and family with image-related tasks, it has already changed quite a few things in my everyday life.</p>
<p>Coded a decent amount of Javascript (but little Typescript) and Python (including Starlark, Bazel's flavor), and a bit of Go.</p>
<p>I'm ramping up on book reading (tech and non-tech, fiction and non-fiction), but it's one area I could do way more.</p>
<p>I also read a lot of articles, but I feel there is an information overload as of late. It takes a lot of work to keep up with everything, so I'm iterating on my sources, filtering criteria, and even time spent (e.g., reading a book instead).</p>
<p>Fewer courses watched, but more talks: Strange Loop, GOTO, InfoQ, and miscellaneous individual talks. But I miss the networking part of a physical conference.</p>
<p>I deleted my Twitter account. I don't want to be part of the crappy place that Elon is converting it into, so that party is over for me. For the moment, my only social presence is at Mastodon.</p>
<p>[1] I'm sure they are fully aware, but Google's biggest concern should be the fact that chat conversations with ChatGPT are a much better user experience than a search box. Of course, it's not yet useful in all scenarios, but one way or another, we'll get there.</p>An Entity Component System in Javascript2023-12-21T11:50:00+01:002023-12-21T11:50:00+01:00Kartonestag:blog.kartones.net,2023-12-21:/post/ecs-in-javascript/<p>Taking advantage of my Christmas holidays, one topic I had pending exploring was the <a href="https://en.wikipedia.org/wiki/Entity_component_system">Entity component system (ECS)</a> architecture pattern. It is used primarily in video-games, but it is fascinating because of the radical departure from object inheritance, heavily leaning into object composition instead.</p>
<p>One of the best ways to …</p><p>Taking advantage of my Christmas holidays, one topic I had pending exploring was the <a href="https://en.wikipedia.org/wiki/Entity_component_system">Entity component system (ECS)</a> architecture pattern. It is used primarily in video-games, but it is fascinating because of the radical departure from object inheritance, heavily leaning into object composition instead.</p>
<p>One of the best ways to learn is to a) read and then b) experiment, so I went and built a minimal (but representative) vanilla Javascript ECS implementation. </p>
<p>For the impatient, the code is available here: <a href="https://github.com/Kartones/ecs">https://github.com/Kartones/ecs</a>, and a basic HTML demo is here: <a href="https://kartones.net/demos/028/">https://kartones.net/demos/028/</a>.</p>
<p>I'll remark on a few technical details, but if you want to see how everything fits, the code is compact and easy to read.</p>
<p>I created three systems:</p>
<ul>
<li><code>InputSystem</code>: To handle (keyboard) input. It interacts with <code>PositionComponent</code> components, by modifying their velocity "vectors" and/or changing positions when the <code>Spacebar</code> is pressed (resets all entities to new random positions).</li>
<li><code>MovementSystem</code>: Updates <code>PositionComponent</code> components movement logic: update position based on velocity, or stop if at a boundary (edge)</li>
<li><code>RenderSystem</code>: Initializes the screen (an HTML canvas) and tells <code>RenderComponent</code> components to render based on their <code>PositionComponent</code> values.</li>
</ul>
<p>As you might have noticed, there are two components:</p>
<ul>
<li><code>PositionComponent</code>: Keeps <code>(x,y)</code> and a velocity vector</li>
<li><code>RenderComponent</code>: Keeps the "sprite" data</li>
</ul>
<p>And finally, a few managers:</p>
<ul>
<li><code>EntityManager</code>: Entities do not exist as a class; they are mere identifiers. The sole purpose of <code>EntityManager</code> is to generate the entity IDs and keep track of them</li>
<li><code>ComponentManager</code>: Keeps track of all components of each entity. When a system is going through an update sweep, queries this manager to ask for all components required; e.g., the <code>RenderSystem</code> asks for <code>PositionComponent</code> and <code>RenderComponent</code>, ensuring that any entity has both (or will be skipped)</li>
<li><code>SystemManager</code>: A simple list of all configured systems, plus an <code>update()</code> method that, surprise, triggers an update cycle on all systems</li>
</ul>
<p>And that is mostly everything! At first, I tried to plug in <a href="https://phaser.io/">Phaser</a> for rendering graphics and handling input, but it is already an ECS! So, instead of doing weird code to access some of the systems, I discarded it and implemented a simple keyDown handler for the input and an HTML canvas for the renderer. But Phaser looks so nice and well-structured! I'll try it as a complete game engine in the future.</p>The origins of LEGO Mindstorms2023-12-17T20:55:00+01:002023-12-17T20:55:00+01:00Kartonestag:blog.kartones.net,2023-12-17:/post/origins-of-lego-mindstorms/<p>I recently learned that around two years after announcing the <a href="https://www.lego.com/en-gb/aboutus/news/2020/june/lego-mindstorms-robot-inventor">Mindstorms Robot Inventor</a>, LEGO <a href="https://www.theverge.com/2022/10/28/23428766/lego-discontinue-mindstorm-educational-robots">discontinued the Mindstorms brand</a> in 2022.</p>
<p>It is sad because <a href="https://blog.kartones.net/post/two-decades-lego-mindstorms">I've always thought</a> LEGO Mindstorms was a great way to build robots by focusing on the creative and programming aspects while removing the complex hardware involved …</p><p>I recently learned that around two years after announcing the <a href="https://www.lego.com/en-gb/aboutus/news/2020/june/lego-mindstorms-robot-inventor">Mindstorms Robot Inventor</a>, LEGO <a href="https://www.theverge.com/2022/10/28/23428766/lego-discontinue-mindstorm-educational-robots">discontinued the Mindstorms brand</a> in 2022.</p>
<p>It is sad because <a href="https://blog.kartones.net/post/two-decades-lego-mindstorms">I've always thought</a> LEGO Mindstorms was a great way to build robots by focusing on the creative and programming aspects while removing the complex hardware involved in a non-LEGO robot.</p>
<p>Reading a bit about its history, it is surprising how old it is and its origin, so here are some highlights I found interesting:</p>
<ul>
<li>
<p>It all began with the <a href="https://en.wikipedia.org/wiki/Logo_(programming_language)">Logo programming language</a>, which was created in 1967! I used the the Turtle Logo Pascal library (<a href="https://cs.nyu.edu/~marateck/turtle.html">Turtle Graphics</a>?) to draw figures and spirals in high school.</p>
</li>
<li>
<p>The <a href="https://en.wikipedia.org/wiki/Lego_Mindstorms#Lego/Logo_and_the_Technic_Control_Center_(1985)">Technic Control Center</a>, in 1985, was the first combination of LEGO with a programming language.</p>
</li>
<li>
<p>"Logo Blocks" were the predecessors of "RCX Code" and later evolutions, a purely visual program control flow language, by adding and linking visual blocks that represented loops, conditionals, sensor values, and the like.</p>
</li>
<li>
<p>The first <strong>LEGO Mindstorms</strong> product appeared in 1998 (the Robotics Invention System, aka "yellow brick"), but the name comes from a 1980 book, <a href="https://en.wikipedia.org/wiki/Mindstorms_(book)">Mindstorms: Children, Computers, and Powerful Ideas</a>.</p>
</li>
<li>
<p>The yellow brick was the first model commercialized to the public, but before it existed both a red brick and a grey brick:</p>
</li>
</ul>
<p><picture><source srcset="https://images.kartones.net/posts/kartonesblog/lego_programmable_bricks.webp" type="image/webp"/><img alt="grey, red and yellow LEGO programmable bricks (from Wikipedia)" height="576" loading="lazy" src="https://images.kartones.net/posts/kartonesblog/lego_programmable_bricks.jpg" width="741"/></picture></p>
<p>Additional Resources:</p>
<ul>
<li><a href="https://cs.uml.edu/~fredm/papers/magical-machines.pdf">To Mindstorms and Beyond: Evolution of a Construction Kit for Magical Machines</a></li>
</ul>Content quality is suffering (as of late 2023)2023-12-02T19:00:00+01:002023-12-02T19:00:00+01:00Kartonestag:blog.kartones.net,2023-12-02:/post/content-quality-is-suffering-2023/<p>Lately, I've come to understand why GPT models avoided digesting content from later than September 2021 [1]: The amount of artificially extended written articles and videos is staggering; probably there are also more fully AI-generated cases, but I wanted to focus on human-originated cases. For me, it is more than …</p><p>Lately, I've come to understand why GPT models avoided digesting content from later than September 2021 [1]: The amount of artificially extended written articles and videos is staggering; probably there are also more fully AI-generated cases, but I wanted to focus on human-originated cases. For me, it is more than just a matter of wasting extra time when reading because there are whole sentences or paragraphs devoid of content or repeating for the sixth time the same point with different words. The form is also of poorer quality, making it harder to understand (which fails one of the main principles of writing, to communicate something!).</p>
<p>Let me mention two examples:</p>
<ul>
<li>Everybody knows that 95% of YouTube channel content nowadays is artificially extended to get extra displayed ad slots. As a specific example, a particular channel that some friends like watching seldom publishes videos shorter than 30 minutes, sometimes going as far as 90 minutes. The "short" ones are usually content that can be explained in less than 5 minutes. For the longer ones, at minimum, one could remove 1/3 of the length (interviews that get too pedantic, "in-depth reports" that iterate multiple times over each topic...). I did a test, and in a specific video (~25 mins), they mentioned one relevant term more than 20 times. This is why I experimented <a href="https://github.com/Kartones/python/tree/master/youtube-summarizer">with building a YouTube summarizer</a> using ChatGPT, and I use a fine-tuned variant if I check YT (which is rare).</li>
<li>When reading content in English, I have some leeway regarding initially wrong-looking texts, because I am not an expert in the language, so it might be a wrong interpretation. But when I read Spanish articles, I am way stricter, and it is degrading a lot outside main media sites: Half a page of buzzwords, abusing bolding text on almost every sentence (probably because not even the author can find relevant information otherwise), with sentences often cut in half, breaking the natural structure and forcing you to do extra cognitive work (maybe to give the impression of a longer text?), at times with non-sense words suspiciously looking like other more appropriate ones (LLM mistake?). And worst of all, if you read the text many times, any reasonable human being will notice something wrong.</li>
</ul>
<p>Everybody is free to write however they want. I have friends who run their texts through ChatGPT to make them sound more formal, and I've used it to generate more cheerful messages for Slack announcements, so it is not that I'm against their use; quite the opposite [2]. But people are forgetting the basics: <strong>make your content readable and understandable, and then, if you want, make it longer</strong>. Some books could be perfectly summarized in less than a single page, so it is nothing new!</p>
<p>For example, I currently use <a href="https://grammarly.com/">Grammarly</a> (premium) to proofread my blog posts and some emails. At work, I use <a href="https://languagetool.org/">LanguageTool</a>, which serves the same function [3]. They both have browser plugins and give you spelling corrections and suggestions about tones, false friends, partial or complete sentence rewordings for clarity... </p>
<p>Nothing beats careful human proofreading, but if you don't have the time or desire (I often don't, and simply click publish once grammar check is ok), at least try using suitable tools to increase legibility. It would also be nice to avoid "dark patterns" in writing online content; the tools I mentioned will probably flag most of them.</p>
<p>[1] Although I read somewhere that this might change soon. They probably devised an accurate enough way to detect artificial content to discard.</p>
<p>[2] The summaries on <a href="https://blog.kartones.net/">this blog's landing page</a> are also made by GPT (but revised by me), and I use ChatGPT very often for both general questions and as a Swedish tutor/teacher. I sincerely think that LLMs are a technical revolution in many ways.</p>
<p>[3] I'm considering switching to LanguageTool's premium plan, as they don't use your data for ML training. But if you are okay with that, Grammarly is excellent.</p>Tiny Markdown-Based Wiki2023-10-31T18:30:00+01:002023-10-31T18:30:00+01:00Kartonestag:blog.kartones.net,2023-10-31:/post/tiny-markdown-wiki/<p><a href="https://blog.kartones.net/post/note-taking-and-knowledge-base/">Earlier this year</a>, I settled on using markdown files to keep my notes around different topics. For editing and while using my computer, I am happy with <a href="https://obsidian.md/">Obsidian</a>, but at times I want to quickly check something (maybe from my work computer or the phone). I could pay for the …</p><p><a href="https://blog.kartones.net/post/note-taking-and-knowledge-base/">Earlier this year</a>, I settled on using markdown files to keep my notes around different topics. For editing and while using my computer, I am happy with <a href="https://obsidian.md/">Obsidian</a>, but at times I want to quickly check something (maybe from my work computer or the phone). I could pay for the sync features of the tool, but as we're talking markdown files and a few media contents, I decided to build a simple web alternative.</p>
<p>TL;DR is that you can check <a href="https://github.com/Kartones/tiny-wiki">tiny-wiki in GitHub</a>. It is a no-frameworks, HTML 5 + CSS + Javascript glorified markdown renderer.</p>
<p>As a summary, it:</p>
<ul>
<li>Fetches an <code>items.json</code> file containing a list of markdown files. Folders are treated as sections/subsections (supports up to one section and one subsection, so two folder levels), and the file name is treated as the Document name (and <code><h1></code> heading once rendered as HTML). The list of sections, subsections, and files is rendered at the left.</li>
<li>When loading a page, it fetches the markdown file, and then renders it client-side. I did some basic benchmarks, and it is faster to fetch the smaller markdown and render it, rather than pre-generating all the HTML files (at least on a decent computer or phone).</li>
<li>Also, when rendering a page, extracts the headings from the document and creates a navigable list at the right of the content</li>
<li>Supports light/dark theme (saving to <code>localStorage</code>)</li>
</ul>
<p>The whole Javascript code is less than 200 lines, so straightforward to understand.</p>
<p>It is mentioned in the README of the repo, but I used <a href="https://marked.js.org/">Marked</a> for transforming the markdowns (really fast, and very easy to extend/modify the tag renderers) and <a href="https://picocss.com/docs/">Pico.css</a> for the styling (I love it because without needing to add any classes already makes everything pretty). Be warned that the styling is probably not perfect. I built this and did some quick experiments, but that's all.</p>
<p>🦇 Happy Halloween 🎃!</p>On multi-tasking and high WIP2023-10-17T07:00:00+02:002023-10-17T07:00:00+02:00Kartonestag:blog.kartones.net,2023-10-17:/post/multitasking-and-high-wip/<p>This video details why multi-tasking, or having a high work-in-progress (WIP), is ineffective. The author explains it simply and clearly, demonstrated in multiple common scenarios. And yet, it is still an endemic problem we face at work too often.</p>
<p><iframe frameborder="0" height="379" src="https://www.youtube-nocookie.com/embed/3MxAUurD9gU" width="620"></iframe></p>Book Review: DOOM Guy2023-10-15T18:15:00+02:002023-10-15T18:15:00+02:00Kartonestag:blog.kartones.net,2023-10-15:/post/book-review-doom-guy-john-romero/<h3>Review</h3>
<p><picture><source srcset="https://images.kartones.net/posts/kartonesblog/book_doom_guy_john_romero.webp" type="image/webp"/><img alt="DOOM Guy book cover" height="200" loading="lazy" src="https://images.kartones.net/posts/kartonesblog/book_doom_guy_john_romero.jpg" width="133"/></picture></p>
<p><strong>Title</strong>: <a href="https://romero.com/shop/p/doomguy">DOOM Guy: Life in First Person</a></p>
<p><strong>Author(s)</strong>: John Romero</p>
<p>Let's begin with the end: I won't say that I did not enjoy reading this title because I did, all in all, like the 1980 to 1996 stories. But for someone who boasts multiple times about having an …</p><h3>Review</h3>
<p><picture><source srcset="https://images.kartones.net/posts/kartonesblog/book_doom_guy_john_romero.webp" type="image/webp"/><img alt="DOOM Guy book cover" height="200" loading="lazy" src="https://images.kartones.net/posts/kartonesblog/book_doom_guy_john_romero.jpg" width="133"/></picture></p>
<p><strong>Title</strong>: <a href="https://romero.com/shop/p/doomguy">DOOM Guy: Life in First Person</a></p>
<p><strong>Author(s)</strong>: John Romero</p>
<p>Let's begin with the end: I won't say that I did not enjoy reading this title because I did, all in all, like the 1980 to 1996 stories. But for someone who boasts multiple times about having an extraordinary capacity to recall past events in absolute detail, it is interesting to see what the book does <em>not</em> speak about. e.g., all we get from the Daikatana epoch is a series of founding and management issues and mistakes and a final <em>mea culpa</em>.</p>
<p>So, I will focus on the positive things instead, of which there are also plenty.</p>
<p>The contents of the book are laid out, according to my ebook reader, as follows:</p>
<ul>
<li>10% early life (until early 80s)</li>
<li>65% pre-id "dev life" & id Software (until 1996)</li>
<li>15% Ion Storm & miscellaneous (until 2001)</li>
<li>10% Up until 2022 (emphasis on his new DooM map packs)</li>
</ul>
<p>This means that there is a majority of content related to Commander Keen, Wolfenstein 3D, DooM, and Quake; I am adding Daikatana to the last one, as it used the Quake & later on Quake II engines.</p>
<p>This book represents an excellent tale of how, with effort and dedication, you can create great things, no matter where you come from. It might not be easy, it might take some time, but it is possible. We'll read about the first PC games and the abundant problems they posed, always limited by CPU speed, but also severely handicapped by primitive graphic cards. We'll also learn about the first steps of the <em>shareware</em> distribution system, and why John Romero and John Carmack got a lot of money, founded id Software, and then became very wealthy in their early 20s.</p>
<p>I grew up living the same PC evolution and playing the very same games they were creating, from Commander Keen and Wolfenstein 3D to DooM and DooM II, and Quake is my all-time favourite videogame, so I devour any article <a href="https://blog.kartones.net/page/reviews/">or book</a> that tells me more about them and how they were made. You won't be disappointed in that regard, there is plenty of internal information about building each title.</p>
<p>Many other geeky details are also fascinating, like why coding both DooM tools and the game itself in NeXT computers, or many of the features that Romero added to each version of the map editors, or the rare tools they would build (<code>"Carmacizing the maps"</code>, aka compressing) and insane work they'd all put (e.g., <code>"Michael Abrash had had to rewrite his highly optimized renderer eight times"</code>). There are also notes of humour and funny stories here and there.</p>
<p>The best part of the Ion Storm era is some good lessons that Romero states as some introspection-work outcome, primarily oriented towards managing people in a company, but a few are also related with being in the videogame production industry. And, of course, the whole thing is a cautionary tale about correctly picking co-founders (and deciding their share).</p>
<p>The final chapters, post-Daikatana era, lose momentum and are salvageable only because of the Sigil DooM maps part.</p>
<p>It was a decent read, which I wasn't sure what to expect and delivered in some areas, but did not on others. Just don't expect any shocking reveal regarding what you can already read about on the internet about id Software.</p>Reproducible Builds2023-09-24T21:00:00+02:002023-09-24T21:00:00+02:00Kartonestag:blog.kartones.net,2023-09-24:/post/reproducible-builds/<p>One topic, that I incorrectly though was always happening, was that compiling always generated the exact same output (the same bytes). <strong>This is not always the case</strong>. </p>
<p>I know about compilation modes, optimization flags and the like, so we're not talking here about those basic scenarios. We're talking about cases …</p><p>One topic, that I incorrectly though was always happening, was that compiling always generated the exact same output (the same bytes). <strong>This is not always the case</strong>. </p>
<p>I know about compilation modes, optimization flags and the like, so we're not talking here about those basic scenarios. We're talking about cases where running exactly the same flags, in the same environment, and against the same source code (let's say C++), generates a binary that works exactly the same, and yet has a different checksum (and differs in some bytes).</p>
<p>There are two big issues with this lack of output determinism, or as it is better known, lack of reproducible builds:</p>
<ul>
<li><em>Security</em>: How can you ensure that a binary has not been tampered with, if its signature changes?</li>
<li><em>Build Caching</em>: You will always get a cache miss if you always get a different binary </li>
</ul>
<p>My tiny research originated from discussing with a colleague why some Windows Visual C++ builds were not cached, when there were no apparent code changes [1] and the flags were not mutating.</p>
<p>The first thing that he found was that indeed, <strong>Microsoft Visual C++ (MSVC)</strong> is not deterministic by default. The following article will help you achieve it: <a href="https://nikhilism.com/post/2020/windows-deterministic-builds/">https://nikhilism.com/post/2020/windows-deterministic-builds/</a>.</p>
<p>Coincidentally, I read that <strong>Golang</strong> since 1.21.0 has a perfectly reproducible build toolchain. It was explained in a <a href="https://go.dev/blog/rebuild">blog post</a>.</p>
<p>At this point, I decided to check if there were more resources, and found that there is a <a href="https://reproducible-builds.org/docs/">Reproducible Builds organization</a>, with great general tips on what to look for in compilers, project files and the like, to achieve determinism.</p>
<p>And I was quite surprised to find that <strong>Java</strong> is also not deterministic by default, but with a twist: the bytecode is, but the <code>jar</code> files aren't. So here are some articles around that:</p>
<ul>
<li>generic reproducibility: <a href="https://reproducible-builds.org/docs/jvm/">https://reproducible-builds.org/docs/jvm/</a></li>
<li>with Maven: <a href="https://maven.apache.org/guides/mini/guide-reproducible-builds.html">https://maven.apache.org/guides/mini/guide-reproducible-builds.html</a></li>
<li>with Gradle: <a href="https://dzone.com/articles/reproducible-builds-in-java">https://dzone.com/articles/reproducible-builds-in-java</a></li>
</ul>
<p>As an extra note, these kind of non-deterministic behaviours can also happen on scripted languages like <strong>TypeScript</strong>/<strong>JavaScript</strong>, not when transpiling code, but when doing tree-shaking and/or bundling; See for example the multiple places where you can set flags to <code>deterministic</code> in <a href="https://webpack.js.org/configuration/optimization/">Webpack</a>.</p>
<p><br/></p>
<p>[1] Build avoidance is a different topic, so let's assume that there was <em>some</em> reason to trigger a compilation, instead of skipping the whole step and reusing a previously compiled artifact.</p>Book Review: At The Heart Of Management2023-09-13T07:50:00+02:002023-09-13T07:50:00+02:00Kartonestag:blog.kartones.net,2023-09-13:/post/book-review-at-the-heart-of-management/<p>Note: Free evaluation copy provided by the author.</p>
<h3>Review</h3>
<p><picture><source srcset="https://images.kartones.net/posts/kartonesblog/book_at_the_heart_of_management.webp" type="image/webp"/><img alt="At The Heart Of Management book cover" height="200" loading="lazy" src="https://images.kartones.net/posts/kartonesblog/book_at_the_heart_of_management.jpg" width="130"/></picture></p>
<p><strong>Title</strong>: <a href="https://www.goodreads.com/book/show/128182590-at-the-heart-of-management">At The Heart Of Management</a></p>
<p><strong>Author</strong>: Lino F. Ciceri</p>
<p>Disclaimer: I'm not a manager. I've led small technical teams in the past, but not departments or even companies for which this book aims.</p>
<p>After the remark, I'll begin by saying …</p><p>Note: Free evaluation copy provided by the author.</p>
<h3>Review</h3>
<p><picture><source srcset="https://images.kartones.net/posts/kartonesblog/book_at_the_heart_of_management.webp" type="image/webp"/><img alt="At The Heart Of Management book cover" height="200" loading="lazy" src="https://images.kartones.net/posts/kartonesblog/book_at_the_heart_of_management.jpg" width="130"/></picture></p>
<p><strong>Title</strong>: <a href="https://www.goodreads.com/book/show/128182590-at-the-heart-of-management">At The Heart Of Management</a></p>
<p><strong>Author</strong>: Lino F. Ciceri</p>
<p>Disclaimer: I'm not a manager. I've led small technical teams in the past, but not departments or even companies for which this book aims.</p>
<p>After the remark, I'll begin by saying that the book is interesting. I don't know how some of the themes will apply at (or collide with) different companies, but at least some chapters try to be different. There is also an overall attempt to add science, or at least use it as inspiration, to measure and orchestrate metrics, procedures and processes. </p>
<p>As I mentioned, this is a book about pure management: of people, of processes, of a company's mission, vision, and goals, of how to leverage research and innovation versus production, and even about ethics and behaviors, both internally and externally. But it aims to be different in a few topics, which I'll mention.</p>
<p>Extrapolating electromagnetic fields as market views, thermodynamics as a form of viewing impediments to change, and organizations as molecular bodies "more than the sum of their member atoms" are a few examples, sometimes even going as far as providing formulas to measure success. I don't know how applicable they are; thus, I can't judge them, but at least it is a different view, and nature is quite clever so why not try to imitate it (same as we do in areas like robotics)?</p>
<p>About the growth or decline of a business being always an exponential process, I am not so sure, as I've seen and know of quite a few companies that are stuck in the middle, not drowning but not going up much either, small and big, private and public ones. But my view is biased and limited, so that I can be wrong. </p>
<p>And the last point is that I appreciate the general theme of optimism in the book: aiming for "the common good", for "prioritizing helping others ahead of ourselves", for suggesting trying to avoid massive reductions in force/employee terminations, playing fair with the competition... All of this is admirable, but at least in my sector (tech companies), it is something that very rarely happens. I usually see companies prioritizing benefits (theirs and their investors') over anything else, employees included, as we can see from the 2022-2023 mass layoffs.</p>
<p>There are of course general and traditional management bits of advice, a few of them even I had heard about. Cross-domain thinking and holistic views I think are becoming more widespread, but it is good to see them remarked. And a good list of questions to ask yourself or the company executives to reflect upon and see how to steer a company.</p>
<p>Those previously mentioned uncommon topics are, I think, what the author means constitute the fundamental pillars of his "Timeless Management" framework. Using science and formulas and aiming to do some good, not only being selfish, in order to survive "forever". </p>
<p>In conclusion, it is a curious (innovative maybe?) approach to the classical company management.</p>