2,854 karma · joined October 30, 2014
Am I biased/wrong here?
But I saw it as next step towards shifting programming from sitting and scanning texts into something more tangible, where developer has broad overview of software, and can work on smaller parts while seeing context of how these parts are connected. Ended up concluding that this stuff should work in VR.
Good defaults definitely matter. But not overloading an app with functionality matters as well. Matching feature sets to actual user needs also matters.
The problem with state restoration is that it’s one of those features that looks simple, yet can be extremely tricky to implement correctly – the point you already made. And there’s no single solution that will fit all cases, or even 80% of them. Restoring scroll position is one thing, but restoring an unfinished video editor timeline is another. Both look deceptively simple ("I just reopened the crashed app and it opened at the exact same state"), but the internal mechanics require wildly different mechanisms and trade-offs.
I do agree, however, that frameworks and SDKs should provide properly designed mechanisms for state restoration – and they often do (like the State Restoration API on iOS/macOS).
But the argument that "state restoration should be default and provided by the environment" feels like post-rationalization of the existing mechanics.
> It’s like the Erlang approach to errors, but on steroids
The Erlang approach was intentionally designed that way. Web apps’ normalization of "restarting" is just a testament to how normal buggy software has become in the web ecosystem. Anyone who has ever tried to buy tickets online or register through a simple form on a government website knows that even for such common use cases, it’s extremely hard to create a good user experience. There are some fantastic web apps nowadays, and government-backed design systems and frameworks that sometimes match native apps’ experience – but that only proves the point. It takes an enormous amount of effort to make even simple things work reliably on the web stack.
The core reason, of course, is that the "web stack" is a typesetting engine from the ’80s that was never designed for modern UI apps’ needs in the first place. Why we still use a markup language to build sophisticated UIs and think it’s fine is beyond me. I recently saw an experiment where someone played a video in Excel, using spreadsheet cells as pixels and a lot of harness code to make it work as an output device. It’s doable, but Excel was never designed for that. No matter how many layers of abstraction we put on top – or how many ExcelReact frameworks we create – the foundation is simply not right for the task.
And yet people continue to justify the “defaults” of the web stack as if they were deliberate design choices rather than byproducts. Like, "it’s so good that everything is zoomable," or "I like that everything is selectable". Which sounds fine – until it doesn’t. Why on earth would I need to select half my widget tree with a 3-pixel mouse shift? And when I really do need to select something, it often doesn’t work properly because developers take it for granted and never verify or test it.
Or zooming – whenever I zoom a Facebook page to write a comment, the view keeps jumping around because some amazing piece of JS crapcode decides to realign the interface on a timer (to show ads?). Nobody on Facebook’s QA team probably even tests how the comment section works when zoomed in Safari. The web app experience is simply one of the worst, due to this messy feature set people call "good defaults". And as someone who also has to write web apps from time to time, I can’t stress enough how disproportionately more effort it takes to make an app with sane, good default behavior.
(P.S. There are some good things in the current state of the web stack – but they’re mostly the product of the industry’s sheer size, not the stack itself.)
These days I play with both AI photography and “normal” photography. My main camera is the A9 III with a global shutter – a machine gun that fires 120fps RAW files. I shoot a lot of sports, and the people I photograph are thrilled to get such high-quality shots of moments that mattered to them. It doesn’t really matter how much cultural value society attaches to photos – those captured moments will always be meaningful to them, and they feel joy when they see them. That’s the whole point of photography for me.
AI photography is a bit different. I take 15–20 photos of a friend’s face with my camera, train a LoRA model to use with Flux1.dev, and upload it to network storage on RunPod. Then I spin up a serverless worker on an H100 that runs the ComfyUI API, and use my own Flutter-based frontend to play with prompts and generate new photos of that person. I can make far better headshots this way than in a real studio. For some friends, it’s even been a therapeutic experience – seeing so many high-quality images of themselves looking confident, happy, and fully alive helped them feel that way, even if just for a moment. One friend told me, “You did more with these AI photos of me than therapy did in the past year.”
My mental model is that it's a caller who decides how call should be executed (synchroniously or asynchroniously). Synchronious call is when caller waits till completion/error, asynchronious - is when caller puts the call in the background (whatever it means in that language/context) and handle return results later. CSP concurrency model [1] is the closest fit here.
It's not a property of the function to decide how the caller should deal with it. This frustration was partly described in the viral article "What color is your function?" [2], but my main rant about this concurrency approach is that it doesn't match well how we think and reason about concurrent processes, and requires mental cognitive gymnastics to reason about relatively simple code.
Seeing "async/await/Promises/Futures" being a justification of a "protocol" makes little sense to me. I can totally get that they reimagined how to do RPC with first-class async/await primitives, but that doesn't make it a network "protocol".
[1] https://en.wikipedia.org/wiki/Communicating_sequential_proce...
[2] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
I'm confused. How is this a "protocol" if its core premises rely on very specific implementation of concurrency in a very specific language?
type Foo struct {
somepackage.Bar
URL string
}
you don't want to depend on whether Bar already have URL. Your depth level has higher priority.Even more, imagine in the future authors of `somepackage` decided to add URL to their struct and it suddendly started to break your code from being compiled.
Example in the OP article is a corner case where this behavior is creating ambiguity, indeed. Yet, it's documented and intentional.
These won't compile:
type Bad struct {
Name string
Name string
}
type A struct{ Name string }
type B struct{ Name string }
type C struct {
A
B
}
bad.Name() // compile error: other declaration of Name
c.Name() // compile error: ambiguous selector c.Name
The case in article is about field names of the different depth. Spec is very clear about this behavior, and it was intentional.One of the reasons why handling same field names is different at different nesting levels is to protect against changes in structs coming from external libraries. Or, better phrased, external structs should not dictate what names you're allowed to use in your own structs (so they have priority).
I.e. when you create a struct with another embedded struct (possibly from other package):
type Foo struct {
somepackage.Bar
URL string
}
you don't want to depend on whether Bar already has URL. Your depth level has higher priority.Even more, imagine in the future authors of `somepackage` decided to add URL to their struct and it suddendly started to break your code from being compiled.
I agree that behavior in the OP article example is confusing (and so is the code - do you want URL of Foo service or Bar service?). Yet, this behavior is intentional and documented.
As usual, it's a subtle tradeoff here. If this feature would be implemented differently (say, compile time error for all depth levels), we would see an article with rant on how external structure changes breaks compilation.
I just tried this new feature to work on a text document in a project, and it's a big difference. Now I really want to have this feature (for text at least) in ChatGPT to be able to work on documents through voice and without looking at the screen.
[1] https://github.com/AstroNvim/astrocommunity/tree/main/lua/as...
Dancing with AGENTS/CLAUDE/GEMINI/windsurf files symlinks/imports becomes really annoying. Using projects like https://github.com/intellectronica/ruler for some reason doesn't stick (yet another tool to install, yet another cognitive debt to pay).
Please help bring attention to that issue.
Gosh, it must be hard to understand people with the stance like that.
I have no idea what your definition of "general computational device" is, but it's very clearly different from mine.
In my worldview, "general computational device" is the piece of hardware specifically designed to run any program you want. Personal computers, desktop computers, servers, and mini-computers are examples of these.
Smartphones - with the exception of a few very niche devices – have never been any of this. They didn't start as "mini-PC", they grew out of telephony – a heavily regulated industry with strict standards around the usage of frequencies, and where compliance and billing matter more than ability to tinker. The ability to "run apps" was never even on the table in pre-iPhone era. iPhone, ofc, changed it by pioneering the app market, and it was locked in from the very beginning - for security and user experience reasons. We can argue whether that was a good decision or not, but that's the short history of smartphones never being a "general purpose computational device". Modern phones are heavily optimized, specialized devices for the "daily life" tasks - camera, navigation, calls, messaging, web browsing – that also have very limited and sandboxed capability to run apps in a way that the manufacturers allowed.
So no, phones are not "general computational devices" and have never been. I'm sorry that your worldview doesn't allow listening to other people's opinions. Debating is indeed very hard without it.
Developer experience is... well, I usually develop app while running it locally as a MacOS desktop app build. Just much easier to use with hot-reload and Flutter dev tools. Often using DevicePreview [1] wrapper to check against different sizes, dark/light mode, font scaling etc. Unless I'm working on something platform-dependent (like push notifications or a QR code scanner that uses camera/ML frameworks from OS), I don't even test it on mobile devices or web - I know that it will look pixel-perfect. There are optimization caveats like "emojis are not included in the web build by default to decrease the size", but otherwise web build looks the same way pixel-to-pixel as MacOS or mobile view. Test I run with maestro in iOS simulator.
Centering widgets ("<divs>") is never a problem, haha. Having a properly designed layout system is a no-brainer and thousands of times better experience than that pile of hacks on top of hacks called CSS.
Still, my main issue with the current Flutter design is the tight coupling of two main design systems (Material Design and Cupertino) and the core, and the lack of a wide choice of alternative design systems. Just to make it clear - it's extremely easy to create your own widgets/themes/look-and-feel in Flutter app. But having a well-thought-out design system is a different beast. Luckily, decoupling is on the way [2] and I hope it will lead to a boom of nice design systems implementations.
Also, because Flutter originally was targeting mobile development, and expanded to desktop/web almost accidentally, the majority of the widgets are optimized for mobile UI. For example, if you want a date input field that feels native to a desktop user, with masking and yet a calendar picker – good luck finding one. And as I create desktop/mobile apps 50/50, I settled for now with forui [3] design system, heavily inspired by shadcn.
Performance has been the last of my concerns with Flutter, because the engine was originally heavily optimized to hit <15ms frame rendering and modern web renderer is using Wasm and shader precomilation and some dark magic I don't even want to know about. And to be honest, my own experience with "web apps" is so bad, that I don't think any non-native-to-browser rendering pipeline can make it worse. Like, having UI glitches and unresponsive components, bad state management, need to refresh the page (which is essentially a "restart an app" in web), mess with forms/fields it's just such a normal experience in web. I don't have any of that with Flutter web apps. They might feel a little bit "non-native" to HTML-based web apps, but I never heard real users caring about that.
[1] https://pub.dev/packages/device_preview
[2] https://docs.google.com/document/d/189AbzVGpxhQczTcdfJd13o_E...
For many years I'm advocating the community to be very open about the history of web stack (and JS in particular) and be honest about it's suitability for the modern software development. The level of accidental complexity in this stack is insane and people seem to embrace it add more and more layers of it.
Personally, I try to avoid using it as much as possible. And it works beautifully. Of course, tradeoffs are everywhere, and the sheer scale of the web development community has its own benefits. For example I miss the wide choice of alternative design systems in Flutter (compared to web), but hey, flutter now decoupling it's core from design systems in 2026. But the net effect of not using fundamentally flawed tools for your products is huge.