David Rothlis, a software engineer, writes about Emacs, SQLite schema migrations, build systems and software testing.
HN commenters recommend his Emacs tutorial, cite his declarative SQLite migration method for their own use, and link his Ninja build benchmarks.
I'm a moderately experienced Emacser - been using it heavily since 2009 (first encountered it in 2003). I have written a few small extensions and contributed features and bug fixes to bigger ones.
Credentials established, I cannot recommend this tutorial enough:
https://david.rothlis.net/emacs/tutorial.html
He walks you through most of the core of what makes Emacs great by showing you how to make a change to a project in the idiomatic Emacs way.
I would have learned it years faster had I started there.
Beyond that, learn basic Emacs keybindings via the tutorial, as others have suggested.
I started in Emacs but installed evil-mode a few years ago and have never looked back.
I do not recommend Spacemacs. Install the tools you want as you find you want them, so that you know what's doing what, and so you have a decent chance of knowing what broke things when something stops working.
Keep your packages in version control as part of your .emacs.d repository. That keeps updates and deleted packages from screwing you.
Use "use-package" (https://github.com/jwiegley/use-package) for configuring what you install. It's written by one of the Emacs maintainers and will help you do things right by default.
I'm not the best Emacser out there, but if you're curious, my config is on my GitHub account: https://github.com/NateEag/.emacs.d
Happy hacking.
I should rephrase, by dependencies I mean third party dependencies. That is on the build system not the compiler.
And make tends to fall significantly behind Ninja in my experience for cold builds. Here’s a post from someone else that echoes my experience https://david.rothlis.net/ninja-benchmark/ but for a sufficiently complex project even a well tuned make build is about 20% slower on CI, which is about 10-20m per build.
It also seems like you’re giving make the benefit of the doubt when it comes to “most being badly written but my own is great”, while simultaneously deriding cmake without giving it the same benefit.
But to your larger point, and going back to my C vs other languages comparison (let’s pick C++ for arguments sake). Yes Make can do it all, but even by your own statements it requires doing everything correctly and there’s significant room for error. CMake makes the trade off of abstraction for a more consistent experience with minimal work.
This is similar to C and C++, where yes C can (1) do much better in the very very specific right hands, but (2) it can also become an unwieldy mess. C++ with RAII may seem perplexing from the lens of only accepting the former and not the latter. It lets people spend their time elsewhere on the system.
This is an interesting approach to this problem.
I like the idea of building the new schema as an in-memory database. You could even go a step further and compare them using a SQL query that joins across the two databases (SQLite supports this, it's pretty neat).
I'm a bit nervous about how edge-cases might screw things up, but a nice thing about SQLite is that backups are really cheap so I guess you can protect against any risks by creating a backup before running this script.
My preferred approach to database migrations is the one implemented by Django: migrations are a sequence of transformations stored in files on disk, and the database includes a table that says which of those migrations have been applied. This keeps everything in version control and means there's no chance of the wrong migration being applied in the wrong way.
It's quite a bit more work to setup though. I don't have my own Django-style migration system for SQLite yet and I really need one.
I really love how clean and short the implementation of this is! https://david.rothlis.net/declarative-schema-migration-for-sqlite/migrator.py
I wonder what the appeal of having the build tools written in JS is, as performance is key here. Spoilers on the article:
> Rebuilding our seller tools, which previously took almost a minute on every request, now takes under 30 seconds when we’re starting a fresh compiler, and subsequent requests take only a second or two.
According to [0], esbuild is orders of magnitude faster than we pack. The speedup advertised is from 60s to hundreds of ms. The article talks about 12k js files, while according to [1], 4 year old hardware could handle an out-of-date check in less than a second on the entire code base if using a tool like make.
Im coming at this from an outside perspective, but even the results sound like they could be substantially faster? That said, it's an interesting article and I enjoyed reading it!
[0] https://esbuild.github.io/.
[1] https://david.rothlis.net/ninja-benchmark/
What do you think of the approach that pg_roll takes?
Seems like the top contenders, at least for Postgres, are:
sqldef: https://news.ycombinator.com/item?id=46845239
pgschema: https://github.com/pgschema/pgschema
pg_roll: https://github.com/xataio/pgroll
atlas: https://github.com/ariga/atlas
grate (minimal SQL-based migrations): https://grate-devs.github.io/grate/
pg-schema-diff: https://github.com/stripe/pg-schema-diff
results: https://github.com/djrobstep/results
https://david.rothlis.net/declarative-schema-migration-for-sqlite/
There are actually a bunch of external tools that offer declarative schema management flow. Personally I agree that that the overall flow should be external to the DB, but it would be useful if databases could offer more built-in functionality in this area to make these tools easier to write.
For sqlite in particular, check out https://david.rothlis.net/declarative-schema-migration-for-sqlite/ and https://sqlite-utils.datasette.io/en/stable/python-api.html#transforming-a-table