HNHacker News
TopNewBestAskShowJobs

jodersky

66 karma · joined November 8, 2019

Jakob Odersky

https://jakob.odersky.com/about

[first name]@[last name].com

submissionscomments
jodersky··on Looking forward to Git 2.56 – and 3.0
Another thing that becomes easier with change IDs is reviewing multiple related commits together, essentially "stacked pull requests".

If you treat a branch as your unit of review, then it becomes super difficult for someone to submit a chain of related changes. You'll be constantly rebasing your pull requests onto each other as you get feedback from dependent branches.

I heard that the github CLI recently introduced support for this, but since in git there's no concept of dependent branches (a branch isn't even an object in git, just a reference to a commit), I think this approach will always be clunkier than reviewing commits related by a change ID.

jodersky··on Looking forward to Git 2.56 – and 3.0
It's unfortunate that change IDs aren't considered. There was a discussion [1] in 2025, and it has resurfaced a couple of times since.

Basically, the idea is to attribute a new kind of ID to an initial 'change'. During review, or whenever a commit is rebased, the change ID is kept, whereas the commit of course changes. This allows tooling to identify all previous versions of a change, and is what enables "per-commit" code review à la Gerrit [2] (which IMO is a much better experience than the branch-review-squash model that GitHub normalized). It's also used in jj, although I'm not familiar with that.

As of today, any tool that wants a change ID needs to somehow encode it in commit message bodies. The proposed discussion was about making a change ID a standard header field that git would natively keep across rebases.

[1] https://lore.kernel.org/git/Z_OGMb-1oV0Ex05e@pks.im/T/#mf941...

[2] https://gerrit-review.googlesource.com/Documentation/user-ch...

jodersky··on The Twelve-Factor App (2025)
> I. Codebase (https://12factor.net/codebase)

> Multiple apps sharing the same code is a violation of twelve-factor.

I never understood why the 12 factor app is against monorepos. It seems completely orthogonal to the contract between an application and its execution platform, which if I understand correctly, is the main point of 12 factor.

jodersky··on Helm 4.0
I'm curious what the google cli is that you're referring to. Could it be kubecfg (https://github.com/kubecfg/kubecfg)?

I've used it in the past (for a quite small deployment I must say), but have been very happy with it. Specifically the diff mode is very powerful to see what changes you'll apply compared to what's currently deployed.

jodersky··on Scala 3 Migration: Report from the field
This might be a bit of a shameless plug, but because you ask :)

Regarding no sbt, I would highly recommend to have a look at the mill build tool https://mill-build.org. I personally find it very pleasant to use as a replacement for sbt, mostly because of the following points:

- it uses regular Scala code to define a build

- it isn't DSL-heavy like sbt, which means it's A) easy to debug by simple searching, and B) anyone unfamiliar can get a vague idea of what's going on at a first glance

- it is designed around a generic task graph and isn't centered around the JVM world (disclaimer: I'm helping with development, and recently first-class support for Python and JavaScript projects was added)

jodersky··on Scala 3 Migration: Report from the field
The article mentions they used an experimental language feature, which is enabled via a special compilation flag and came with a big warning from the start that it was in fact experimental and could be removed any time. I highly doubt that most people use any libraries that use those.

As a side note, I've personally had the experience of migrating several projects to Scala3 (when it was still called Dotty), and never had any issues with 3rd party dependencies, since Scala 3 is binary-backwards compatible with Scala 2.13

jodersky··on DHCPv6-PD – First Steps
AFAIK, it's not strictly true that unicast addresses are required to use a /64 network identifier.

It's common, almost necessary even, for environments with dynamic clients to use /64 subnets (precisely so that SLAAC works), but in a static environment it's perfectly fine to use prefixes larger than /64 (e.g. delegate a /80 to each individual host in a datacenter, for virtualization applications etc).

Hence, I'm wondering what the spec is you mention that is broken?

jodersky··on Researchers, please replace SQLite with DuckDB now
One data point that really highlights this is that it is used in the flight software in Airbus planes. This alone is a very strong indicator that it is extremely robust, and also that it will be around for a very long time. There's a whole list of additional industry use-cases [1] that support this claim even more.

[1] https://www.sqlite.org/famous.html

jodersky··on Ask HN: Who wants to be hired? (December 2023)

    Location: Lausanne, Switzerland
    Remote: yes
    Willing to relocate: no
    Technologies: compilers, distributed systems, developer tooling and devops. 15 years of experience in Scala, deep knowledge of the JVM. Also multi-year experience with Python, C, C++ and open to any other language.
    Résumé/CV: https://www.crashbox.io/cv.pdf
    Email: in the resume
jodersky··on The cost of cloud, a trillion dollar paradox (2021)
> I think the biggest thing is that the minimum extra spend if you want in house managed infra is basically the salary of a full time sysadmin + hardware costs.

The cloud promises to make admin tasks easier, however I have never seen it eliminate the role of a sysadmin in practice. In my experience, most organizations that run their infra on a cloud still have dedicated admin roles (often called "DevOps" or infra teams).

Hence, I think that the claim that a sysadmin's salary is an extra expense for self-managed infrastructure is exaggerated. You may need more sysadmins for achieving the same features in a self-managed setup compared to the cloud, but it is not a linear scale.

jodersky··on Scala isn't fun anymore
I recommend to have a look at Mill. It's versatile, built on simple foundations, and implements many concepts from general-purpose build tools such as Bazel (but of course it was designed for Scala). It's easy to call it from various scripts too, and doesn't require you to design your project around your build tool.

At work we've used mill to first replace sbt and then also gradle in another project, and haven't looked back. It worked out-of-the-box for our JVM projects, and we trivially wrote custom "rules" for integrating cmake-based C++ projects into the build.

jodersky··on Scala isn't fun anymore
Seconded. Mill is a very versatile build tool. It mainly focuses around modeling builds as DAGs of tasks, and thus allows you to only rerun what is necessary after changes. Other tools like Bazel are built around this model too, but IMO Mill has "taste" in the way it is configured. It also gets out of your way, you can seamlessly integrate it into various shell scripts, and you don't need to make your project revolve around your build tool.
jodersky··on Scala isn't fun anymore
I find that one of the best things about using a managed runtime such as the JVM is the ability to get stack traces when things go wrong. When debugging, it is a considerable time saver to be able to determine the causality chain that lead to a specific failure.

Unfortunately, all libraries that abstract concurrency on an application-level break the ability to get meaningful stack traces. At least all the ones I know of, including ZIO, Akka, Monix, plain Futures, etc. I know that there is tooling to counteract that (such as the abstractions used in distributed tracing), but that's again on the language level.

In my experience, for all but the most advanced applications, the debuggability advantages of using linear code outweigh the performance advantages gained by abstracting over execution contexts. Thus, I would posit that concurrency is best dealt with on the platform, not the language level, especially when starting a project.

Of course there are some situations where a library can make some concurrency task appear trivial, but as long as there is no good tooling, the time saved using beautiful abstractions tends to be paid back 5-fold when those abstraction break (which they often do as an application grows).

jodersky··on Monads are a class of hard drugs
I usually tell people that monads are an abstraction which encourage writing code with less branches.

Consider the following code where you would like to multiply a number by two, but this number is potentially undefined:

    var x = ... // a number or null
    if (x == null) return null
    else return x * 2
Now, imagine if x were a list containing zero or one numbers (if the number is undefined, the list is empty). In this case, you could refactor the code as follows:

    var xs = ... // a list of zero or one numbers
    return xs.map(x => x * 2)
The advantage of the second snippet is that there are no branches, thus making it easier to reason about the code.

Thus, in order to understand 80% of their utility in 20% time, I can recommend that you think of a monad as a wrapper around a value which allows you to treat special cases uniformly. In this case, a list of one or zero items. Of course there is more to it, but I this is usually enough to get people to stop worrying and interested in exploring more.

jodersky··on OpenSMTPD
I'm a very happy user of Maddy (https://maddy.email/). It's a single executable that contains everything you need for a send-and-receive email server, including all modern anti-spam features. In my experience, the configuration is simpler than Postfix, Exim and OpenSMTPD, and falls back to sane defaults.

Another nice feature is what I would call its architecture: it does not try to be a service manager (instead, you are supposed to spawn it from your own favorite service manager, be that systemd, docker, or anything else, and you can hence really lock it down), hence it does not require root to run and does not rely on using system accounts by default.

I've only used it for very basic setups, but for those I can highly recommend it.

jodersky··on A Summary of OAuth 2.0 Attack Methods
Yes indeed, you are right that this is not part of the implicit flow mechanism.

AFAIU, the recommendation from OAuth 2.1 is to drop the use of implicit flows in web apps and instead rely on code flows with PKCE. The idea would be that the web app registers itself as a so-called "public client" (see https://oauth.net/2/client-types/) when it is loaded and then uses the standard code flow with PKCE.

jodersky··on A Summary of OAuth 2.0 Attack Methods
There's an OAuth 2.0 extension called PKCE (https://oauth.net/2/pkce/) which mitigates this issue, and from what I understand it will be mandatory in OAuth 2.1.

Essentially, the idea behind it is that the client (the web app in this case) dynamically registers itself with a secret at the authentication server. After receiving the code, it uses a hash derived from the secret to authenticate itself. An attacker who intercepts the authorization code, would not be able to exchange it for a token, since they don't have the secret. Section 1.1 of the RFC (https://datatracker.ietf.org/doc/html/rfc7636#section-1.1) has a very concise and clear explanation.

jodersky··on Ask HN: Books that teach you programming languages via systems projects?
Hands-on Scala Programming (https://www.handsonscala.com/) is a great way to learn Scala. It's down-to-earth, project-based and focuses on the practical side of the language.
jodersky··on What Does My Site Cost?
It seems expensive at first sight, but the $10/GB are world-wide, and limited to $60 per month.

It's not something I would recommend as a substitute for wifi, but definitely worth it if you travel to multiple countries, and don't want to deal with getting and/or swapping sims at every destination.