Full Width [alt+shift+f] Shortcuts [alt+shift+k] TRY SIMPLE MODE
Sign Up [alt+shift+s] Log In [alt+shift+l]
23
Go is the most hated programming language. Compared to other languages, it provides 80% of utility with 20% of complexity. The hate comes from people who want 81% of utility, or 85% or 97%. As Rob Pike said, no one denies that 87% of utility provides more utility than 80%. The problem is that additional 7% of utility requires 36% more work. Here are some example. Someone complained on HN that struct tags are a not as powerful as annotations or macros. I explained that this is 80⁄20 design. Go testing standard library is a couple hundred lines of code, didn’t change much over the years and yet it provides all the basic testing features you might need. It doesn’t provide all the convenience features you might think of. That’s what Java’s jUnit library does, at a cost of tens of thousands lines of code and years of never-ending development. Go is 80⁄20 design. Goroutines are 80⁄20 design for concurrency compared to async in C# or Rust. Not as many features and knobs but only a fraction of...
a month ago

Improve your reading experience

Logged in users get linked directly to articles resulting in a better reading experience. Please login for free, it takes less than 1 minute.

More from Krzysztof Kowalczyk blog

Ideas for faster web dev cycle

I strongly believe that fast iteration cycle is important for productivity. In programming fast iteration means: how quickly can I go from finishing writing the code to testing it. That’s why I don’t like languages that compile slowly: slow compilation puts a hard limit on your iteration cycle. That’s a general principle. How does it translate to actions? I’m glad you asked. Simulated errors I’m writing a web app and some code paths might fail e.g. server returns an error response. When that happens I want to display an error message to the user. I want to test that but server doesn’t typically return errors. I can modify the server to return error and restart it but in a compiled language like Go it’s a whole thing. Instead I can force error condition in the code. Because web dev typically offers hot reload of code, I can modify the code to pretend the request failed, save the code, reload the app and I’m testing the error handling. To make it less ad-hoc another strategy is to have debug flags on window object e.g.: window.debug.simulateError = false Then the code will have: try { if (window.debug.simulateError) { throw Error("fetch failed"); } let rsp = await fetch(...); } That way I can toggle window.debug.simulateError in dev tools console, without changing the code. I have to repeat this code for every fetch(). More principled approach is: async function myFetch(uri, opts) { if (window.debug.simulateError) { throw new Error("featch failed"); } return await fetch(uri, opts); } To go even further, we could simulate different kinds of network errors: Response.ok is false response is 404 or 500 failed to reach the server We can change simulateError from bool to a number and have: async function myFetch(uri, opts) { let se = window.debug.simulateError; if (se === 1) { // simulate Response.ok is false return ...; } if (se === 2) { // simulate 404 response return; } if (se === 3) { // simulate network offline } return await fetch(uri, opts); } Start by show dialog Let’s say I’m working on a new dialog e.g. rename dialog. To get to that dialog I have to perform some UI action e.g. use context menu and click the Rename note menu item. Not a big deal but I’m still working on the dialog so it’s a bit annoying to repeat that UI action every time I move the button to the right, to see how it’ll look. In Svelte we do: let showingRenameDialog = $state(false); function showRenameDialog() { showingRenameDialog = true; } {#if showingRenameDialog} <RenameDialog ...></RenameDialog> {'if} To speed up dev cycle: let showingRenameDialog = $state(true); // show while we're working ont While I’m still designing and writing code for the dialog, show it by default. That way app reloads due to changing code won’t require you to manually redo UI actions to trigger the dialog. Ad-hoc test code Let’s say you’re writing a non-trivial code server code to process a request. Let’s say the request is a POST with body containing zip file with images which the server needs to unzip, resize the files, save them to a file system. You want to test it as you implement the logic but iteration cycle is slow: you write the code recompile and restart the server go through UI actions to send the request Most of the code (unpacking zip file, resizing images) can be tested without doing the request. So you isolate the function: func resizeImagesInZip(zipData []byte) error { // the code you're writing on } Now you have to trigger it easily. The simplest way is ad-hoc test code: func main() { if true { zipData := loadTestZipFileMust() resizeImagesInZip(zipData); return; } } While you’re working on the code, the server just runs the test code. When you’re done, you switch it off: func main() { if false { // leave the code so that you can re-enable it // easily in the future zipData := loadTestZipFileMust() resizeImagesInZip(zipData); return; } } Those are few tactical tips to increase dev cycles. You can come up with more such ideas by asking yourself: how can I speed iteration cycle?

3 weeks ago 13 votes
Stage manager in Mac OS

Stage Manager in Mac OS is not a secret, but I’ve only learned about it recently. It’s off by default so you have to enable it in system settings: It’s hard to describe in words, so you’ll have to try it. And experiment a bit because I didn’t get in the first hour. It’s a certain way to manage windows for less clutter. Imagine you have a browser, an editor and a terminal i.e. 3 windows. Might be annoying to have them all shown on screen. When Stage Manager is enabled, thumbnails of windows are on the left edge of the screen and you can switch to the window by clicking the thumbnail. By default Stage Manager shows each window by itself on screen. You can group them by dragging thumbnail onto screen. For example, when I’m developing, I’m using text editor and terminal so I will group them so they are both visible on screen at the same time, but not the other apps. So far I’m enjoying using Stage Manager.

3 weeks ago 14 votes
Zed debug setup for go server / Svelte web app

Today I figured out how to setup Zed to debug, at the same time, my go server and Svelte web app. My dev setup for working on my web app is: go server is run with -run-dev arg go server provides backend apis and proxies requests it doesn’t handle to a vite dev server that does the serving of JavaScript etc. files from my Svelte code go server in -run-dev mode automatically launches vite dev go server runs on port 9339 It’s possible to setup Zed to debug both server and frontend JavaScript code. In retrospect it’s simple, but took me a moment to figure out. I needed to create the following .zed/debug.json: // Project-local debug tasks // // For more documentation on how to configure debug tasks, // see: https://zed.dev/docs/debugger [ { "adapter": "Delve", "label": "run go server", "request": "launch", "mode": "debug", "program": ".", "cwd": "${ZED_WORKTREE_ROOT}", "args": ["-run-dev", "-no-open"], "buildFlags": [], "env": {} }, { "adapter": "JavaScript", "label": "Debug in Chrome", "type": "chrome", "request": "launch", "url": "http://localhost:9339/", "webRoot": "$ZED_WORKTREE_ROOT/src", "console": "integratedTerminal", "skipFiles": ["<node_internals>/**"] } ] It’s mostly self-exploratory. First entry tells Zed to build go program with go build . and run the resulting executable under the debugger with -run-dev -no-open args. Second entry tells to launch Chrome in debug mode with http://localhost:9339/ and that files seen by Chrome come from src/ directory i.e. if browser loads /foo.js the source file is src/foo.js. This is necessary to be able to set breakpoints in Zed and have them propagate to Chrome. This eliminates the need for terminal so I can edit and debug with just Zed and Chrome. This is a great setup. I’m impressed with Zed.

3 weeks ago 18 votes
lazy import of JavaScript modules

When working on big JavaScript web apps, you can split the bundle in multiple chunks and import selected chunks lazily, only when needed. That makes the main bundle smaller, faster to load and parse. How to lazy import a module? let hljs = await import("highlight.js").default; is equivalent of: import hljs from "highlight.js"; Now:   let libZip = await import("@zip.js/zip.js");   let blobReader = new libZip.BlobReader(blob); Is equivalent to: import { BlobReader } from "@zip.js/zip.js"; It’s simple if we call it from async function but sometimes we want to lazy load from non-async function so things might get more complicated: let isLazyImportng = false; let hljs; let markdownIt; let markdownItAnchor; async function lazyImports() { if (isLazyImportng) return; isLazyImportng = true; let promises = await Promise.all([ import("highlight.js"), import("markdown-it"), import("markdown-it-anchor"), ]); hljs = promises[0].default; markdownIt = promises[1].default; markdownItAnchor = promises[2].default; } We can run it from non-async function: function doit() { lazyImports().then( () => { if (hljs) { // use hljs to do something } }) } I’ve included protection against kicking of lazy import more than once. That means on second and n-th call we might not yet have the module loaded so hljs will be still undefined.

3 weeks ago 14 votes
Using await in Svelte 5 components

Svelte 5 just added a way to use async function in components. This is from Rich Harris talk The simplest component <script> async function multiply(x, y) { let uri = `/multiply?x=${x}&y=${y}` let rsp = await fetch(uri) let resp = await rsp.text(); return parseInt(resp); } let n = $state(2) </script> <div>{n} * 2 = {await multiply(n, 2)}</div> Previously you couldn’t do {await multiply(n, 2) because Svelte didn’t understand promises. Now you can. Aborting outdated requests Imagine getting search results from a server based on what you type in an input box. If you type foo, we first send request for f, then for fo then for foo at which point we don’t care about the results for f and fo. Svelte 5 can handle aborting outdated requests: <script> import { getAbortSignal } from "svelte"; let search = $state("") const API = "https://dummyjson.com/product/search"; const response = $derived(await fetch(`${API}?q=${search}`), { signal: getAbortSignal() }) </script> <input bind:value={search}> <svelte:boundary> <ul> {#each (await response.json().products as product)} <li>{product.title}</li> {/each} </ul>

3 weeks ago 14 votes

More in programming

Digital hygiene: Passwords

Stay safe out there folks!

5 hours ago 2 votes
The serial TX path seems to be down

The previous series of articles about UART was initially motivated by an error I was getting when using the ESP-Prog. I could have jumped straight to the conclusion, but I took the time to really understand what was going on, and we are finally reaching the end of this investigation. Connecting to “real” UART again … Continue reading The serial TX path seems to be down → The post The serial TX path seems to be down appeared first on Quentin Santos.

2 days ago 6 votes
What do you do with a chance?

One day, I got a chance. It just seemed to show up. It acted like it knew me, as if it wanted something. This is how Kobi Yamada's book What do you do with a chance? starts. I've been reading that beautiful book to the boys at bedtime since it came out in 2018. It continues: It fluttered around me. It brushed up against me. It circled me as if it wanted me to grab it. What a mesmerizing mental image of a chance, fluttering about. What do you do with a chance? is a great book exactly because it's not just for the boys, but for me too. A poetic reminder of what being open to chance looks like, and what to do when it shows up.  Right now, Omarchy feels like that chance. Like Linux fluttered into my hands and said "let's take a trip to the moon".  I joked on X that perhaps it was the new creatine routine I picked up from Pieter Levels, but I only started that a few days ago, so I really do think it's actually Linux! This exhilaration of The Chance reminds me of the 1986 cult classic Highlander. There's a fantastic montage in the middle where Sean Connery is teaching Christopher Lambert to fight for the prize of immortality, and in it, he talks about The Quickening. Feeling the stag, feeling the opportunity. That's the feeling I have when I wake up in the morning at the moment: The Quickening. There's something so exciting here, so energizing, that I simply must get to the keyboard and chase wherever it flutters to.

2 days ago 4 votes
Developer Tools, Hardware Enablement, and Multitasking Futures

Your monthly updates post is here! This month we have a couple of releases for our developer tools, plus plenty of improvements to Bluetooth, as well as a hardware enablement boost from Ubuntu and plenty to talk about in Early Access. Let’s dive in! System Settings The previously mentioned redesign of Bluetooth Settings has arrived! This redesign not only brings a bit more visual separation between paired devices and nearby devices, but also improves the keyboard navigation and screen reader experience. Plus, you can now double click rows to activate them. We resolved an issue where sometimes devices would be duplicated in the list and fixed issues when a pairing request requires entering passcodes—like with some keyboards. You’ll now also see fewer unnamed devices when discovering, enabling and disabling Bluetooth on devices that have been hardware locked should now work reliably, and to top it all off performance when listing lots of devices has also been improved. Bluetooth settings has a new design Leonhard and Ryo fixed a couple of issues with sidebar selections when navigating directly to a setting from search. Ryo fixed an issue where Sharing Settings lost its window controls when a network was not connected. And there’s now an action to jump directly to the System Updates page from the context menu in the Dock or Applications Menu or via search. Code Working with Git projects continues to get better thanks to Jeremy! There’s now a new feature to clone git repositories directly from inside Code via the projects menu in the sidebar. The item for opening project folders has moved there as well, so managing your open projects now happens all in one place no matter where they come from. You can now clone Git projects in Code He also fixed an issue with blank tooltips appearing in empty sidebar folders, a crash when deleting selected text while using the “Highlight Selection” plugin, and a freeze when editing lists with the “Markdown” plugin. Plus, the Symbols sidebar now shows a loading spinner when searching symbols takes longer than usual, and filters have been fixed for C symbols. Terminal Terminal will now warn about pasted commands that include options to skip confirmation like -y, --interactive=never, and --force. Plus we now make sure to show all found warnings about a pasted command, not just the first one found. For example, if a command like sudo apt update && sudo apt install -y fuse is pasted, we will warn about use of admin privileges, multiple commands, and that it skips confirmations, not just that it uses admin privileges. Terminal warns about more potentially dangerous commands Corentin fixed an issue where long commands could resize windows. Jeremy fixed an issue where tab labels didn’t properly update when using screen or ssh. And he made sure we properly close tabs when using the exit command. And More A few small bug fixes for our Window Manager: Corentin resolved a potential crasher, Leo improved dock hide animations, and Leonhard fixed an issue with revealing the panel over fullscreen apps. A new Hardware Enablement stack has arrived thanks to Ubuntu! This includes Linux 6.14 and Mesa 25 which brings support for newer hardware as well as some big performance gains and potential battery life improvements. OMG! Ubuntu! breaks down all the nerdy details here Get These Updates As always, pop open System Settings → System on elementary OS 8 and hit “Update All” to get these updates plus your regular security, bug fix, and translation updates. Or set up automatic updates and get a notification when updates are ready to install! Early Access Maps Last month, Ryo made the last release of Atlas on AppCenter because we’ll soon be shipping it by default in elementary OS as Maps! As part of our work to improve the experience on computers you take with you—like notebooks and tablets—we’ve been working on features that use your location, and shipping a Maps app is part of that work. An in-development version of the new Maps Our hope with Maps is to improve support for mapping and location features in our platform libraries and to improve experiences in other apps like Tasks and Calendar as well as 3rd party apps in AppCenter. We’ve also already made a tiny improvement to the wider Freedesktop ecosystem by documenting a standard location icon used across desktops and in Portals. We’re really looking forward to getting your feedback and learning how we can improve experiences for apps that use your location in elementary OS. Window Manager & Dock First up is some new eye candy. We’ve heard requests for transparency and blur over the years and I’m happy to report we’re now experimenting with some new effects in shell elements like the alt + tab Window Switcher. We want to make sure to carefully balance shiny effects with performance and legibility, so be sure to send in your feedback. We’re also on track to apply some blur behind the Dock soon, so watch out for that. Blur effects have landed in the window switcher and are coming to the Dock Speaking of the Dock, you may have noticed that it’s now sticking around when in Multitasking View! We’ve replaced the old workspace switcher and you can now launch apps from the Dock directly into different workspaces to quickly get things set up exactly how you like. We’ve also merged in a new feature to monitor background apps that use the cross-platform Background Portal. Here you can not only manage background apps, but also see an explanation of what exactly they’re doing while running. With these features, we’re seeing years of design and development work come together: an improved way to multitask on elementary OS whether you use a mouse at your desktop, multitouch gestures on your laptop or tablet, or rely on keyboard shortcuts to get the job done. I’m extremely proud of what the team has done here and look forward from hearing more from you about it! Background apps now show in the Dock And that’s not all. Building on the previously mentioned Gesture Controller, the new Touchpad backend for multitouch gestures has also landed. This replaces Touchégg in the Secure Session as the way to track multitouch gestures, fixes bugs, and enables new features like two-dimensional swiping between workspaces and the full Multitasking View. So if you are a fan of gestures on your notebook, we’d love for you to try it out and report back before we ship it for everyone. Hardware Support Last but not least, we’re now building Universal EFI install images for ARM64 processors. This means instead of building unique ARM images for every hardware platform, we can build a single universal image for platforms like Pinebook, Raspberry Pi, and M-series Macs. These builds are still experimental and come with a few bugs, but we’d love folks to give them a spin in a virtual machine or on a spare computer and report back. If everything looks good, we may be able to offer stable ARM64 downloads starting with OS 8.1 later this year. Sponsors I want to give special thanks this month to Ryan Prior for his extremely generous one-time sponsorship! Ryan noted that this sponsorship was dedicated to the hard work of Renato who has been translating elementary OS into Brazilian Portuguese. Thanks a ton for your work Renato! At the moment we’re at 22% of our monthly funding goal and 332 Sponsors on GitHub! Shoutouts to everyone helping us reach our goals here. Your monthly sponsorship funds development and makes sure we have the resources we need to give you the best version of elementary OS we can! Monthly release candidate builds and daily Early Access builds are available to GitHub Sponsors from any tier! Beware that Early Access builds are not considered stable and you will encounter fresh issues when you run them. We’d really appreciate reporting any problems you encounter with the Feedback app or directly on GitHub.

2 days ago 6 votes
Sit On Your Ass Web Development

I’ve been reading listening to Poor Charlie’s Almanack which is a compilation of talks by Charlie Munger, legendary vice-chairman at Berkshire Hathaway. One thing Charlie talks about is what he calls “sit on your ass investing” which is the opposite of day trading. Rather than being in the market every day (chasing trends, reacting to fluctuations, and trying to time transactions) Charlie advocates spending most of your time “sitting on your ass”. That doesn’t mean you’re doing nothing. It means that instead of constantly trading you’re spending your time in research and preparation for trading. Eventually, a top-tier opportunity will come along and your preparation will make you capable of recognizing it and betting big. That’s when you trade. After that, you’re back to “sitting on your ass”. Trust your research. Trust your choices. Don’t tinker. Don’t micromanage. Don’t panic. Just let the compounding effects of a good choice work in your favor. Day Trading, Day Developing As a day trader your job is to trade daily (it’s right there in the job title). If you’re not trading every day — following trends, reacting to fluctuations, timing trades — then what are you even doing? Not your job, apparently. I think it’s easy to view “development” this. You’re a developer. Your job is to develop programs — to write code. If you’re not doing that every single day, then what are you even doing? From this perspective, it becomes easy to think that writing endless code for ever-changing software paradigms is just one develops websites. But it doesn’t have to be that way. Granted, there’s cold-blooded and warm-blooded software. Sometimes you can’t avoid that. But I also think there’s a valuable lesson in Charlie’s insight. You don’t have to chase “the market” of every new framework or API, writing endless glue code for features that already exist or that will soon exist in browsers. Instead, you can make a few select, large bets on the web platform and then “sit on your ass” until the payoff comes later! An Example: Polyfills I think polyfills are a great example of an approach to “sit on your ass” web development. Your job as a developer is to know enough to make a bet on a particular polyfill that aligns with the future of the web platform. Once implemented, all you have to do is sit on your ass while other really smart people who are building browsers do their part to ship the polyfilled feature in the platform. Once shipped, you “sell” your investment by stripping out the polyfill and reap the reward of having your application get lighter and faster with zero additional effort. A big part of the payoff is in the waiting — in the “sitting on your ass”. You make a smart bet, then you sit patiently while others run around endlessly writing and rewriting more code (meanwhile the only thing left for you will be to delete code). Charlie’s business partner Warren Buffett once said that it’s “better to buy a wonderful company at a fair price, than a fair company at a wonderful price”. Similarly, I’d say it’s better to build on a polyfill aligned with the future of the platform than to build on a framework re-inventing a feature of the platform. Get Out Of Your Own Way Want to do “Day Trading Development”? Jump tools and frameworks constantly — “The next one will solve all our problems!” Build complex, custom solutions that duplicate work the web platform is already moving towards solving. Commit code that churns with time, rather than compounds with it. Want to do “Sit on Your Ass Development”? Do the minimum necessary to bridge the gap until browsers catch up. Build on forward-facing standards, then sit back and leverage the compounding effects of browser makers and standards bodies that iteratively improve year over year (none of whom you have to pay). As Alex Russel recommends, spend as little time as possible in your own code and instead focus on glueing together “the big C++/Rust subsystems” of the browser. In short: spend less time glueing together tools and frameworks on top of the browser, and more time bridging tools and APIs inside of the browser. Then get out of your own way and go sit on your ass. You might find yourself more productive than ever! Email · Mastodon · Bluesky

3 days ago 4 votes