Good design for developers & good design for non-developers don’t operate by different rules.
Good design for developers & good design for non-developers don’t operate by different rules. Devs aren’t happy needing to memorize manuals, and end users can & will learn things if it makes their lives easier.
The primary difference between a programming language & an application GUI is the expected acceptable tradeoff between initial learning curve steepness & flexibility.
If you can get more flexibility without making your initial learning curve steeper, you will please the entire spectrum of users. (Hint: you probably can. Think about it.)
I’ve said all this before, but maybe saying it this way is more understandable.
Consider what it would be like if, as part of your windowing environment or widget toolkit, every application had, built-in, the ability to perform a for-loop-like or while-loop-like behavior whose conditions are defined by the user. Just importing one (simple) structure from programming & making it universal to all GUI apps would have an enormous effect on flexibility, while remaining totally accessible to non-technical users. (No user is unable to imagine the concept of ‘do it 10 times’)
Interface usability in a nutshell: minimize how often the simplest way to do a thing the user wants to do is 1) hard to imagine before you see it, or 2) hard to understand once observed. (Assume the user is more creative than you & less well-informed.)
(Like all interface usability concerns, this applies equally to programming languages as to GUI applications, because the only real difference between the two is how much of the manual you can assume the user is willing to read)
This is similar to the ‘law of least surprise’, but it also makes explicit some things about the normal formulation of law of least surprise that are easily ignored. Also, where the law of least surprise is post-hoc (about whether or not the user can predict and understand individual actions), this formulation is about planning whole sequences of interactions.
Often, simple & predictable components or steps cannot be combined to produce comparably simple & predictable large-scale solutions. For instance, assembly language instructions are incredibly simple and predictable, but understanding large assembly-language programs is hard.
When the simplicity of components doesn’t scale, you end up with write-only languages: it’s easy to figure out how to solve a problem because each step is easily understood in certain circumstances (known to the programmer), but those circumstances must be reverse-engineered by a maintainer if a change is needed and any information is missing — for instance, to determine the intended behavior, correctness, or input format of some code.