The one "rule" I wish it covered is about surfacing/exposing the conceptual model to the user.
If I don't understand the conceptual model of the product, I will always be confused, no matter how well-labeled the icons are. For example, imagine a product that has a "New Configuration" command. What is a "Configuration"? Is it like a template that lets me define other objects? Is it a way to rapidly switch between different sets of options? Is it a container, like a folder?
The UI must be designed so that the user can infer the conceptual model just from exploring the interface. This is not always easy.
To be clear - the conceptual space the software is built around isn't an implementation detail. It's the way you reach your goal; it necessarily imposes a burden on the user. A good conceptual space presses less heavily against the user, but you can't obscure the notion that there are containers in a file system but not a relational database.
There is always the discussion whether the UI should "hide the implementation details" (make the internal model, which differs from the conceptual model, invisible -- resulting in hard-to-understand behavior) or "make the implementation details visible" (change the conceptual model to be equal to the implementation model, and force the user to adapt to that).
But the one option that is rarely used but yields the (IMHO) best results is: design the conceptual model, then build/change the implementation model to be equal to it.
One example for this strategy that is forever stuck in my head is macOS application folders. The conceptual model is that an application can be moved around like a file, and applications be organized in folders like files. But you also want to run an application by double-clicking it. Instead of what Windows (and then Linux) did with links, menus, installing applications and centrally registering them etc., the implementation was changed to be like the conceptual model. A whole class of errors from inconsistencies just vanished.
I'd argue the implementation detail is still hidden. You don't know if Applications use FUSE or are WASM containers or docker images or what not.
Interface is a translator between what user understands ("I press button, channel changes") and implementation detail ("rubber dome changing resistivity, ...causing IR signal to be sent", ...).
Joel Spolsky described these as "leaky abstractions". If the implementation does not quite match the conceptual models, then the implementation "leaks out" to the user. The user is confused because the UI does not match the conceptual model in their head.
Usually, the designed conceptual model imposes constraints on the implementation. Sometimes, the implementation affects the conceptual model (a leaky abstraction). But they are logically orthogonal.
And you can't "abstract away" the conceptual model as if it were an implementation detail. The conceptual model IS the abstraction!
If I don't understand the conceptual model of the product, I will always be confused, no matter how well-labeled the icons are. For example, imagine a product that has a "New Configuration" command. What is a "Configuration"? Is it like a template that lets me define other objects? Is it a way to rapidly switch between different sets of options? Is it a container, like a folder?
The UI must be designed so that the user can infer the conceptual model just from exploring the interface. This is not always easy.