Code Guidelines

The programming code should prioritize adaptability and readability. This can be made by making it easy to refactor the code or to translate it to a completely other language. The use of standard/common code conventions also makes it easier to integrate other code easier and in a more consistent way.

Avoid side effects, as it makes it harder to understand a program. Avoid inheritance, because it makes it harder to write easily portable side effect free code under certain conditions. Inheritance works great as adhoc wrappers and type and implementation extenders. Inheritance does not support swapping out the parent implementation, which makes it often not portable in practice.

State intent and not actions. Therefore, pointer or index arithmetic should be avoided.

Readability is preferred over compactness, but compactness is still important.

Every full name should have an unambiguous meaning. This means a renaming would be valid in general, if every instance of the name can be renamed, while still maintaining the correct meaning. Names are preferred to abbreviation and abbreviation are preferred to symbols as a shorthand.

If there is an inverse usage for a given method likeisEmpty, consider creating a dedicated method. This minimizes the likelihood of misreading such an inverse usage. For example, it helps to create anisEmptyand anhasElementsmethod, because it is relatively hard to distinguishsomeObject.doSomething().doSomtingeElse().isEmpty()and!someObject.doSomething().doSomtingeElse().isEmpty()from one another, if one just skim through the code.

It should be possible to execute the tests programmatically inside the program. An appropriate main method should be provided, so the tests can be executed as a program. This ensures that tests are nothing special and therefore independent of the build system.

Every implemented feature should be tested. Also every project command should be tested as well.

Every test name starts with a verb like every other method that's primary function is an action. Every test name should refer to the primarily tested thing (Object/Method/Function/Class), the tested feature, the tested situation and the tested result in that order (This is based on Naming standards for unit tests by Roy Osherove ). All referred things in the method name, should be referred to, by its original name.

Inside tests following naming scheme can be used: a test subject is creating a test product that is verified or validated in order to create a test result. A test is successful, if the test result is positive.

Implicit runtime tests are generally speaking optional and not part of the main interface contract. In other words no code is allowed to rely on the fact, that it will be informed about errors implicitly.

It has to be explicitly stated, if, for instance, argument checking is part of the interface. These types of checks are not considered to be tests in this context.

Each test should have an error message, in order to minimize the time in order to understand an error.

The code should be formatted in such a way that the required space is minimized and the readability and navigability of the text is maximized. Empty lines are omitted, if indentation is enough to easily separate code blocks.

Trailing special symbols like commas in lists are preferred to leading symbols, as this is the most common way. Thereby, generally speaking, the overall structure of the source code is visible on the left side, whereas the meaning of the structure is located at the right side.

Maximize the replaceability of external dependencies. Minimize dependency on concrete versions of the dependencies. Prefer own interfaces and avoid accessing external things. Use dependency injection via static methods as this supports most paradigms and implementations. This also supports dependency injection of general objects like lists nicely.

Minimize the number of extern dependencies that are explicitly supported as these can cause a maintenance burden. Minimize side effects between dependencies. For example, in an ideal case transitive dependencies are not shared between dependencies.

If there are not enough resources or if it is not optimal to develop and maintain a piece of required functionality, then use a dependency in order to get this functionality and declare the functionality of the dependency as something that is out of scope of the project. The support, usage and extension of the dependency might still be part of the project.

Minimize direct dependencies between different things inside the project in order to easier analyse the effect of one piece of code to the rest of the project.

Try to create a common dictionary of words. Each word should be used for one meaning if possible. This makes it easier to create names for new things, to find new things by its name and to understand described things.

Use prefixes if multiple dictionaries have to be used in a document. This helps to associate each text with its correct meaning.

Avoid importing the same things over and over again in each file. If possible create dictionary documents that contain all imports and link to these dictionaries in each document. Minimize the number of dictionary documents which are linked to from a given document. Minimize the number of individual imports in non dictionary documents.

By default settings only events that require action or signal execution progress for the log inspector should be shown.

Model the (interactive) console and log files as event logs/queues. The subject/publisher of the event should always be directly or indirectly identifiable. This way it is ensured that the history of the execution is shown, which allows one understand the execution and interact with it. In the ideal case one can reproduce the history of each object.

Prefer placing support documentation for errors and similar in program code, instead of documentation, as this is more stable regarding automatic code refactoring. This can be done by adding runtime checks with an extensive error message.

If a support documentation is needed, try to structure it in the form of a decision tree, that finds the appropriate problem and solution given a set of symptoms.