HN user

can3p

116 karma
Posts11
Comments55
View on HN

All the usual suspects, error handling, sum types, interfaces.

Just a note, I'm yet to see a problem highlighted in the section about interfaces, in particular that changing a concrete type will make it not fit the interface anymore which will result in troubles. It's often used as a tool to make the changes (e.g. change the interface, observe the compilation failure and fix all the occurrences). They way interfaces are usually defined on site as a minimal possible signature - if your code just needs one method, you define a narrow interface and that's it. That also makes it impossible to predict what kind of interface is needed at producer side.

If the argument is that you can fit a wrong struct into the interface, then again, I'm yet to see a real life manifestation of this problem.

Every library is a liability especially in terms of api. There are many example where the first take on a problem within a std lib was a bad choice and required a major overhaul. Once something is in standard library it’s literally impossible to take it back without breaking the world if you don’t control api consumers

I think this post needs better examples to show case the issue, because right now the issue is not clear. Ideally you would need an example that uses the context.Cause function, see below

The contexts and errors communicate information in different directions. Errors let upstream function know what happened within the call, context lets downstream functions know what happened elsewhere in the system. As a consequence there isn't much point to cancel the context and return the error right away if there isn't anybody else listening to it.

Also, context can be chained by definition. If you need to be able to cancel the context with a cause or cancel it with a timeout, you can just make two context and use them.

Example that shows the approach as well as the specific issue raised by the post: https://go.dev/play/p/rpmqWJFQE05

Thanks for the post though! Made me think about contexts usage more

For many business apps, they will never reach 2 billion unique values per table, so this will be adequate for their entire life. I’ve also recommended always using bigint/int8 in other contexts.

I'm sure every dba has a war story that starts with similar decision in the past

The other reason is the volume of the code being produced combined with the constant product changes. An innocent change like mixing two close but still different concepts can easily poison the whole codebase and take years to undo and may even be nearly impossible to fix if it propagates to external systems outside of direct control

I’ve made my own attempt in building a social network [0] and it’s evening running for me and my friends.

Here are few things I’ve encountered during the development:

- Based on my experience private only approach does not work. It’s all about network effects and if users can’t send their post to all friends, they’ll just move on to a different platform

- chronological friends only feed is really boring. Not that it’s bad per de, but it’s hard to convince people to stay if the service is not entertaining

It can also be me not being able to market the project right. Good luck with your attempt!

[0] https://github.com/can3p/pcom

There are two sides to the argument which I think should be treated separately: a) Is it a good idea overall? and b) is htmx implementation good enough?

a) I think so, yes. I've seen much more spa that have a completely broken page navigation. This approach does not fit all use cases, but if you remember that the whole idea of htmx is that you rely on webserver giving you page updates as opposed to having a thick js app rendering it all the way it makes sense. And yes, js libraries should be wrapped to function properly in many cases, but you would do the same with no react-native components in any react app for example

b) I don't think so. htmx boost functionality is an afterthought and it will always be like this. Compare it with turbo [1] where this is a core feature and the approach is to use turbo together with stimulus.js which gives you automagical component life cycle management. Turbo still has it's pains (my favorite gh issue [2]), but otherwise it works fine

[1] https://turbo.hotwired.dev/ [2]: https://github.com/hotwired/turbo/issues/37

This and similar post are a bulletproof way to start a flame war.

Last time it was generics that were missing, now everyone is raging about sum times and of course explicit error is a topic of constant concern and why panics and not exceptions?

Go is well designed to build good software quickly. Easy dependency handling, good tooling, vast ecosystem.

Go is well designed to help developers with automation and help them catch mistakes, that's why it's easy to parse and all language design decisions take that into account.

It's also designed to produce a lot of code and that requires the language to be easy to understand and programs easy to tweak and that's what it provides, since you'll have a lot of developers tweaking the code.

We're in the industry of shipping different kinds of products and that imposes different constraints and results in different languages being used. Also, different people care about different stuff and languages form clusters of similar minded people around them, that's a choice too.

One of the things that surprised me in the article was their usage of J2K. They’ve been using it as part of IntelliJ, alright, but why did they have to run it headless? They’ve even mentioned that it was open sourced. And later they’ve said that they were not able to do much improvements because it was on maintenance mode at Jet Brains.

I mean, with the ressources meta has I’m sure they could have rewritten the tool, made a fork or done any other thing to incorporate their changes (they talk about overrides) or transformed the tool into something better fitting their approach. Maybe it has been done, just not clear from the article

Local state is indeed a problem that's exacerbated by swapping logic. Simple example: you have a form + a collapsible block inside or maybe a dynamic set of inputs (imagine you're adding items to a catalog and you want to allow to submit more than one). If you save the form and simply swap the html the block state will be reset. Ofc you could set the toggle state somewhere to pass it along to the backend, but that's a pain already compared to spa approach where you don't even bother with that since no state is reset.

You could you query string as mentioned in the article, but that's not really convenient when done in a custom way for every single case.

Having said that I think that a way to go could be a community effort to settle on the ways to handle different ui patterns and interactions with some bigger project to serve as a testing ground. And that includes backend part too, we can look at what rails does with turbo

My opinion is that htmx (and similar) approach is different enough to potentially require a different set of ui interactions and it usually hurts when one tries to apply react friendly interactions to it.

1M Users 2 years ago

Just checked it, thanks for pointing to it. I think it's more of a decentralized encrypted messaging platform, and my idea was to have a way constrain the visibility of the conversations to naturally connected groups of people while giving a way to slowly expand the connections rather then fighting censorship

More or less like in real life, where you chat a lot with your friends, but necessarily with some of their friends you don't know that well. In this case you would ask your friends for the introduction and that what I've tried to model.

One other feature I've been thinking about was to make the moderation automatic in a sense of making signups possible only via invitation and putting some weight on it. Basically if you invite somebody who's misbehaving on the platform and they get flagged, you get penalized as well unless you do it first. My theory is that it should make users care about their digital surroundings.

1M Users 2 years ago

Nice! Personally I think that the more niche social networks we have the better it is. The big problem with the mainstream networks is that they've evolved from a media to communicate and keep in touch with real people into a platform for influencers and businesses.

The common complaint I hear about instagram for example is that every second connection of yours would try to sell/teach something and that's just garbage if all you need is to keep in touch with your friends.

The main problems to tackle imo are:

- information propagation speed. This is good in case you want to get a quick update but it also a double edged sword, since this allows information attacks, trolls etc

- Scale. Anything of big scale becomes a problem by itself since it becomes economically viable to target the platform with bots, scam etc.

- Incentives. I think we should get to the point where social networks are being run by non profits

I've posted the link a couple of time, I'm working on my personal take on this problem[0]. My approach is the following:

- Slow down information propagation. Every post is visible to the direct connections, to their connections if you allow it, but no further

- No way to get a connection request from a stranger. Either you specifically allow it, or it's introduced by your direct connections

- No federation, since my idea was to have small communities

- Fully open in the sense of data formats, import/export etc. Migrating between instances is as easy exporting posts in bulk, creating an account on another instance and doing the import. You could do the bulk updates the same way

Also, it's all go + htmx just in case anyone else is also tired of modern frontend mess. I have a couple of videos on the feautures[1], if you like. The design is not great, since I wanted to focus on the idea itself

[0] https://github.com/can3p/pcom

[1] https://www.youtube.com/playlist?list=PLa5K-kCUS-FozB6Cw7rJL...

I’ve been scratching my own itch lately trying to build a communication medium that I like.

IMO the problem with current social networks is their scale and public only approach. Any network that goes this way ends up with lots of bad actors and public only approach means that it’s easy to harass people and bots are economically viable.

I’ve addressed both points [0]. Visibility of the posts is limited to direct connections, you need a proxy connection to make a new one and at the same time it’s mega easy to import/export, markdown support and apis are there etc. That was my way to get miningful discussions back.

In general, you need to look to small scale places

[0] https://github.com/can3p/pcom

Small nitpick - the author mentions upsert in the beginning of the article only to "forget" about it and use it in the end (insert .. on conflict ignore) and that's the obvious solution there.

The final query is very neat though! And special thanks for mentioning "MERGE ... RETURNING" in PG17, that's really cool

I think the whole article can be generalized as following: one cannot make assumptions about relative values.

You can replace UTC with US dollars and Amsterdam time with euros and talk about conference prices. If you convert 100 euro to US dollars at the time of record creation, the price at the day may not be 100 euros anymore.

Ideally you record a tuple that allows to define value unambiguously (e.g. time 2022-02-21 9:00 timezone Europe/Amsterdam) because in this case you can always resolve the absolute time value later.

This is a typical hiccup for any business expanding into multiple locations with different parameters (time zones, currencies, units etc).

Once case that I find particularly interesting is an event that happens in different locations at the same logical (but different absolute time). Let's say you want to send an email to all your users across the global on Monday 9:00. If you want to add up to complexity, you could think about sending an email to all your users across the globe on the first working day next week.

I think the module imports apis are a python2/3 moment for node.js ecosystem. There is no clearly superior way and as a consequence not too many people care, however it hurts for real.

The proposal to disable node.js style imports will just split ecosystem and make a large part of industry stick to ancient version / make a fork. Is that really worth the gain? Just check how long it took some bigger projects to migrate from python2 to python3

The part that blows my mind all the time is that there are all sorts of cups - https://en.wikipedia.org/wiki/Cup_(unit)

Mile unit is another one of the same sort - https://en.wikipedia.org/wiki/Mile with the exception that only two kinds have survived if I'm not mistaken - US mile and nautial mile

I guess it can be very simple in US, especially if mug/cup volumes are defined in terms of a "cup" multiples, but in europe I get totally lost when I see the cup unit in the recipe since I din't know what volume it refers to

I think linux became much better in recent years not at least due to things moving into web. Ofc there is a ton of specialized windows only software still, but it became much less relevant for ordinary people.

Just remember all the people struggling with open office (not relevant because of google docs and alike) and video/audio codecs (Spotify, Netflix etc). In general the amount of desktop apps needed to be productive has reduced.

The desktop is just good enough even though App Store apps are quite terrible in both Ubuntu and fedora in my experience.

On the other hand with pipewire we can finally have working Bluetooth headphones and after years of endless shitshow simple things like screen sharing are working again

I think tailwind went a bit too far, but in general it’s really hard to have a controllable amount of css on huge projects. The reason is that selectors are often too broad and it’s not possible to say in general whether a particular selector is being used or not.

Atomic classes really shine in this aspect, since it’s really just what you have in html and nothing more.

Another fantastic quality is the fact that you can really tweak things slightly in the html and skip inventing a modifier class just for this particular situation.

I think bootstrap css hits a really sweet spot there, since they have lots of reusable components, which are very easy to use and extend and a huge bunch of utility classes to accommodate for exceptions. I know that’s not an argument for spas, since you have components there, but for server side templates that’s the best

Can't recommend anki flash cards enough. One thing that I found important is that you need to build the deck yourself and you'll miss out a lot by using prebaked decks of any kind. Reasons:

- Context is the king. Most of the words have multiple meanings and it's easier to remember them if you just added them from a text you've read. Moreover, this approach gives you an opportunity to see the words being used in the wild which gives confidence on when to use the word/idiom - Words with no context are just harder to learn - 3rd party decks will give you loads of words you don't care about

For learning French I've found kwiziq much more useful. Very little gamifications and lots and lots of training and exercises with examples that actually make sense

The answer is usually self selection and calibration at scale. Self selection is about people looking like minded colleagues. If everybody is crazy about solving riddles and participates in programming competitions that's what they would be looking for.

Now, about the scale. Anything run at scale needs standardisation. You need to hire 100 senior developers. How do you know they have more or less same level? If every single interview is hand crafted, you'll either need to get all devs envolved (and not everybody is good at coming up with interview questions) or get standard questions and answers to allow a smaller group of people to deal with candidates and coding puzzles fit great there because they're slef contained and isolated. Every realistic question has multiple facets and that's what you get at the system design interview step.

Another problem I've observed was that the more you give the same puzzles to candidates, the easier they look to you. What the means is that you as an interviewer either need to keep your self in check regarding your reactions or you're risking giving a bad interview score in situations where it's not really warranted or there is a chance that the next question you take will be the one you find more complex (to be equal to position level in your head) and that would push the level of questions up. That's another observation I had when some interview questions would become so complex that I knew some of the existing devs would fail the interview for sure.

Does that give good results on the other end? I don't know, but what we definitely know is that there is the whole industry around leetcode to train peeople to pass these challenges specifically and that means that they only thing the interviewer know is that the candidate has put some effort to prepare for the interview meaning they're motivated to join the company. And maybe it's not the worst data point! Some companies actually explicitly mention this fact on their hiring pages.

To add to it, big corps have different ways to make interviews objective in whatever sense they think and that by definition reduces the personal impact. "Why did you ask this question? We've never done it before, we'll need to have a group call to calibrate". After a handful conversations like this you'll just stick to the standard process.

Is there a way to come up with a more human approach? Personal recommendations with some skin in the game I guess. I'm sure in some niche areas like browser engines all good devs know each other well and no interview is often necessary.

Great post! I've been thinking about that a lot recently and my take on it [0] is that the metric could be the iteration time. Teams that move fast can do fast iterations during development. If that's possible, a lot of tasks, also maintenance ones become much simpler.

Another point that's relevant in this discussion is that the tech debt does not appear out of nowhere and developers do not develop whatever they like. Rather, they're implementing ideas of product managers, designers and other stakeholders. If the team finds itself in a hole shortly after tidying things up it can also be because of the ignorance on the product or design side with the requests that demand unreasonable effort to implement very insignificant changes.

All in all, it looks like both terms should be used in combination, because they describe different types of inefficiencies

[0] https://dpetrov.substack.com/p/the-tyranny-of-the-feedback-l...

Thanks for mentioning templ, looks interesting. Templates are one of the fields where go has some space for improvements

I think a fair question to explore is why is it not a problem in other languages (maybe it is)

Direct paths also make file structure a part of api and that may not be the desired effect. In addition the bigger problem is not barrel files in your project but rather those in all third-party dependencies

This is not a tyranny if’s marginal user, this is corporate mechanics and metrics at play. Every big company has a number of North Star metrics. If you move them in right direction you get promotions and recognition, since the metrics are used as a proxy for customer benefit

The problem though is that it’s relatively easy to game the metrics, especially in short term hence the popular sport is to pump the metric, get promotion and move on to a different project before the negative consequences are evident.

Eg if your metric is conversion you can exploit it in lots of really dark ways

In even bigger companies like google it’s possible to repeat this action many times and the result is obvious. You can see how this could work with acquired products - of course the first changes will be to bring them to Xcorp scale, stack or standards which can mean years without new features

It works completely differently with hobby projects because of different incentives. I’m 100% sure that the best things in the world are created when their authors do them just for the sake it using their vision.

Unfortunately you cannot really grind in this way. So if you have to implement a login using 100 different auth systems, the approach should be different

I think build systems are a very big reason for the mess javascript is in nowadays.

- Typescript is very light from the code transformation point of view. If anyone remembers the output of babel especially for async/await + the way module imports are implemented generates a really hard to read code and the "best practices" about hiding the state make things a lot harder. Just think about the fact that back in the days (tm) it was common to inspect the state of the app and change it full lisp style and now the js console can mostly be used for quick code tests and looking around when execution is stopped at breakpoint and you can't see that much anyway because of how the code is generated. - The whole babel thing still feels like a madness to me. Yeah, you're getting some new language features but for the price of non obvious code transformation that makes you need source maps (and you need to make them work and maintain that) and all the rest - Build step + npm results in on controlled bloat of the js bundle. `npm install <random-component>` may inflate you bundle by 500kb easily - And with all that there is still a quite big trouble with requiring necessary modules for the use on frontend. Just think that there is still no simple way to require all css provided by a library from npm

Another big problem on my opinion is the propagation of "write once/use everywhere" approach. It works sometimes yeah, but you need to sell your soul for that: you'll have to use something like next.js and that implies that you're bound to use node.js and then you either do all your development in node or have another service doing stuff in the language of your choice and then have a node service as a templating layer and then you need containers and orchestration and so on which makes it a technically challenging project for something that almost for sure can be done in some trivial set of technologies if this requirement had been dropped.

One could argue that we need a different approach with libraries that acknowledges that frontend is distinct world and aims to provide ready made components specifically for the web with an easy setup and no/minimal dependencies. Maybe even with a vendor folder like approach, since the won't be too much code anyway. That should be enough for 99.999% of projects and the rest can use the full scale approach and embrace complexity if they really need it.