Design‎ > ‎

Design principles and choices

This page lists the principles that the Zimbu design is based on, and what choices were made as a result.
More or less in order of importance.

1. Code must be easy to read.

Code is read at least 10 times more often than it's written.  Even when creating a program one reads back the text several times to check if it works. And when a bug needs to be fixed the programmer looks at the code several times to spot the problem.  Therefore code must be very easy to read back, and this may go at the cost of some more time spend on entering the text.

Key to good readability is a good mix of text and symbols.  Too much text makes you need to read it to understand it (Cobol).  Too many symbols makes it cryptic (Perl). It's best to leave out any symbols that are not really needed.
  • Use uppercase keywords for the most important items: CLASS, PROC, FOR, etc.
  • Use symbols for operators: && for logical and, | for bitwise or, == for equal, etc.
  • Do not use () around the condition for IF, FOR, etc. they are not needed.
  • Do not require (or allow) a semicolon to end a statement.
It also helps to use one style.  Many projects and companies use a style guide.  But this then requires another tool besides the compiler to verify the code meets the style.  It's a lot simpler if the compiler gives an error for a style violation. At least for where most programmers agree about the style, there still must be flexibility to format the code where it makes sense.
  • Require white space around operators. E.g.: "i=0" is wrong, this should be "i = 0".
  • Disallow white space where it isn't needed.  E.g. "foo ( arg )" is wrong, this should be "foo(arg)".
Meaning of words in the language should be close to what they mean in English.  For example "virtual function" can only be understood after studying OO terminology.  "default function" does have a meaning, it avoids required knowledge. At the same time, keep the words short, long words are harder to read. Make just long enough to have a clear meaning.
  • Use "int" for integers, "float" for floating point numbers.  Do not use "double" or "long", they are meaningless.
  • Do not use "static", one cannot guess what it means.
It must be avoided that tiny changes in text mean something very different.  For example, when changing a colon into a semicolon results in working code that does something different, this will be a very hard to spot bug.

2. Learn from experience

One can only make good choices when one recognizes what matters and what doesn't.  Writing programs in various languages provides the necessary experience. See the Inspiration page.

3. Nobody likes bugs

The number of bugs in a program is directly related to how easy it is do write good code.  If one has to write lots of tests to avoid problems (C++) basic reliability will still be low.

When debugging it is important to understand what the program could do and what is impossible. This minimizes the possible causes for a bug that need to be looked into.  E.g., if an object member is private, you can be sure that it isn't changed outside of the class it's defined in.  If an int variable is marked as a constant, you know what the value is, it won't ever change.

Type checking helps a lot.  Java is a good example here.  However, this conflicts with ease of use (e.g., Python).  It should work to have as much static type checking as possible, but make it possible to have dynamic types with runtime type checking.

Programmers make mistakes.  Over time we have learned what the common mistakes are.  The language should be designed so that common mistakes result in a compiler error, so that they are found early.

4. Faster is better

If one has a very nice language that is too slow, it won't be used.  And "too slow" quickly means slower than others.  That is why C and C++ are often favored above Python and Java.

5. The next compiler version will add a new feature

Once a compiler version is released programs will be written and distributed.  The next version must not break the existing programs. Thus it must be possible to add keywords, types, modules, etc. without worrying that this might break someone's carefully crafted code.
  • Keywords are all-caps. No user symbol may be all-caps
  • Builtin type names are all lowercase.  User types must start with an uppercase letter.
  • Builtin module names are all-caps. User modules must contain a lowercase letter.
  • Predefined methods start with an uppercase letter.  User methods must start with a lowercase letter.
This may seem a bit strange at first, but one gets used to it very quickly. And the compiler gives a clear error message when making a mistake.

6. Write once, run everywhere

A program must be able to run on many different systems without changing it. This not only means the compiler is available, but also that the libraries are portable.

The language should solve portability problems.  Avoid having every programmer work around differences, do it once for all.

7. Programmers need tools

Progamming tools are essential.  The language should make it easy, or at least possible, to have tools do such things as:
- reformatting
- auto-indenting
- refactoring
- automatic completion
- looking up documentation