If you're just going to sit there doing nothing, at least do nothing correctly
devblogs.microsoft.com
devblogs.microsoft.com
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.
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.
> ...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!
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...
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.
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.
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.
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.
This made much more sense when Microsoft had multiple platforms running windows with just different sets of apis activated.
At it's peak, this was: PC, phone, hololens, Xbox.
SMS apis may only work on phone, spatial APIs may only work on hololens, printing may work on several, but not all targets. There are ways for developers to check which APIs are supported at runtime, but you can still call these APIs since they are part of the UWP surface.
The base philosophy of "if it's wrong it should fail" is primarily for developpers, and shouldn't apply to generic customer products.
If it's dangerous, or will cost money, or will have severe ill adverse effects, I'd see the point. If a credit card transaction is wrong, make it fail.
But short of these extremes, the default should be graceful handling of exceptions and help the customer app keep going and deliver some value to the user even if it's poorly written, mishandling the context.
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.
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.
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.
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.
The only caveats I can think of are that it must prominently display that it’s running in a “compatibility mode” and that any encrypted subsystems can’t revert to a lower standard of encryption, which may render the application unusable anyways depending on how tightly integrated it is.
Here's a pretty detailed list:
- It is possible to target Windows XP SP3 (released 2008, EOL 2014, 10 years ago) from Windows 11 and Visual Studio 2022[1] using C++23. Windows 2000 can be targeted with a little more setup[2]. Windows 2000 is 24 years old this year.
- It is possible to run a binary written for and compiled in Windows NT 3.1 x86 on a modern 2024 Intel/AMD PC running Windows 11 with absolutely no modifications to said binary whatsoever. Windows NT 3.1 is 31 years old this year.
- It is possible to write one binary and target multiple versions of Windows by simply choosing a Platform Toolset, which is paired with a Visual C/C++ Redistributable.
- Windows has a run-as mode to run programs in what is essentially a super-thin VM; like you mentioned, emulating different iterations' behaviour for a given program.
All four of these are nearly impossible on Linux. The fourth is essentially Docker, which is needed even to target an older glibc (i.e. the equivalent of the first situation). Windows has gone to extreme lengths to not only maintain API compatibility, but ABI compatibility as well. The fact that unmodified binaries from 20, 25, 30 years ago can run without a hitch is a testament to how important backwards/forwards compatibility still is on Windows.
Side tangent: all the criticisms levelled at Windows here and in many hacker fora are limited to its userspace—things like its shell and user-space programs, and trivial complaints like 'Candy Crush', or 'start bar', or 'extra right click', or even 'PowerShell aliased curl to Get-Content, grr'. The userspace changes so often because it can; it is a superficial part of Windows. To the haters: Try actually programming with NT OS primitives and even the (undocumented) NT syscalls. It is as enjoyable as UNIX system programming, and I daresay more productive.
[1]: https://learn.microsoft.com/en-sg/cpp/build/configuring-prog...
[2]: https://building.enlyze.com/posts/modern-visual-studio-meets...
Day zero feature availability, without compatibility issues.
I would personally make use of this, I know of a 16-bit program whose latest version was released in the late XP days, so it's not even that old. The idea there was that it was always compatible with DOS, some users might presumably still want to run it on DOS, and there's no point in breaking that compatibility if modern Windows can run it just fine. Then development stopped, 64 bit systems got more popular, and a recompiled version was never released.
I guess the lesson there is that if you're keeping an API for backwards compatibility, some programmers will refuse to switch to a replacement to make their software work on older systems, making the API impossible to remove down the line without breaking modern programs.
I haven't tried running too many old programs, though, so I have no sense for how common this might be.
This seems like a norm for most operating systems. Linux mixes files from all sorts of apps all over the place, for example, and a `make install` might put files anywhere.
Somehow, it feels like you don't actually care about the point I was making as much as putting me down. I misspoke...barely, yet you're so fixated on pointing it out in the most unhelpful manner. You keep replying so why not try using more than one sentence next time?
Also, is this a trick question about binaries that weren't patched for y2k or something?
Which is weird considering the argument you had with others above about how "Linux (kernel) doesn't run software", was it a buildup to convince us that "GNU(glibc)/Linux" is really bad at running old binaries? Because your argument doesn't hold for the Linux kernel itself running statically linked binaries.
Last time I checked, hardly anyone uses their computer as an embedded board.
Not a kernel booting directly into an application doing straight syscalls.
Linux runs /sbin/init.
Which you can make any executable you want.
Not to mention initial RAMdisk (loaded by a bootloader like grub) which can be of arbitrary size & loaded up with an arbitrary ton of goodness.
But as you state: it's the OS-level ABI's (C library, desktop environments, middleware libraries, etc) that keep changing constantly. And thus, keep breaking pre-compiled binaries.
Source-level API vs. binary ABI stability. Kind of a philosophical debate imho. But sadly, even that source-level API isn't too stable in some circles.
NT seems to be a nice OS at the core, but that's more about what it can do and how it is implemented than about how pleasant it is to use. Some of its syscalls are much more convoluted than the UNIX ones. Typical functions take many parameters, some of them complicated on their own, and typical invocations pass a bunch of NULL arguments (you still need to roughly understand what they mean).
Linux has a stable ABI as well. For a given architecture, like x86_64, syscall numbers and their arguments and their arguments/outputs are expected to be stable.
The stable API/ABI promise of Linux is the syscalls, because at the end of the day that is the interface between userspace applications and the kernel, and kernel devs take not breaking userspace very seriously.
And on Windows, the opposite is true. The stable interface is the Windows DLLs that you are supposed to use dynamically. If you hardcoded the syscalls, you cannot complain if your application breaks because windows only promises that the DLL will not break backwards compatibility, and they reserve the right to change the syscalls with any update.
So you can have a Linux binary that works across many Linux versions without breaking. You can also have a Windows binary that works on one version of Windows but not the next.
I'm curious about this. What do you mean? I remember using Office '97 on a Windows '98 machine, but I don't remember Office trying to take over all my desktop.
But the primary resolution to that problem was to force hardware vendors to write higher quality drivers (or for MS to write good enough default drivers that HW vendors wouldn't need their own), not to hide the BSOD. Technical details were only removed from them 2 decades after MS started fixing drivers.
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.
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...
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.
Well. I have two or three (I am not even sure because for one email address there are probably two accounts, but no way to distinguish between them) MS Teams accounts. There is no painless way to switch between them. Currently there are probably at least three different MS Teams apps installed on my machine, one of them self-installed without my consent (my PC is not managed by an org or domain, it's mine). Switching accounts involves several confusing errors, at least three password inputs, and several complaints by MS Teams that something is wrong, but it won't tell me how to fix it.
Use the browser version they said. Well for scheduled meetings it works, but for adhoc calls Firefox does not (there is no reason provided, but at least it does say outright), while Chrome seems to work but does not transmit my voice and camera. All other meeting software, of course, works.
I am not the youngest anymore and this is my lifelong experience with Microsoft. Its software works barely enough to sell to corporations; poor users have to endure it.
And new app developers will have to build upon that. Imagine the next app developer, you have to take into account that a platform pretends to support printers when it is not the case. So you will do things like: if there is a printer api but i don't see a printer available (/connected), pretend that we can't print and don't show the button... and so on...
If you have doubts about that, you can read the history of the openxml format: https://ooxmlisdefectivebydesign.blogspot.com/2007/08/micros...
No, they can't. "The application" has already been written by a 3rd party who could be out of business for all we know.
> If it is does not work, it does not work.
Or you could let it keep working. Somebody might depend on it, and none of this is their fault.
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.”
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!
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.
Try: ISP router intercepts DNS and drops the record because your company put private addresses on public DNS and the router has rebind protection.
"Connection Refused No Further Information"
Well thanks pal.
From MSDN:
> An HRESULT value consists of the following fields:
> A 1-bit code indicating severity, where zero represents success and 1 represents failure.
> A 4-bit reserved value.
> An 11-bit code indicating responsibility for the error or warning, also known as a facility code.
> A 16-bit code describing the error or warning.
The "reserved value" also includes a bit for non-Microsoft code (which driver vendors and other API producers can use, although I don't know how often they do)
There's a list of common "facilities" here: https://learn.microsoft.com/en-us/openspecs/windows_protocol...
As a regular user, you will see errors like 0x8ACEF00D, but if you decode them, you can get a sense of what part of the system ran into the failure. Compared to the "negative value indicates failure, look up the possible failures and what they mean for every function" approach many other APIs follow, that's a welcome change.
Of course there's no guarantee that Microsoft doesn't return some kind of meaningless internal E_SOMETHING_WENT_WRONG value, but for a lot of APIs, there are details hidden in plain sight. It won't tell you your ISP's fiber has snapped, but it'll tell you if the problem is within the driver, a security limitation, an HTTP error, or a generic network stack issue.
Users should not be seeing "08CAE5D012" error messages. They should be seeing "Connection refused. (08CAE5D012)" messages, or "No connection. (83255321)" messages instead.
There's is a non-trivial protocol for translating HRESULTs into error text; but it is often not supported properly by Windows applications, or Windows OS components.
e.g. DirectX which returns generic 0x8004005 E_FAIL errors. Or the WinSock APIs, which return HRESULTs, but don't provide text message translations; or Microsoft Installers that report raw HRESULTs with no attempt to capture the associated error text.
With discipline, the entire system could have worked. But there wasn't, and it didn't.
1. DNS lookup fails because the DNS server address configured at the computer OR router is incorrect 2. DNS lookup fails because the configured DNS server is down 3. DNS lookup fails because some firewall is blocking requests to it 4. DNS lookup fails because the network was congested 5. DNS lookup fails because of interference in the Wifi channel from other Wifi networks 6. Etc. Etc.
So indeed, usually when the network is down you only get "DNS lookup failed". Because the actual reason may be complicated. Of course, usually it is due to your computer not being connected to a router so usually the error message hints at that (in layperson's terms: not connected to the internet). So that's why browsers hint at it being your connection, i.e. ethernet or wifi.
But there is no way to make sure. All we know is that DNS seems to fail. The reason it fails could be any part of its configuration which is spread out across physical systems and software components.
The best we can say: probably your ethernet/wifi connection. If we trust that none of the other components are failing then it must be your connection that is failing.
It's like trying to find out what's wrong in 1+2+32+4=10. Sure, it seems like the 32 should be a 3. But maybe the 10 should be a 39. There is no way to tell anymore. All we can do is make an educated guess.
1. is the printer turned on?
2. is the printer out of paper or ink?
3. does the cable have a loose connection?
4. is it the wrong printer driver?
5. do you need to reboot windows?
6. do you need to power cycle the printer?
No help anywhere. You just try things one by one, sacrifice a small animal, and then maybe the printer gods will smile on you and the printer will print.
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.
HTTP 200
{"error": "Not found"}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.
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.
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.
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.
The article isn't so much about swallowing exceptions, but more about designing the system so you don't have to raise exceptions.
That kind of thing intuitively sounds bad. But I guess of this is in a space shuttle I would take that back.
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.
Are you serious? I thought a key principle of Go was to handle panics in a layered way at runtime
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
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.
Not limited to testing time, though.
That file opens and appears to render just fine for me in Word 2016.
This has been my experience w/ Office files in general. Old files open and render very well in newer versions.
"Converting this document from its original format was a bit of a victory for open source software. And a lesson in how hard document preservation is."
So, opening this document was hard and that it finally worked was not because of Microsoft's alleged famous backwards compatibility- which is a myth in my book.
As long as there is no retroactive interpretation, like it happened with RGB, for example, the "doubt it" will stand.
Will it be a 1-to-1 with printed output from 1996? Probably not.
0: https://www.legis.state.pa.us/cfdocs/Legis/LI/uconsCheck.cfm....
My LaTeX files from 35 years ago, on the other hand - they just do fine.
Yeah, because they're plain text. A fairer comparison would be whether they render pixel perfectly as 35 years ago, which I doubt.
Compiled to PDF you might get very slight differences.
Which is used by approximately no one. Good luck uploading your resume in DVI.
Again, not my experience at all.
I think if a company didn't accept my PDF CV and asked for a Word file instead, I'd strongly reconsider whether I'm actually interested in working there.
A stable file format is the most important difference here, but the text encoding means that small incompatibilities can be solved by a human rather than needing to rely on an upstream maintainer to recognize and explicitly handle your unique situation.
And games? Microsoft broke numerous games by shutting down GFWL. I had to pirate Dark Souls as my original copy wasn't playable until it got re-released on Steam.
Source? This seems utterly bizarre.
That hasn't been the case in a long time, though.
[1]: https://en.wikipedia.org/wiki/Office_Open_XML#:~:text=Office....
https://www.joelonsoftware.com/2008/02/19/why-are-the-micros...
I remember back in school religiously saving new versions of Word documents so that if the newest version went bad I could start a fresh doc, then copy and paste sections from old versions via Notepad to cleanse the corruption. (Direct Word-to-Word could bring it across — I guess that tells us something about how they implemented copy+paste between documents, too!)
Starting from Office 97, they switched to an improved .doc, .xsl, etc. file format (even though it was still binary).
That's why modern software such as Office itself or LibreOffice call the .doc format "Microsoft Word 97/2003"
and cool that Mr Chen thinks about UX and compatibility, but MS as whole does not really. important business apps got special treatment, and that's it. (MS and its corporate entourage solved this mostly by providing Windows and "security" patches for it, for a lot of money.)
you get a dialog saying "unsupported"
now you can download dosbox but that isn't really "exactly as expected"
> To clear up some confusion: The idea here is that the printing API has always existed on desktop, where printing is supported, and the “get me the list of printers” function is documented not to throw an exception. If you want to port the printing API to Xbox, how do you do it in a way that allows existing desktop apps to continue to run on Xbox? The inert behavior is completely truthful: There are no printers on an Xbox. Nobody expects the answer to the question, “How many printers are there?” to be “How dare you ask me such a thing!”
If he just used the words "existing desktop apps" in the second paragraph of the article instead of the second to last, I don't think people would be reacting so negatively. Instead, when he talks about avoiding "gaslighting" by returning an invalid pointer by just gaslighting in a different way by lying about the error that occurred, it almost sounds unhinged.
If the app is not prepared for printing not being supported, and printing just throws an exception, the app probably just crashes. That's bad.
If the app is prepared for printing not being supported, it should be calling the explicit API to check if printing is supported, and then not displaying the UI for printing if it isn't. The article is not about these apps, it's about what to do about apps that fail to check first.
The bug is with the app, but a good platform does its best to make bad apps work anyway, rather than have them just crash.
That's the whole point of this article - when you can't control the various platforms that your application is run on, you want to try to do the "least bad" thing, even if that platform didn't anticipate the situation of, in this case, telling people that printing isn't supported.
I don't know about that. If it crashes, I might not try that thing again.
first of all, i certainly wouldn't be more frustrated if the app just crashed, but how about just letting the user know that the xbox can't print? why does everybody seem to think that's out of the question?
Because the situation described is about an application that was made for PC (which supports printing) and a user is trying to run it on an Xbox (which doesn't support printing) with the developer never even imagining someone will try to run the program on an Xbox in the first place. You can't implement a message about an error you don't even know will happen.
My point was that, as an end user of such apps on Xbox, my preference would have been to have the Xbox OS tell me directly that printing is not supported on this system, even if the app doesn't know about this.
Xbox cannot tell you that there is no printer support before you try to do something related to printing because it doesn't know you may want that. An application that was made for Windows also can't do that because on Windows you can add printers (even fake ones that print to PDFs, no hardware needed).
I see Microsoft has not learned from 30 years: https://www.reddit.com/r/hacking/comments/djvzd/windows_nt_l...
The way they've worded this betrays the internalization of their suffering as a MS developer.
It all depends on how the clients are currently using the API. If the clients are already testing for NotSupportedException, then that's what you should return. But if not, you need a different approach.
If you're talking about making backwards-incompatible breaking changes to an API, that's another thing.
The article:
> The app that the user installed on the Xbox was probably tested primarily, if not exclusively, on a PC, where printing is always available.
I.e. there is no concept in the (desktop) Windows printing subsystem of printing as a feature not being available; on desktop Windows, printing as a feature is available by definition.
It's entirely correct to return error codes, and any client is expected to handle that.
Actual exceptions — in languages that have them — are a bit different, in that they “do” something by default: they propagate and unwind unless they’re caught. And so, new (unchecked, if in a language where that’s relevant) exceptions can be introduced after the fact under the presumption that the runtime’s default behavior for propagating unknown exceptions will kick in, and that this will trigger the desired result for applications that weren’t written in awareness of that particular exception.
Error codes aren’t like that; they have no default semantics as a class, only explicit default semantics per function and/or per algebraic error-code type, if-and-where documented as such. New error codes simply aren’t meant to be introduced in most APIs, unless those APIs have rules about e.g. generalized default handling for defined code ranges that new codes can be later slotted into.
Basically, error codes are weak enums. If you’re writing a dynamic-link library (or a runtime — same thing, basically), you’re not supposed to add new potential values to an enum used as a return value: client code will likely have been written to switch on the value with the known options as cases, and your new value won’t be in there.
Correct. The error `ERROR_CANCELLED` is defined in WinErr.h and it's translated via `HRESULT_FROM_WIN32` in the same[1]. It was this change pointed out in `CreateWidget` to get around returning the null pointer that he was suggesting would be better to make the API inert.
[1] - https://learn.microsoft.com/en-us/windows/win32/api/winerror...
If the API was never expected to throw NotSupportedException or return an error code, then all of a sudden starting to throw in a future release breaks the API contract, and the client cannot be expected to handle it sensibly.
EDIT: Duh! My comment is useless. This was the exact conclusion that the article came to, too. So instead of reading this comment chain, just finish the article :)
Has the Xbox ever supported printing? Why even have these APIs? Just don’t offer them at all in the Xbox SDK. You shouldn’t be able to compile code that tries to call these when targeting Xbox.
Xbox essentially runs Windows. Therefore, the Windows API is available on Xbox.
It seems like an enormous amount of effort for an extreme edge case. It’s this weird obsession Microsoft has with the flawed idea that you should be able to run anything on every device without modifications. It’s their unwillingness to acknowledge that different types of devices require different user experiences.
Raymond is behind arguably the foremost exemplar of this (Windows) but the same thing happens in the Linux kernel ABI, glibc, the web platform, Java, and so on.
If you were on the Windows team and I was your manager, I might fire you for that.
This is Windows. You do not break applications that users depend on. Ever, ever, ever. If you have a "shitty" or misbehaving client application, you use whatever workarounds, shims, and compatibility hacks it takes to make the application work as expected. Even if it means having special memory management code for SimCity so it will work.
But I suspect the situation this is being designed for is existing PC apps being ported to an Xbox. OK, in that case I can see fudging the API since there might be obscure corners that the devs didn't think about that try to print. But I'd still say the devs should be testing on an Xbox and make an effort not to attempt to do things when it doesn't make sense for the platform.
“We’ve decided software that operates your 100 ten-million-dollar-each CNC machines is ‘shitty,’ so buy new equipment so you can get Windows 11” isn’t going to fly, it would get the whole company laughed out of the room.
Especially because what is allegedly making them shitty would just be someone’s failure to predict some minor detail about the future of the platform. APIs do have to change, and the creative part is thinking of how they can be safely rendered inoperable without damaging anything that didn’t predict that removal. Sure, you can’t print, but that’s in this example a deliberate design decision of the platform, probably for good reasons.
...and then you'll also have to re-write your software to support Win 11, of course.
While I feel less strongly about this Xbox/printing example, I remember Bill Gates saying "I reboot my computer every day" which is a similar mindset-- this culture has been forced to adopt a certain form of "hygiene" due to that same culture NOT adopting hygiene preemptively when they built their systems.
Really, emulation is all about telling lies. Your Xbox doesn't actually have a way to attach a printer. You're running a game on Linux, not Windows. Your fake iPhone is actually a ARM server in AWS. The point here is that if you're going to lie you better do so convincingly. That's because you need existing applications to still work! When Microsoft says you can port your existing Windows app to Xbox the promise for the Windows app was that it would be able to print, and so Xbox needs to lie for that to happen.
This is very different from a normal error. If a program does a use after free, and you silently pretend the bug doesn't exist by working around it, then you're not doing anything correctly. That's because nobody promises that your existing use after frees will be bug-for-bug compatible on a new platform.
> For example, Windows has an extensive printing infrastructure. But that infrastructure does not exist on Xbox. What should happen if an app tries to print on an Xbox?
It says nowhere that the context is doing emulation for software that will not change. You just assume that because it supports the position you like. In fact, everything written applies to a program that I might write tomorrow for an XBox, and try to print something. There is nothing that designates this behavior only for old, unmaintained software.
That is the whole point! You don't have a choice for software that will not change - all you can do is try to keep it working anyway. Like they did here.
That you are not "motivated" to do things correctly is not a convincing argument otherwise.
If you don't want this behavior in your own apps, you don't have to invoke it. Using the API correctly sidesteps all of this but is not a choice when "doing emulation for software that will not change."
OTOH I absolutely agree this is a good call if your goal is for more users to be able to run more software on your platform, even if printing is broken.
The point of the blog is to make the process of bringing apps (UWP) to XBOX be frictionless: no recompile required, no messy ifdefs, none of that extra work. The App would "just work". Then, it's up to the developers to start adjusting the app to fit the XBOX platform more. The important thing here is that the developer was able to bring the app with no effort to XBOX. This is good for both the platform and the developer.
To the user, it's a clear signal that they can't print since the list of printers are empty. But most importantly for them, the app did not crash or show the most hated error: "oops something went wrong. Try again later."
Is that message a better experience for the user? No.
Sure, the developers can recompile the app and add a more descriptive message but then we're back to square one.
for example, accusations of swallowing errors. That's not the point, not at all.
Add a printer in Settings. While the printer is installing, click over to the "Color Profiles" tab. If you time it right, gnome-control-center will crash. If you dive into the details, you see that it was trying to enumerate the available printers (it knows one should be there) but that info doesn't exist yet. So it just crashes.
Thankfully, the fix is to just wait a few seconds for GNOME to finish installing the printer and restart Settings. Still, it's the principal app responsible for making your desktop work correctly as an end user with some unknown computing background. In a perfect world, this app should never crash.
It's hard to think about edge cases. It's even harder to imagine your handling of edge cases has its own edge cases. Right or wrong, at least the author is thinking deeper than "bad app, needs to be rewritten to support Wayland"
I thought we learned from that experience. Apparently not.
See this, hilariously hosted also by microsoft: https://techcommunity.microsoft.com/t5/discussions/funny-sto...
> And then Google built Chrome, and Chrome used Webkit, and it was like Safari, and wanted pages built for Safari, and so pretended to be Safari. And thus Chrome used WebKit, and pretended to be Safari, and WebKit pretended to be KHTML, and KHTML pretended to be Gecko, and all browsers pretended to be Mozilla, and Chrome called itself Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13, and the user agent string was a complete mess, and near useless, and everyone pretended to be everyone else, and confusion abounded.
Could we possibly do away with the User-Agent header, or reset it to a simple “Chrome 150.01”?
Also I’m amused checking mine that the user agents still say “Intel Mac OS X” even on Apple silicon. I guess they were afraid someone’s parser would think we are on PowerPC without that!
I would not miss much if I was time-traveled to 1999.
If early browsers displayed an error the first time it came across an <img> tag, instead of just best-effort rendering the page, then every new browser feature would have been smothered in the cradle.
<p>Hello
<br></br>
World!
And see the errors that now show up because of the wisdom we gained… wait, it still renders alright? I guess we still have much to learn then. Or, there might be something to gracefully handling certain classes of errors while crashing on exceptional cases.This is a completely normal usage and some people even author their HTML like this. Granted this is part of the effort to standardize error handling.
That unclosed <p> will auto-close as soon as you start another paragraph or close it's parent element. Likewise this is how I do lists these days:
<ul>
<li> One
<li> Two
</ul>
The subsequent li's will close the previous and the bounding ul ends the last list item.Which means this "solution" to a stupid, self-created problem is stupid. I bet this workflow will lead at least a handful of people to ask "How do I add a printer to my X-box?" instead of "Fuck the app crashed, better not do that again."
Microsoft has so much stupid, corporate driven decision making. Can't wait for it to follow in IBM's footsteps.
This seems like a long way to go for “we know that this device is an Xbox and Xbox doesn’t support printing, let’s tell the user”
Only it doesn’t tell the user. It leads them down a path implying implementation is possible.
On the other hand, I now know why so many issues I’ve troubleshooted on MS products end in tears and complete confusion as to why they wouldn’t just say “this is not a feature you can use on this device.”
You're missing the fact that Xbox can run apps developed for (desktop) Windows, and that the scenario in the article is about the platform <-> end user relationship and does not involve the app developer at all.
Doesn’t the platform: 1. Know that is a windows app 2. Know that it is Xbox
So it could override the “print” request with a user appropriate notification?
"apps that assume that printing works will still behave in a reasonable manner: You’re just on a system that doesn’t have any printers and all attempts to install a printer are ineffective."
Maybe the underlying assumption is that the users will give up before spending an "unreasonable" amount of time on these tar pit features.
As the author is a Microsoft employee I'm a little surprised no attribution or reference to the original author of (the levels of) exception safety guarantees which his article partly describes.
Raymond Chen (article author) is refering to the "no throw guarantee" in his article as opposed to one of the other outcomes https://en.m.wikipedia.org/wiki/Exception_safety
Exceptions are such a catastrophically bad idea in almost all cases.
It is absolutely infuriating as a programmer to call a function and not know if it can throw and, if it can, not know what it can throw. It’s a disaster.
I so desperately wish that C++ had Rust’s Result type and pattern matching. std::optional and std::expected are kinda sorta ok, but you really want compiler enforced pattern matching.
What a tragedy.
noexcept.
Granted, it may not have the annotation but still not throw in reality, but a Rust function can also declare a Result return type but never actually return an error.
> if it can, not know what it can throw
How do you square that with backward compatibility?
If you declare what you can throw, what do you or any of your transitive dependencies do when they want to change their implementation in a way that makes a new error a possibility? Either you shove it all into an UNKNOWN error that you hopefully declared from the get go to be future-proof, or you break all your downstream users every time. So either no compatibility, or over time your API converges to a meaningless UNKNOWN error code for almost everything and a bunch of legacy error codes that are never used.
boost and Python are my arch-nemesi because they make heavy use of exception errors and it makes the APIs an absolutely miserable nightmare to use.
> How do you square that with backward compatibility?
Huh? The same way normal code handles changing function arguments or return types? I have absolutely never relied on exceptions to “future proof” return error types! Yikes.
The only thing I have ever used exceptions for is to escape bad input/data. It gets trapped internally in the “private” API and same result types are returned through the public API.
I would much rather have a return type of Result<T, Exception const*> than T but also maybe it throws or maybe not and you almost definitely forgot to check which is why people do filthy filthy hacks like the OP article.
Every nontrivial function can fail (in C even a unary operation on an int), it's just a question of whether and how the caller is informed, how easily the failure is to ignore and continue processing in an undefined corrupted state, and what percentage of the code ends up being dead branches for impossible-but-unprovable error paths.
> I so desperately wish that C++ had Rust’s Result type and pattern matching.
I'm a fan of Rust too, but what do you think panic() is?
Rust has no concept of code that always succeeds. It's all-but impossible on current CPUs.
https://github.com/search?q=repo%3Arust-lang%2Frust+path%3A%...
https://doc.rust-lang.org/std/result/enum.Result.html#method...
e.g. before going to production with real users these cases should error as hard as possible, including potentially logging crashing the program to make the program errors super visible. Then in production it should largely log these things in error logs and keep chugging along.
And not like an environment variable with conditions. Something as first class as changing the standard exception and fatal calls behaviors.
You might be viewing something and want to print it, but that's clearly not desirable enough for Microsoft to build print functionality into the Xbox UI.
I'm sure there's something about "windows print subsystems are pretty terrible and we should excise them from anything we can" and "reduce code to reduce bugs" but like.... There's no technical reason it can't
Who do you blame, especially since the usual diagnostic tools of a PC with a full operating system aren't available?
It's a feature very few people will use with lots of sharp edges that people accept on a PC but would find intolerable on a video game console.
Features aren't free. What Xbox feature would you drop to have an engineer go implement printing APIs on them? Is that the best use of their time?
The article illustrates how *not* to build APIs.
I hope this is never shown to the user, because one of the most infuriating things that can happen is when the computer tells me that I did something I actually didn't.
On the other hand, I recall a few years ago (in the days of one of Apple’s least stable Mac OS [X] releases) seeing the message frequently after a random kernel panic “You restarted your computer because of a problem.” And I would be pretty ticked, saying “Nope! YOU restarted yourself. 0% of this was me. I was sitting here and you just died and rebooted.”
They changed it to use passive voice instead, a year or two after that!
This also isn't just about new platforms. If you have a desktop operating system and want to change the behavior of an API in a future version, you have to do this same process.
The entire point, it should be noted, is to gaslight the app. But the API must be good enough at gaslighting that the app doesn't discover the lie.
The Daily Azure shit Mastodon account has more than enough examples of this. For example https://azsh.it/167 or https://azsh.it/107
This article made me realize while Azure is the way it is - unreliable and broken.
What? Why would you ever do this? This post screams of "can't see the forest from the trees"
Sure, now you don't have your app crashing, and instead you have this weird state of seeming like you can print but ultimately can't, wasting users time and perhaps frustrating them even more.
Why not literally just show a dialog like "printing is not supported from an Xbox"? Easy to develop, easy to understand... everyone wins.
And I've written PHP4.
Stripping out the Windows types and compile-time validation and the wrappers, and picking non-Windows error codes, you can turn the code into more Unix-like C++:
int32_t CreateWidget(int32_t* widget)
{
*widget = nullptr;
return ECANCELED;
}
int32_t GetWidgetAliases(wchar_t* aliases, uint16_t capacity, uint16_t* actual)
{
*actual = 0;
return EBADF;
}
int32_t EnableWidget(int32_t widget, bool value)
{
return EBADF;
}
int32_t Close(int32_t widget)
{
return EBADF;
}
However, this code may not function if you're building for 32-bit Windows and it may not work on every compiler; it just assumes certain bit sizes that the API only guarantees in the form of typedefs.The goal, IMO, would be to force the app not to try (or not to try once it failed) something that is bound to fail.
this is exactly the kind of stupid shit that makes me hate using anything from microsoft. on what planet is this desirable behaviour? is it beyond microsoft's capability to just show a message saying "Printing is not available on Xbox"?
Bogus comparison. Non-crappy apps are a thing.
"Crappy" here refers entirely to developer hygiene, which the user does not care about at all.
If the platform changed and Angry Birds crashed, the customer would not accept "but look at all of these other Angry Birds clone games still available" as an answer, they want the app they are familiar with.
Angry Birds doesn't print AFAIK.
The scenario is an app being run on a platform that doesn't meet its declared system requirements.
If an app requires Windows, and customer tries to run it instead on Xbox OS, then he should be surprised it even launches. He should not be surprised if it crashes on print.
> customer would not accept "but look at all of these other Angry Birds clone games still available" as an answer, they want the app they are familiar with.
Then he'll have to run that app on the OS it requires. He's free to sent to MS his complaint that Xbox does not run that OS.
Telling customers "well go use this other platform" is not an effective way to build or grow a platform.
Honesty is the best policy.
Telling customers they should expect to run apps that don't support your platform is not honest.
There is no "build" because the source code was lost when all of the company's assets were sold off in 2002.
There is no "build" because the developer made a game, put it on your app store, moved on to the next game and has no interest in supporting this game that isn't providing any significant new revenue.
There is no "build" because this is FooManager 6.0, the company that makes FooManger wants everyone to buy FooManager 7.0 and isn't making any further changes to 6.0.
etc. etc. etc.
Someone wants to show some guests some of their photos and videos on their TV through their Xbox. Unfortunately they can't because their app (eg Samsung Gallery or iCloud or whatever) included a print button somewhere.
And with these inert functions, if Microsoft one day adds printing support to the Xbox, it'll just work in the photo app without any update.
This must be satire. Otherwise I can't comprehend how something as infuriating as this could be presented as a good or smart thing to do UX-wise
Printing may also run on startup. Consider software for a vinyl cutter which looks for the device when beginning.
Then my point stands.
> Consider software for a vinyl cutter
On Xbox?? Good grief.
Just because an XBox can't print doesn't mean that an app that prints shouldn't run on XBox. It should just mean that the printing function shouldn't run. How to achieve that is exactly what Raymond Chen, a Microsoft and Windows veteran, is trying to explain here.
It seems the point resembled: 'this device doesn't support printing, don't return obscure, unhelpful or crashing errors; return something that makes sense so that the user can figure out and move on'. I.e.: Fail gracefully.
If anything creating mystery about what the app is doing is the direct opposite of good UX.
1. App crashes back to the desktop/Home Screen/etc
2. App can’t find any printers. User cancels and saves the document, prints elsewhere.
You really think option 1 is better?
Also, none of this precludes the ability to display a message. He’s talking about the system calls themselves and how they should respond. I suppose if the call for the “Add Printer Wizard” is called, it could not only return the “user cancelled it” status but also display an error message. It depends on the implementation details and whether someone probably 20 years ago foresaw the need for a modal but not fatal system error message to be triggered by that API call. Which again is not in the today developer’s control.
Why do think it would crash, rather that simply return to main loop?
How in heck is that more useful than App reporting that "I can’t find any printers"?
And reports the exception.
> Well, the wrong thing to do is to have the printing functions throw a NotSupportedException. The app that the user installed on the Xbox was probably tested primarily, if not exclusively, on a PC, where printing is always available. When run on an Xbox, the exception will probably go unhandled, and the app will crash. Even if the app tried to catch the exception, it would probably display a message like “Oops. That went badly. Call support and provide this incident code.”
If they made an app only for PC, why would they test it on Xbox??
If they wanted their app to run on Xbox, why would they not make an Xbox version, and test it there??
RC's scenario is taking an app made for only Windows PC and running it on Xbox. I wonder if he has found even one example which permits this in the licence.
I don't know what program he would be talking about, but I think if Raymond Chen is writing about something, it's usually because it is a real problem that was encountered, even if he's writing about it as if it was hypothetical to avoid naming the software in question.
He generally avoids naming non-Microsoft software he's found bugs in.
I don't doubt that. But I do doubt the problem can be encountered except by abusing the app.
> He generally avoids naming non-Microsoft software he's found bugs in.
Not relevent, since this failure of Xbox to run a Windows app is not a bug.
I don't doubt that. But I do doubt this problem can be encountered except by abusing the app.
> He generally avoids naming non-Microsoft software he's found bugs in.
Not relevent, since this failure of Xbox to run a Windows app is not a bug.
By showing that no printers can be found the app is misleading the user to think there's an issue external to the app that they need to solve themselves.
So anyway, the platform vendor can’t be sure the above situation is perfectly handled by every app, so the entire point of the article is “given you must technically comply with the published API specifications, how can you construct the least harmful and least disruptive response to every request sent to this fully-removed system component.”
This whole exercise is basically constructed in order to usually guarantee the outcome you’re suggesting: to cause the app to just return to its normal functioning without doing the impossible thing.
There's no grace in misleading the user and wasting his time.
Thanks to anyone who replied to me pointing that out. It's a good example of when one should read the article more closely before commenting!
If that's really the suggestion of product and engineering leadership at MSFT no wonder all their products...err...work as designed.
When the software your customers are relying on breaks because of a change you made, it doesn't matter whose "fault" it is. It's broken, it broke because of something you did, and you have burned customer trust - not the trust of whoever wrote the software you believe is "wrong" or "to blame", trust of your platform and company.
An operating system with billion+ install base, and millions of developers tends to be complex. I'm not sure what you're proposing here, have your platform/software be more niche? Somehow get all of them to fall in line?
>So instead of handling errors properly you suggest to implement a convoluted user flow that offers always failing actions (install a printer when there's none available).
How are you going to "handle errors properly" if the publisher of the software in question went out of business?
This is for other developers who are writing 3rd party apps for Microsoft's platforms and who don't always test perfectly. They may have written their app primarily for Windows and didn't consider what happens when someone installs it on their Xbox and clicks "print". In that case, the API should "just work", instead of crashing with an error message.
Bad: good apps can't know what's supported or not.
What's missing from the article is adding a way for apps to detect and handle this behavior. (Using the printer example) There should also be some API that tells me "printing is not supported on this platform" somehow. If I want to be a good software developer I should hide the print button in the UI in a very predictable way.
It's great that if I actually try to print nothing happens as expected. It's bad if I can't detect that printing would never work, and I should be able to do that via at least some function call that doesn't magically noop.
> Now, you probably also want to add a function to check whether printing even works at all. Apps can use this function to hide the Print button from their UI if they are running on a system that doesn’t support printing at all.
Straw man. What's unethical here is deceiving the user.
"NotSupportedException" is there for a reason.
And not only that, we're fast approaching the day where we all power on our PCs to discover that you can login with any user you like. And it gives you the list of all users who have a one drive account.
I have a feeling that "solutions" like this are part of why an increasing number of my computing problems take the form of, "I tried to take an action, nothing happened. No error, no activity, nothing.", and are impossible to debug or diagnose. UX designers made themselves terrified of ever showing an error code to a user, but they took that and replaced it with a world where your shit just doesn't work, and when you try to figure out why, all the OS does is shrug.
Now when something goes wrong the system just kinda gets lazy and stops working. But it won’t crash.
I’ve had my mac pinwheel on the login screen. I can still access the shell and file shares remotely, and even screen share to a logged in user.
But login.app refuses to crash so it’ll just pinwheel.
I’m glad I never forgot to turn things off and on for troubleshooting :(
Next time it happens try turning network connections all the way off.
And when the older, already compiled executable calls the API, how do you make things "work"? That's exactly what the article is about.
Launching platforms is an eternal chicken and egg problem: You want to launch a new platform. Users want apps before they buy into the platform. Developers want users and a guarantee they will spend money before investing time and money building apps for the platform. If you're really really rich, you can literally pay developers to write apps for you, but ask Microsoft how that went with Windows Phone.
Instead, the most reliable way (I said most reliable, not reliable) is to leverage an existing group of apps onto your platform. Maybe you have a phone ecosystem and want to get into tablets. So you take the already existing phone apps in your store and let them run on your new platform.
There is no recompiling. There is no build.
There is no "build" because the source code was lost when all of the company's assets were sold off in 2002.
There is no "build" because the developer made a game, put it on your app store, moved on to the next game and has no interest in supporting this game that isn't providing any significant new revenue.
There is no "build" because this is FooManager 6.0, the company that makes FooManger wants everyone to buy FooManager 7.0 and isn't making any further changes to 6.0.
etc. etc. etc.
Binary compatibility is what matters. Nothing else is of particular significance.
In addition, if recompiling an app for your new platform yields compile errors and requires work (as opposed to targeting a new platform version in a manifest and just hitting build), developers on your platform are significantly less likely to spend the time to do so.
functions that return correct null responses isn't the ideal behaviour, it's the fallback for when you're already off the happy path.
CheckForPrinting : () -> Maybe PrintToken
ShowPrintDialog : PrintToken -> DialogThis is not weird "hidden state" on the implementer's side. It's a straightforward dummy API and all you need to do to test it are a few straightforward asserts that it returns the correct dummy values and doesn't crash.
> I have a feeling that "solutions" like this are part of why an increasing number of my computing problems take the form of, "I tried to take an action, nothing happened. No error, no activity, nothing.", and are impossible to debug or diagnose.
That's precisely not what this is. The whole point of the article is to do nothing correctly. Presenting an empty list of printers is consistent with a PC that simply doesn't have any printers installed. A wrong thing to do would be, for example, presenting a dummy printer that accepts jobs but of course never prints anything.
You don't break the users of your API, period. That shouldn't be controversial. Unfortunately, too many people seem to think they need to do everything over every couple of years only to produce a solution that is no more extensible and resistant to bitrot than the one they're replacing.
No test required. Just try... catch.
> for gracefully handling cases that were impossible when they were created?
You can never know they are impossible. That is why you have a top-level try...catch.
That doesn't even make any sense. Where on earth would you insert a try...catch?
So many people commenting on this article seem to have fundamentally misunderstood what the situation/scenario even is, which is made more jarring by the fact that so many others seem to have gotten it just fine.
Agreed 100%. Those people have overlooked that this is about attempting to run apps on an unsupported OS. And when printing, the OS attempting to gaslight the user into thinking the fail is his fault for not connecting a printer.
"The app that the user installed on the Xbox was probably tested primarily, if not exclusively, on a PC"
??
Note that Xbox OS is not Windows. If an app says "requires Windows", then it means requires Windows.