The primary purpose of the programming language is to make it easy for the programmer to communicate to other humans what the program does. Incidentally, the programs are also interpreted by the computer.
Jakob Nielsen, a famous usability guru, has defined ten general principles for user interface design. What follows are Nielsen’s principles applied to programming language design.
When reading this, bear in mind that a programming language is much more than just a language manual and a compiler. The whole development environment and ecosystem of libraries are as much part of the programming language as the syntax and semantics of the core language. Even the online community of programmers can be thought of part of the language. So when I’m talking about “programming languages”, I usually refer to the whole experience, not just the bare language.
These are ten general principles for programming language design. They are called “heuristics” because they are more in the nature of rules of thumb than specific usability guidelines. Some of these heuristics are clearly applicable to the design of the core language, some to the IDE, others perhaps to standard language libraries.
My apologies to Mr. Nielsen for messing with his stuff.
Visibility of system status
The system should always keep the programmer informed about what is going on, through appropriate feedback within reasonable time.
Match between system and the real world
The system should speak the programmers’ language, with words, phrases and concepts familiar to the programmer, rather than programming language theory-oriented terms. Follow real-world conventions, making the system behave in a natural and logical order.
Programmer control and freedom
Real-world system resources are often unavailable or fail. Program code using these will need an effortless “emergency exit” to leave the unwanted state without having to clutter the code with error handling.
Consistency and standards
Programmers should not have to wonder whether different syntaxes, contexts, or names mean the same thing. Follow platform conventions.
Even better than good error codes is a careful design which prevents a problem from occurring in the first place. Either eliminate error-prone conditions or check for them and present programmers with information on the different ways their code may fail.
Recognition rather than recall
Minimize the programmer’s memory load by making objects, actions, and options visible. The programmer should not have to remember information from one part of the program to another. Instructions for use of the system should be visible or easily retrievable whenever appropriate.
Flexibility and efficiency of use
Accelerators – unseen by the novice programmer – may often speed up the interaction for the expert user such that the system can cater to both inexperienced and experienced users. Allow programmers to tailor frequent actions.
Aesthetic and minimalist design
Functions should not require arguments which are irrelevant or rarely needed. Every extra unit of information in a parameter list competes with the relevant units of information and diminishes their relative visibility.
Help programmers recognize, diagnose, and recover from errors
Error and warning messages should be expressed in plain language (no codes), precisely indicate the problem, and constructively suggest a solution.
Help and documentation
Even though it is better if the system can be used without documentation, it may be necessary to provide help and documentation. Any such information should be easy to search, focused on the user’s task, list concrete steps to be carried out, and not be too large.