Hacker Newsnew | past | comments | ask | show | jobs | submit | lutzh's commentslogin

I use Hyvor Talk - https://talk.hyvor.com - for ad-free and privacy respecting commenting on my blog. I really wanted something that I can just use as a service, not host anything myself. But it's quite expensive.

If I where to ditch it to save the money, I'd look into integrating Mastodon into the page, I saw somewhere that they used Mastodon as their comment system (it's basically a thread on Mastodon that is embedded in the blog page).


12€/month minimum, that's expensive. It's ok for a professional website with loads of comments but for my personal blog, I'd rather not have comments.


I'm sure rv is great, but am I the only one who needs one such tool not only for Ruby, but also Python, JavaScript, and Java, at least, and finds it weird to run 4+ of those?

I put my hope in mise-en-place - https://mise.jdx.dev

What do people think? One tool per language, or one to rule them all?


We've been using mise since it was called rtx at $DAYJOB, and it's caused many a headache (mostly around upgrades/backcompat/etc.). We use it both on dev machines and in CI. In spite of that, it’s decent at what it does, and I wouldn’t soon replace it with individual version managers, given that we have similar needs.

However…more than once we've seen language runtimes that used to be available exclusively via plug-ins be migrated to be internal to mise, which broke everyone's setups in strange and hilarious ways, and caused countless hours of debugging.

Less bad overall than using individual runtime version managers for sure. But the next time mise costs us a bunch of hours fixing multiple engineers' setups, I intend to find another solution, even if that means writing my own. It’s burned us nearly one too many times.


Do you have any examples what tends to break? We used pyenv/rbenv/sdkman etc. individually, then moved to asdf and now arrived at mise. Not using yet for CI just developer stuff and so far didn't have issues. But this is quite recent for us, so didn't have to deal with upgrade issues yet.


We manage mise itself via homebrew. Sometimes when upgrading mise itself, it doesn’t seem to handle being upgraded gracefully, and loses track of installed runtimes even if we manually kick it in our upgrade scripts. Restarting the shell entirely seems to be the only way to fix it.

That, and with Ruby, Node, and at least one other language/tool IIRC, when support for those things moved internal, we had to make a bunch of changes to our scripts to handle that change with effectively no warning. That involved checking to see if the third-party plug-in was installed, uninstalling it if so, and then installing the language based on the built-in support. In the meantime, the error messages encountered were not super helpful in understanding what was going on.

I’m hopeful that these types of issues are behind us now that most of the things we care about are internal, but still, it’s been pretty annoying.


I think it's probably for the best to have a different tool for each language/platform. Not every language or platform matches feature for feature in that the options will already be different for each language, and you're likely to have such a "universal" tool come up short in support of one language or another.

I really appreciate cargo a lot for what it brings, even if it's calling different tools under the covers. Similarly, I appreciate deno in that it brings all the tooling and the runtime in a single executable (box). I've migrated most of my scripting to TypeScript using deno at this point because of that distributive ease. Even if the shebang itself is a bit sloppy.

Aside, would be cool to have a VS Code extension that would to file type detection based on a shebang at the top of the file. Making it easier to do extensionless script files with language support.


In theory it would be nice to have one tool for all languages but I think it's never going to be practical because programming languages can be different in arbitrary ways. I can't imagine how the same tool could ever be ergonomic for managing projects written in C++, Scheme, Haskell and Bash for example. Mise (and other tools for managing development environments like Flox and asdf – I prefer Flox myself) only implement a subset of the features of languages specific tools like cargo/uv/rv. For example cargo can do all of this out of the box (and you can also extend it with more subcommands):

* manage dependencies

* format and lint code

* publish package on crates.io

* open the project documentation

* install binaries

* build/run the project

* run tests

* run benchmarks

Uv/rv don't (yet?) do all of that but they also manage Ruby/Python versions (which is done separately by rustup in Rust).


I'm a happy long-term user of asdf. https://github.com/asdf-vm/asdf


The real selling point of mise imo is that it handles more than just languages - including automatic postgres setup in your dependencies is great)


The only thing I know about “good system design” is that it doesn’t exist in the abstract. Asking whether an architecture is good or bad is the wrong question. The real question is: Is it fit for purpose? Does it help you achieve what you actually need to achieve?

I could nitpick individual points in the article, but that misses the bigger issue: the premise is off.

Don’t chase generic advice about good or bad design. First understand your requirements, then design a system that meets them.


... that is how you achieve a good design (for the time being).


For all the Rubik's Cube enthusiasts here: here's a two-dimensional one in JavaScript - https://www.huehnken.de/games/circles/

Also a solution looking for a problem, maybe.


I looked and Flix a while ago and found it really interesting - so much so that I wrote an article "Flix for Java Programmers" about it. Might actually be a bit outdated by now.. need to look at Flix's recent development again.

But if you're interested: https://www.reactivesystems.eu/2022/06/24/flix-for-java-prog...


Cool blog post! With your permission, I would be happy to add it here: https://doc.flix.dev/blog-posts.html

The language has improved a lot in the years since the post. In particular, the effect system has been significantly extended, Java interoperability is much improved, and some syntax have been updated.


Heads up, the links to Paul Butcher's datalog posts are broken. The series can be found here now: https://paulbutcher.com/datalog1.html


Thanks-- I fixed the links!


Thanks! And of course you have my permission, I'd be honored if the post was included in that list.


Wow what a gold mine your blog is. It’s like a more elaborate and well thought through version of thoughts that have been torturing me for years. Looking forward to reading it all.


Wow, thank you so much, that's flattering. And motivating - I shall start blogging again this month, and try to stick to a monthly cadence. Make sure to subscribe to the RSS feed or follow me on Bluesky or Mastodon, to get notified for new posts :)


In the Unison language, code is stored in a database, with a hash code of its content as the key. Quoting https://www.unison-lang.org :

A new approach to Storing code. Other tools try to recover structure from text; Unison stores code in a database. This eliminates builds, provides for instant nonbreaking renames, type-based search, and lots more.


Thank you for your kind words!

> Yes, sort of, but mostly no. Events do not "trigger" anything. The recipient of an event may perform an action in response to the event, but events cannot know how they will be used or by whom.

I don't see the difference. Maybe it's a language thing. But I'd say if a recipient receives an event and perfoms an action as consequence, it's fair to say the event triggered the action. The fact that the event triggers something doesn't mean the event or the publisher must know at runtime what's being triggered.

Regarding your suggestions, I think your proving my point. Of course the whole "there are two types of.." is a generalization, but given that, you seem to fall in the first category, the one I called "DDD engineer/architect".

My response to the first three would be: Why? I know some literature suggests this. I've applied this pattern in the past. And I wrote "This is totally legitimate and will work.". But we also need to ask ourselves: What's the actual value? Why does the kind of event / the business reason have to be encoded as the name/type of the event? Honest question. Doesn't having it in the event payload carry the same information, just in a different place?

I don't want to be following what might be seen as "best practices" just for the sake of it, without understanding why.

I know of a few systems that started of with domain events that were named & typed "properly" according to the business event. And after a while, the need for wide events carrying the full state of the source entity arose. If you look at talks and articles from other EDA practioners (e.g. the ones on https://github.com/lutzh/awesome-event-driven-architecture#r...), you'll see that's not uncommon. This regularly leads to having to provide the wide events in addition to the "short" events. This is extra effort and has its own drawbacks. I just want to save the readers the extra work.


>Thank you for your kind words!

You're welcome, sorry for the delayed response.

>>...Events do not "trigger" ... >I don't see the difference

Yes, sorry, I'm being pedantic without context - to the uninitiated, the expression "events trigger actions" may be confusing, as it implies that events are active/actors/participants with 1:1 correspondence with reactions, omitting the recipient's agency.

>"two types of..."

...meh; I am/was both, and many other roles, but you are correct in that I hold the problem/solution domain as primary, and prefer to keep the implementation domain out of it as much as possible.

>Doesn't having it in the event payload carry the same information, just in a different place?

Yes, grouping and filtering is absolutely 100% functionally equivalent. But it is not free.

>Why?

Thanks for asking!

BookingUpdated(Reason) looks to me like an unnecessary coupling/corruption of the implementation model and domain model. This may cause additional cognitive load (user confusion/search/explanation) and possibly impact the event-routing mechanisms significantly.

For example:

* a consumer desiring only SeatReserved events will not find that as a topic. Instead, they will have to (unnecessarily) learn something about the implementation model (BookingUpdated:Reason==SeatReserved) in order to find what they want.

Slightly annoying, maybe no big deal w/better topic search or docs, just one example of a tiny unintended consequence.

* where is the selection/filtering performed? broker or consumer? Filtering is probably not free for a single-topic-per-stream implementation; something pays the price for it.

Possibly also no big deal under ordinary circumstances... but here's one way things might go wrong:

* SeatReserved events likely happen more often than the other types due to timeouts, conflicts, and retries. Ordinarily not a problem, but when hot tickets first go on sale the flood of traffic from people and bots competing for the best seats may cause SeatReserved events to increase far out of proportion with the others.

But hey, that's what autoscaling cloud services as for, right?. If the broker handles filtering, that cloud bill might be a bit scary. If consumers handle filtering, every service consuming any type of BookingUpdated event will also have to scale up too, and that bill might be terrifying. :)

With independent topics/streams/tables for each discrete concept, SeatReserved can scale independently, its traffic cannot directly affect services that do not care about it, and the names of topics and events directly reflect the problem/solution domain.

>EDA resourse repo

Excellent collection, thanks for sharing it!

While the need for "wide" events can be symptoms of other design issues, decorating base events is a good solution when they are necessary. If you really need an aggregated BillingUpdated(Reason) event, for example, you can generate it downstream and preserve the independence of the individual event types.

Offhand, I can only think of one situation where capturing the full state of the source entity in an event would be necessary: when it's ephemeral - but that sounds like a larger discussion (perhaps after enjoying a few videos from your collection).

Thanks again!


correction: the frequency/volume of SeatReserved events may suddenly spike


Thanks for your feedback. I realize I should have elaborated the example a bit more, it's too vague. So, as I wrote in some other reply as well, please don't over-interpret it. The point was only to say that in order to differentiate the events, we don't necessarily need distinct types (which would result in multiple schemas on a topic), but can instead encode it in one type/schema. Like mapping in ORM - instead of "table per subclass", you can use "table per class hierarchy".


Thanks for your feedback! Very good point on the naming. fwiw the idea was if you buy a cinema ticket, you are usually presented with some sort of seating plan and select the seat (basically putting them into the shopping cart). So SeatSelected would be the equivalent of "ItemAdded" to the shopping cart in an e-commerce application I guess. Please don't over-interpret the example. There isn't even a definition what that booking aggregate contains. The point was really only to say that in order to differentiate the events, we don't necessarily need distinct types (which would result in multiple schemas on a topic), but can instead encode it in one type/schema. Think of it like mapping in ORM - instead of "table per subclass", you can use "table per class hierarchy".


Reg. the "technical" question: Kafka or any log-based message broker (or any message queue) would not prevent you from that. Any service can publish/send and/or subscribe/receive.

Regarding if it's a problem or a regular occurrence: No, really not. I have never seen this being a problem, I think that fear is unfounded.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: