I am implementing a baremetal USB device stack in an embedded application and an having a really, really hard time.
The device in question is a decoder for sportive chronometry and uses lots of DSP for detecting and measuring when vehicles pass through the finish line.
I don't think the quote suggests that a programmer would mentally design a whole system before writing any code. As programmers, we are used to thinking in problems as steps needing resolution and that's exactly the 90% there.
When you're quickly prototyping to see what fits better as a solution to the problem you're facing, you must have already thought what are the requirements, what are the constraints, what would be a reasonable API given your use case. Poking around until you find a reasonable path forward means you have already defined which way is forwards.
I've used many times for small programs and such, even though I don't use any wine program on a regular basis.
However, I do play games on Proton all the time and everything mostly just works.
TDD can be valuable but sometimes hindering. I find myself often with an incomplete idea of what I want and, thus, no clear API to start testing. Writing a quick prototype -- sometimes on godbolt or replit -- and then writing tests and production code will actually yield me a better productivity.
I usually test all of the public API of something and only it. Exported functions, classes, constants and whatever should be tested and properly documented. If writing tests for the public surface is not enough, most likely the underlying code is poorly written, probably lacking proper abstractions to expose the adequate state associated with a determined behaviour (e.g.: a class that does too much).
I think this is only true upto some point. Ultimately the API of a unit of code is not fully defined by the public VS private language features, it is defined by the conventions for its use. If a field/method is public but it is documented to not be used by anything except, say, some tests, then it shouldn't be considered part of the actual API.
Even in languages which have a very powerful type system, there are assumptions that have to be left to documentation (e.g. that the Monad laws are respected by types which match the Monad typeclasses in Haskell). Testing parts which are documented to not be relevant is often actively harmful, since it causes problems with later changes.