The impossibility to maintain Atom

Atom Editor was, and still is, an amazing piece of technology. It was the first practical example of web technologies running locally, applied to a really hard problem: text editors. It it was, and still is, darn good at handling code.

But it’s hard, close to impossible, to maintain as the way it is. I want you to take all my opinions with a grain of salt, because these represent my own ideas and feelings on the project – I’m not a full-time Atom developer, nor I intend to be one. I just closely followed its development cycle, helped find bugs and problems in the first editions, and I still am in love with the editor, even when it’s clearly dying.

And while I would love to modernize the editor, making some PRs and fixing some issues, it’s close to impossible to do it. I believe the problem lies on the fact that Atom was an editor, and then Electron was extracted from it. I made the same choice on Chlorine too: I first made the plug-in, then extracted REPL-Tooling from it. Even on a WAY SMALLER codebase (Chlorine), this was HARD: there are still internal, private data that is used inside Chlorine that is not on REPL-Tooling.

Atom is the same. The “setup project” for Atom (prepare Electron, parse cmdline args, etc) is INSANELY huge. There are insane cyclic dependencies (TextEditor depends on components, UI, etc, and these depends back on the editor), there are NPM modules that depend on the editor (so you have code living in Atom that is used on NPM packages, and these also access internal state instead of going thought the public API) and there are outdated web features. There’s also some insanity happening: using newer versions of Node.JS got me 404 trying to run npm install, and even using the node version that Atom says to use in the documentation (that’s also NOT the current LTS version of node, mind you) didn’t work reliably. The only way I was able to install all dependencies was by running yarn install FOUR TIMES, and that did the trick (I got a different error every try, but at least, it worked).

But the problem is not this one: there’s simply too much code that lives “outside” Atom.
(more…)

The infinite arrogance of software developers

Yeah, sorry for the bold title, but sometimes I get tired of software developers expecting they figure out the secrets of the universe. And let’s be honest: at some time in my career, I was one of them. Sometimes by accident, sometimes… not. Anyway.

First, a little disclaimer: this post is not targeted at anyone in special, and I’ll not mention anyone here – just quotes, slightly modified. Anyway, although I love my profession, sometimes it feels like we’re this programmer guy from XKCD:

I'm here to solve it with Algorithms, then six months latter: wow, this problem is really hard (Megan: You don't say?)

There are LOTS of things that bother me at this programmer mentality, so I’ll separate this post into multiple sections. If you’re reading this and feels like it’s a personal attack against you, please don’t – I’m not really attacking anyone, just trying to change a toxic mentality that poisons our abilities to be better professionals, people, and human beings.

“Not a real programmer”

The first one is classic: people define what a “programmer” is, based on their own experiences and expertise, and dismiss people that don’t fall into their categories. Wikipedia, for example, defines Computer Programming as:

Computer programming is the process of designing and building an executable computer program to accomplish a specific computing result or to perform a particular task

As for the “Computer program part”, Wikipedia defines as:

In imperative programming, a computer program is a sequence of instructions in a programming language that a computer can execute or interpret. In declarative programming, a computer program is a set of instructions.

So it’s hard to find a good definition on what programming is, but if we try to merge the two explanations from Wikipedia, we get that, to program a computer, you have to design an executable “sequence of instructions” or “a set of instructions” so that you can accomplish a specific result or perform a particular task.
(more…)

Advent of Code in SQL – Day 01

Ok, this year I decided to try the Advent of Code. But to level up my SQL game, I decided to do it purely in PostgreSQL. No stored procedures, no tables, just pure logic over SQL (or, at least, PostgreSQL-flavored SQL). I’ll also try to not use PG specific datatypes like JSONB or Arrays/Ranges, but I can’t promise this – the challenge is already hard with the way it is.

So, I decided that the input will be a single table called input with a single record and field, called input. This means that I have to split the input in some way – I’m currently using regexp_split_to_table(input.input, '\n') to generate a table with all the lines when this makes sense.

So, day 1. The first thing is to generate the input:

WITH input AS (SELECT '199
200
208
210
200
207
240
269
260
263' AS input)

The Day 01 problem is kinda simple: you compare a row with the next one and when the next one is greater, you add 1 to a result. So in this case, we do need to split the input into numeric rows. There are two ways of doing this: you either first split then cast, or split and cast in a single query. The first one is easier, so let’s go with that:

WITH depths_as_str as (SELECT regexp_split_to_table(input.input, '\n') depth FROM input)
  , depths as (SELECT depth  :: integer FROM depths_as_str)

(more…)

Performance optimizations in Reagent – part 2

Have I mentioned that it’s a nightmare to install React Devtools in Electron? Turns out, it’s worth it. But it’s still a pain. If you want to try, you’ll need to first install the extension in a chrome-based browser (like Brave, the one I use) and then install it by code. At Chlorine, what I did was to copy the whole extension folder to a devtools directory and then changed the script to load electron to the script below (see the BrowserWindow.addDevToolsExtension):

const path = require('path')
const {app, BrowserWindow} = require('electron')

app.on('ready', () => {
  let browser = new BrowserWindow({
    width: 900, height: 600,
    webPreferences: {nodeIntegration: true}})
  browser.loadURL(path.join('file://', __dirname, '/index.html'))

  BrowserWindow.addDevToolsExtension('./devtools')
})

Originally, the React Devtools was installed at ~/.config/BraveSoftware/Brave-Browser/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.21.0_0 (tilde is my home folder). If you’re trying to install on Atom editor, you’ll have to open developer tools and issue the following script:

r = require('remote')
r.BrowserWindow.addDevToolsExtension('./devtools') // or the right directory

This command will fail, but somehow when you reload Atom, the React Devtools will be there. There’s only one feature that I use – highlight which elements were updated. And that’s where our performance tuning starts again.
(more…)

The magical wonders of programming with pure data

I’ll start with a disclaimer – if you’re developing in ClojureScript because of performance, you’re doing the wrong thing. Although a Clojure code can be really close to Java performance, ClojureScript simply can’t match JS performance – specially because in Javascript, the fundamental data structures like arrays, sets, and objects are implemented in a faster language, and as of today, no “user space” data structure can get even close the “native” ones. And, let’s not forget that JS is slower than Java.

So, if you want to beat JS performance in ClojureScript, you have to make use of what ClojureScript offers you – the REPL, the fast experimentation, and the wonderful experience of programming with data. So, this is a tale of a huge performance improvement that I’m currently working in Chlorine.

Rendering EDN

In Chlorine and Clover, when you evaluate something, the result will be rendered in a tree-like way at the console. This works quite well for Clojure, because UNREPL makes structures that are too big small, and you can query for more data. So far, so good.

In ClojureScript, Clojerl, Babashka, etc, things are not so good. Big data structures will be rendered fully on the view. They can lock or crash your editor, they can occupy all your memory, etc. The reason for that is that tree structures are hard – when you’re rendering the “parent”, you don’t know what the children will be. Currently, in Chlorine, rendering (range 80000) locks my editor for 4 seconds until it calculates everything, layouts all data, etc… and I wanted to change this.

Reagent vs Helix vs React

I was always intrigued on how much performance hit I get when I use Reagent’s Hiccup data structure instead of React objects – after all, there must be some performance problems, right? After all, that’s the promise of Helix – to not pay this performance hit because you’re closer to what React wants.

So, first things first: profiling Javascript inside Electron IS A NIGHTMARE. I decided to install React Devtools extension on Electron (inside the Atom editor) but that got me into so much trouble, false-positives, wrong profiles that I ended up deciding against it and simply used the “performance” tab to do my profiling. There, I could see batching.cljs hogging my performance, so the next move was easy – move away from Reagent and use Helix.

Except… that Helix uses some macros and I ended up doing the code in React. My testcase was simple: render a vector of 80000 elements and see how it would perform, obviously without all the bells and whistles that Chlorine offers today (otherwise this experiment would be waaay longer). And that’s where things get surprising: with Reagent, I was hitting 1800ms of scripting, and about 120ms of rendering. With React… 1650ms of scripting, and about 200ms of rendering. I decided to do more benchmarks and probably because of OS caching, warm-up, or whatever, the results got even closer, with Reagent sometimes performing better than React – but still too slow.
(more…)

Rebirth of the idea of a Hackable Code Editor

So… Atom is in zombie state. Almost everything kinda works but not 100% works so the idea of a “Hackable Text Editor for the 21st Century” is almost dead. LightTable is buried, and it was not as hackable as Atom. And there’s VSCode – a closed-source, telemetry enabled, Microsoft controlled editor based on an open-source model that’s kinda the Webkit model – you have to fork the editor and make your changes, because they control the available APIs, the way that the editor is going, etc.

So what we have now? To be honest, not much. There’s emacs and Vim/NeoVim, but these are all text-based and have both people that love them and people that hate. It’s also not that easy to make plug-ins and configurations (one you have to learn elisp, and the other you can use a mix of multiple languages like VimL, Lua, Node.JS, Python, but they all feel “out-of-place”.

Let’s try to make a new editor? Maybe that’s insanity, so let me tell you what I have in mind:
(more…)

The state of JS in 2021

So… I recently found out that I had no space left on my SSD. When I tried to debug what was consuming my space, my projects folder were the culprit. How? I mean, I take photos, store them in RAW format, so how source code can be consuming more than my photos?

Turns out that by running rm -Rf (find -name 'node_modules'), (FISH shell) I was able to free 20gb of space!

So… let’s see how bizarre is the Javascript ecosystem in 2021.

Strangely big libraries

Sometimes, when I have to generate projects, they ask me to install yo. Yo is just a CLI to run generators – it does not include any generator. Yo occupies 89mb of space in my disk. Installing the react-webpack (manually by running npm i generator-react-webpack, because otherwise yo will try to install globally) means that your node_modules now occupies 180mb.

Let’s thing a little bit about this number: Windows XP, minimalist install without any add-on, requires 1.5gb of space. So a SINGLE GENERATOR occupies 12% of a full operating system.

So, create-react-app is more gentle – it just installs under 5.3mb. Generating a react app creates a node_modules folder with… 242mb. One of the dependencies is global-modules, that is just a single file with an if to define how to call things. It’s also only used in a single file – react-dev-utils/printHostingInstructions.js – in the folllowing code:
(more…)

The end of an era: goodbye, GitHub

We all knew that Microsoft would destroy GitHub. Well, I hope we all knew. I knew it too, but somehow, I thought: it doesn’t matter. Maybe they’ll add some commercial features, maybe they’ll force some integration over VSCode or Visual Studio, but anyway, I didn’t think, at the time, that they’ll be able to make something really bad about it.

This ends now.

Microsoft (I’ll not use GitHub anymore here. I’ll keep GitHub for Atom, probably, but that’s how far I’m willing to go) decided that “public repos are reusable pieces of software” regardless of license, with their “Copilot” product. Yes, people are saying that’s legal, fair trade, blah blah blah. I don’t buy it, and I believe it’s only because it’s Microsoft that they are speaking like this. Every other system that inputs <copyrighted-content> and outputs <content>, when the input and output are the same “kind” (music, painting, code, poetry) needs to be aware of the original license, and that’s final. In fact, every tool that tried to do this in the past WAS victim of copyright strikes – so why Microsoft is not? In fact, there’s public code that’s not open source on Microsoft’s servers. If they are so sure that it’s not a “derivative work”, why didn’t they train their ML with private repositories? With Microsoft’s own private code? The answer is obvious – only the fool don’t want to see.

Anyway, I’ll be removing all code from Microsoft starting now. Unfortunately, there are issues to code cooperation and other things if I decide to self-host a solution, so until Gitea allows for federated content, I’ll got with Gitlab. I’ll start with Chlorine, Clover, and similar projects like REPL-Tooling, Duck-REPLed and Vision. Then, maybe I’ll start moving things on demand (after all, all code that EXIST today was slurped by Microsoft already, so why should I bother removing the damage that already was done). So, here I’ll try to document my process:
(more…)