6 ms·
I've learned this as "swallowing errors" and IMO it's a poor practice. Not only does it not solve the issue at hand (you cannot print on an xbox), but it active
by maerF0x0 3y ago
I've learned this as "swallowing errors" and IMO it's a poor practice. Not only does it not solve the issue at hand (you cannot print on an xbox), but it actively hides how broken the software is, which makes bug discovery and testing much harder.
This is one thing I like about Go's panic. You're mostly not supposed to use it or recover from it at run time. It serves as a great vehicle to blare loud sirens at testing time that you (the programmer) screwed up (and that's ok, we all do), and it's time to figure out where and how to fix it :)
PS this analogy works in a lot of domains - If you have actors in a system actively trying to hide their flaws/errors it will be exponentially harder to root them out and solve the issues.
- gruez 3y ago>It serves as a great vehicle to blare loud sirens at testing time that you (the programmer) screwed up (and that's ok, we all do), and it's time to figure out where and how to fix it :) Right, but if you read the article, the author is talking less about the developer experience and more about the user experience. "blare loud sirens" is great if you're a tester/developer, not so much if you're an end user. When it comes to the end user, "swallowing errors" is preferable to crashing.
- ploxiln 3y agoIf you read the article, this isn't swallowing errors, it's just returning more-backwards-compatible errors. > ...when the app tries to print, it will ask the user to select a printer, and show an empty list. The user realizes, “Oh, there are no printers,” and cancels the printing request. > To deal with apps that get fancy and say “Oh, you have no printers installed, let me help you install one,” the function for installing a printer can return immediately with a result code that means “The user cancelled the operation.” > a documented return value is ERROR_CANCELLED to mean that the user cancelled the creation of the widget. Therefore, apps are already dealing with the possibility of widgets not being created due to conditions outside their control, so we can take advantage of that I'm annoyed when "modern web apps" (or similar desktop apps) seemingly do nothing when there's some error, you don't know if you need to wait a bit, or click again (great fun when the UI jumps 1ms before your re-click), or full reload/restart ... luckily that's not at all what this article recommends!
- amelius 3y agoMaybe then raise an assertion error, which only has an effect in development mode.
- Arainach 3y agoNothing is being compiled here; your customers aren't running debug builds of their apps, and the API code is part of the platform and isn't running the debug bits.
- ryandrake 3y agoEven as an end user, I hate when my computer seems to be trying to hide something from me. Even if I can't do anything about it, I want to know it's happening. Don't worry, Microsoft. I'm a grown-up and can handle the bad news. If I'm a layman, maybe I just dismiss the dialog and try again. But if I'm a little more of a power user, maybe I'll look up the error message and see if I can start diagnosing or helping. If you swallow the error message, I'll have zero idea that something is even going wrong! And almost just as bad: if you put up one of those useless infantilizing "oopsie doopsie computer made a poopsie" error messages, I still won't know what went wrong AND I'm being treated like a moron. I worked for a software company once where our software basically crashed every 2-3 hours of continuous use due to a huge backlog of technical debt, memory leaks, and years of rushing. My manager's solution to this was not to fix the bugs--it was to build a separate "launcher" process that would detect that the application crashed, eat the error messages, and silently re-launch it hoping the user doesn't notice. Way to treat your users with respect...
- Arainach 3y agoThere is no error message here - more often than not it's a straight up crash. No HRESULT, no popup, just NullPointerException, straight to jail. In many cases like this, crashes like this are in app startup, so it's not like you learn not to hit a certain button - it's just that the app doesn't work, an awful UX. As called out in the article, there are (and always should be) APIs like "IsPrintingEnabled" so that forward-thinking apps can show better UX. These practices aren't for those apps, they're for everyone else. Also, if your app preserves state well enough that a keep-alive daemon can restore after a crash and the user doesn't notice, that is ABSOLUTELY an improvement in UX over just crashing. Sure, you should still fix the bugs, but don't let perfect be the enemy of good.
- pjerem 3y agoI’m sorry, maybe the article used the wrong example but the main issue comes from the fact that an Xbox app is trying to print something. It should fail, not for the developer experience, but because to start, there is no way the user would want to print something on an Xbox. Something is already really wrong with your app if it tries to do things like this. Also he says that apps are developed and tested on PCs and that they could print in this context. I don’t know a single thing about Xbox development but I hope you can run/debug them in the Xbox environment (or a simulation). Let me hope that nobody is running their Xbox apps/games on Windows APIs at development time and releases them on Xbox without further testing.
- jacobgkau 3y agoThe point is that the UWP allows running apps developed and tested on PCs on an Xbox. It's for the user's convenience (not having to wait on developers to port to Xbox) as much as the developer's (not having to port to Xbox). If a user wants to run an app on their Xbox, telling them "no, the developer didn't test this on the Xbox, so I'm not going to let you do that because you might try to print and get confused about it" isn't what the user wants to hear. When the app tries to print because the developer was "lazy" and didn't test on Xbox, telling them "I'm going to crash your app now because you clicked Print, even though I know you're on an Xbox and I could just ignore that" also isn't helpful to the user.
- lloeki 3y ago> The point is that the UWP allows running apps developed and tested on PCs on an Xbox. It's for the user's convenience (not having to wait on developers to port to Xbox) as much as the developer's (not having to port to Xbox). It's interesting because that's true in some way (in the sense that PC and Xbox are different), and also not true in another (in the sense that a Xbox is in a way a PC, only with a different UI paradigm) So in the latter sense UWP allows developing apps for that universal platform, and it only so happens that some apps are only designed, developed, and tested for one system (PC) these apps can run on. In a way I can see working from the Xbox up being a better way to have a robust, secure, uniform platform than the Windows 8 attempt of slapping a secondary paradigm on top of the Windows 1.0 / OS/2 descendants. I mean, the facility that underpins e.g WSL2 is exactly the same as the one that underpins Xbox game/apps segregation and Quick Resume. In a way the Xbox OS is very much like Qubes OS! In a way the OS UI we see on an Xbox device is a UI for the hypervisor itself. I would certainly be interested in a "PC" that is so stable, restores state exactly upon updates, "it just works", allows to play games, allows to run a bunch of Linux VMs, with forever perfect backwards compatibility across hardware arch changes and OS evolution through virtualisation/emulation, and has a UI that allows many kinds of inputs and scales from big screen (gamepad, that accessibility input device I can't recall the name) to desktop (kb+mouse) and possibly laptop or even tablet/phone. I mean it's not that far fetched (technically) that MS would announce tomorrow that an Xbox can run Linux, Windows 10, or even Windows 3.1 in a VM: all the facilities are there and you can even plug a keyboard + mouse today. One may philosophically balk at the idea ("How dare you touch at my very open IBM PC! Where are my floating windows! Freedoooom!"), but I think it makes sense technically, and it makes sense as a product, and MS has all the bricks to make it happen.
- thfuran 3y agoThat is a dangerous assumption. Unless you know a great deal about every possible use case, you can't know the potential ramifications of incorrect output. Proceeding from invalid state (which would often be the result of swallowing errors) is essentially undefined behavior.
- Arainach 3y agoThis isn't invalid state. They're not telling the app about a fake corrupt printer, they are using the API contact to represent the truth (there is no printer you can use) in a way the app already has to support
- thfuran 3y agoBut I was responding to a general statement.
- kelnos 3y agoAnd I still think you're wrong. If incorrect input can't be handled gracefully in a way that you can be sure nothing bad will happen, it's possible that crashing is the best option. But I think in most cases that just isn't what's going on. An unsupported API that makes a feature not work is just not a big deal. Lack of support, say, for a cryptographic primitive, could be a big deal, so you might choose to handle that case differently.
- thfuran 3y agoAnd would you treat an API endpoint that's down the same way? Just silently ignore that a feature that's part of the user's workflow isn't actually working, that maybe only half of what was supposed to happen when they pressed a button actually happened?
- kelnos 3y agoYes, and in the case presented in the article -- trying to print on an Xbox -- we really do actually know the potential ramifications of trying to print and then being presented with no printers to print to. Simply: there are no ramifications worth worrying about. On the other hand, we do know what will probably happen if an undocumented exception gets thrown: the app will crash, possibly causing the user to lose data.
- mey 3y agoError design depends on context. For most of the systems I work on, fail fast on request for anything out of spec is the correct design. B2B/Microservices/API focused systems. Windows however has focused on bending over backwards to provide compatibility (including memory patching popular software that was broken, like Simcity https://arstechnica.com/gadgets/2022/10/windows-95-went-the-extra-mile-to-ensure-compatibility-of-simcity-other-games/ https://arstechnica.com/gadgets/2022/10/windows-95-went-the-... ). In the context of a user desktop where a user has no control of correcting the system code, the final experience is more important that correctness in many cases. It doesn't matter who is "in the wrong". Microsoft learned that it doesn't matter why the BSOD occurred, just that bad software/hardware was giving them the bad reputation. So yeah, fail fast/halt catch fire on any invalid input/condition is my personal preferred design, but I can see the value in this approach in this environmental context. The important thing here is that context and not applying either dogmatically. Don't take Mr Chen's approach in reactor or HFT designs for example. Fantastic approach for game engines.
- PaulHoule 3y agoIt's hard to overstate how hard Microsoft has worked to maintain backwards compatibility. Recently I had to read an old Access file and where I work we still keep Office '97 around for this purpose and it is quite amazing that it installs and works just fine on Win 11, Clippy works just fine, in fact all the other lame-ass things Office '97 does to take over your desktop all still work even if they don't quite visually match the current desktop. The thing is that Microsoft has a framework built into Windows where they can specify different system behaviors such as that Simcity case where the game didn't work with a new memory allocator so they put in a flag so an application that needs it can get the old memory allocator. They have a very systematic approach to the half-baked and haphazard process of patching the OS so you don't have to patch applications.
- elevatedastalt 3y agoIt's hard to overstate*
- 3y ago
- greatgib 3y agoThis is the Microsoft way to do things, this is why their products like Windows are so crappy, full of bugs, unexpected behaviors and a big dump of shit of legacy behaviors expected on top of a lot other legacy behaviors on top of another 1989 legacy behavior that every forgot.
- vikingerik 3y agoMuch of the crappy legacy behavior that Microsoft maintains is the fault of other applications, not themselves. The classic one is the error code for the file open function. Early DOS would return error codes of only 3, 4, 5, and no more. DOS programs would actually just indirect-jump using the error number as an index into a lookup table of addresses. When Microsoft tried to add any error codes (say 6), the program would jump out into hyperspace since 6 was beyond that lookup table and that memory word could be anything. So Microsoft was stuck folding every possible file open error into code 5, and to this day that's why just about any file error in Windows just says "5 Access Denied". And no, Microsoft couldn't add more error codes and just let the applications break, since then nobody would buy the new operating system versions that their programs wouldn't work on.
- gruez 3y ago> When Microsoft tried to add any error codes (say 6), the program would jump out into hyperspace since 6 was beyond that lookup table and that memory word could be anything. So Microsoft was stuck folding every possible file open error into code 5, and to this day that's why just about any file error in Windows just says "5 Access Denied". And no, Microsoft couldn't add more error codes and just let the applications break, since then nobody would buy the new operating system versions that their programs wouldn't work on. This doesn't pass the sniff test because 1. There's documented error codes that go all the way up to 16k: https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- https://learn.microsoft.com/en-us/windows/win32/debug/system... 2. There's file related error codes way above 5, eg. ERROR_FILE_EXISTS 80 (0x50) The general gist of your comment is correct though. Suppose windows didn't have file locks before and they were adding it. Returning an error code like FILE_LOCKED or whatever would be much more descriptive, but would also require all existing code to handle this error case. With that in mind returning ACCESS_DENIED makes perfect sense, even if programs aren't using jump tables.
- derefr 3y agoThe point of the article, in large part, is that when you’re designing an alternative runtime for a new platform, it is up to you what conditions are considered to be errors. Deciding to make a component of the runtime “inert” exists before and above the decision to make the implementation panic. In this specific case: it is up to Microsoft to decide what the semantics of “printing on an Xbox” are. It could be an error; or it could be something that “could be supported in theory in the future, but for now has no way to actually accomplish it.” This is a design choice, not a development choice. After all, in theory, you could print on an Xbox — plug in a USB printer, find a “game” that knows how to print (some enhanced port of a Gameboy game that had GB Printer support, maybe?), and tell it to do so. It’s not necessarily, fundamentally an error that a Xbox game is trying to print. You could define it as an error — but that’s a choice like any other, with trade-offs (in this case, to application portability.) You could define it as asking for the user to choose from no options, as the Xbox actually does. You could have the API lie and say it printed something. You could even actually support printing. These are all choices. It’s only once you’ve made that choice, defining the semantics of “printing on an Xbox” as an error, that it becomes an implementation/debugging problem if that error isn’t thrown — i.e. gets “swallowed.”
- freeone3000 3y agoUWP apps that don’t require specifically desktop APIs will run on Xbox — including, for instance, Excel.
- RetroTechie 3y ago> In this specific case: it is up to Microsoft to decide what the semantics of “printing on an Xbox” are. It could be an error; or it could be something that “could be supported in theory in the future, but for now has no way to actually accomplish it.” This is a design choice, not a development choice. Anything wrong with "print to file"? There'd be no dead tree output but (file) output nonetheless & printing as a function should work. Btw love the title of this article!
- WalterBright 3y agoIt has irked me for decades that when the internet connection fails, all you get is a message that it failed. But what failed? 1. the software on your computer 2. the computer's hardware 3. the ethernet cable or wifi 4. the switch 5. the router 6. the cable modem 7. the internet cable to your house 8. the ISP 9. the remote system you're trying to connect to Nothing has improved for decades.
- Am4TIfIsER0ppos 3y agoAdd a parallel step there, somewhere, for DNS. My raspberry pi runs pihole but the hardware is failing somehow so the server crashes so DNS lookups fail. All existing connections are fine, direct IPs are fine, locally cached results are fine, but new lookups fail. It is somewhat fun to watch it happen.
- tinix 3y agoKeep going... ... Try: ISP router intercepts DNS and drops the record because your company put private addresses on public DNS and the router has rebind protection.
- EnigmaFlare 3y agoWindows has a tool to diagnose network problems, and it's usually completely useless but I think DNS not working is something it does identify.
- WalterBright 3y agoWindows has a button to diagnose failed internet connections, but it has never reported anything other that the internet connection doesn't work. It's pathetic.
- flir 3y agoI've been suffering that TODAY. "Connection Refused No Further Information" Well thanks pal.
- deleted 3y ago[deleted]
- wvenable 3y ago> I've learned this as "swallowing errors" and IMO it's a poor practice This is not swallowing errors. This, in the Linux parlance, is not breaking user-space. There are two ways to handle the situation presented: error out because the machine can never have printers or return an empty list of printers because the machine can never have printers. They're both valid but only one of them doesn't break user-space.
- Trollmann 3y agoAgreed this is akin to HTTP 200 {"error": "Not found"}
- samatman 3y agoNot at all! It's like porting a program which expects there to be a TCP stack to a system which doesn't have one, and wiring up a component which responds to all HTTP requests with 404 instead of letting it hang on an infinite loop or crash. Say it uses a browser for rendering, but in the original you can also fetch websites, and the assumption is deeply baked into the code. If your choice is between playing whack-a-mole with all parts of the system which might call out, or just issuing a 404 (after all, if there's no Internet, you're not going to find a web page on it), that's a reasonable way to solve the problem.
- nonethewiser 3y ago> responds to all HTTP requests with 404 instead of letting it hang on an infinite loop or crash How is a 404 equivalent to not throwing an error? 404 would be like throwing the error and then not handling the 404. And the equivalent of hanging and crashing in the xbox example would be hanging and crashing.
- h0l0cube 3y agoThis is something that Elixir nailed. The typical idioms for return types are `{:ok, ok_value} | {:error, error_value}`, for which callers can pattern match against and handle appropriately. If fail-fast is desired, many functions will also have a variant signaled by a postfix exclamation mark (e.g., some_function!(...)), that returns `ok_value` or raises an exception.
- nonethewiser 3y ago> This is something that Elixir nailed. The typical idioms for return types are `{:ok, ok_value} | {:error, error_value}`, for which callers can pattern match against and handle appropriately. Agree this is a good pattern. Im not categorically against throwing errors but I like returning errors or the result and then having to check at the caller. Do this in typescript a lot.
- h0l0cube 3y agoAny typed language could use this pattern, though with Elixir specifically it was idiomized from the very beginning and all libraries use it, which makes error handling very consistent even when piping operations. The common option to fail fast is also handy when crashing the process is preferred and no matching is required to unwrap the value
- perryizgr8 3y ago> Not only does it not solve the issue at hand It does actually. This approach ensures that old apps (whose authors never thought it would run on something called an Xbox) will seamlessly run and perform all functions properly except for printing, which isn't supported on Xbox. Panicking here would mean every older app has to update their code to support Xbox.
- stubish 3y agoAs a Go programmer, how often do you check if fmt.Print returned an error? You get to assume that stdout and stderr exist for a start, even if your code is being run in an environment where that makes no sense. And what is the correct behavior for your software when IO errors start happening when you print? In a dev environment, probably crash. But in a production environment? A customers workstation? The article isn't so much about swallowing exceptions, but more about designing the system so you don't have to raise exceptions.
- nonethewiser 3y ago> The idea here is to have the printing functions all behave in a manner perfectly consistent with printing being fully supported, yet mysteriously there is never a printer to print to. That kind of thing intuitively sounds bad. But I guess of this is in a space shuttle I would take that back.
- Wowfunhappy 3y agoThink of it like an emulator. The goal of DosBox is to provide Doom with the environment it wants so that it will run. That will necessitate some amount of lying.
- kelnos 3y agoCompletely disagree. Getting back at the programmer for making a mistake isn't what matters. Presenting the best experience possible to your users is all that matters. If the user clicks on a print button in an app on the Xbox, and the app crashes (possibly losing some of the user's data), that's a bad experience for the user. Why do that to them just to stick it to the programmer? And on top of that, now some developer at some company (often not even the person who initially made the bad assumptions about printing) has now been called in on a weekend by their boss to scramble to fix the issue and push out a new release. Why do that to people? Regardless, also consider the API contract. If the printing API isn't documented to throw any exceptions, and you start doing that, you're breaking the contract. You can't blame the programmer for not considering platforms without printing support; you've documented that API as always returning something without blowing up. But that's still irrelevant; don't break user code just because you can, or because it's more expedient for you to do so. Your Go example is completely unrelated; you're talking about making things blow up at testing time, which I agree is the right thing to do. But that's also when you have full control over the code and the testing. If a third-party platform API starts behaving in ways you didn't expect it to behave, that's a whole other thing.
- l33t7332273 3y ago>You're mostly not supposed to use it or recover from it at run time Are you serious? I thought a key principle of Go was to handle panics in a layered way at runtime
- maerF0x0 3y agoin my experience that's partly true (it's a judgement call and lies on a spectrum). Like a HTTP server should handle panics in handler code so as to not crash the other go routines handling requests. Or maybe a long running queue worker (eg reading off SQS) should recover from a single go routine handling a message (assuming it can recover and handle the next message successfully). But it'd be way out of scope to put a recover block outside every function call just incase it did a runtime error: index out of range [1] with length . In this way its much different than try catch in languages that explicitly call out what they throw
- admax88qqq 3y agoNah I don't think this counts as swallowing errors. There's nothing wrong or buggy about the printing API on Xbox returning a list of no printers instead of an exception. It's essentially the Null Object design pattern. Even Go implements this in the way that a zero list can still be accessed an jsut behaves as an empty list. Or in unix how /dev/null exists, which implements the file API but doesn't do anything. This is way nicer than fixing every UNIX program to handle stdout not existing sometimes.
- inglor_cz 3y agoI wonder if Go's panic was inspired by Symbian OS User::Panic, an uncatchable sort of exception that was only used in situations when the programmer screwed up. It would kill the entire thread. Not limited to testing time, though.