General 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 an isEmpty and an hasElements method, because it is relatively hard to distinguish someObject.doSomething().doSomtingeElse().isEmpty() and !someObject.doSomething().doSomtingeElse().isEmpty() from one another, if one just skim through the code.

For method names prefer using a noun, if the of the method is to retrieve something. Use verbs instead, if the goal of the function is to do something or to change something.

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.

Any kind of error testing method like the `orElseThrow` method of Java's Optional class, should have a required error message argument. Otherwise, it is unnecessarily hard to debug errors of users, whose computer cannot be accessed. Such error messages or reports do not have to be statically typed, in order to make it easier to add error messages to code, which is often more important, than having easily processed error messages.

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. This is especially important, if the test is run during the execution of the program by an external user.

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 on the right side.

Automatic code styling/formatting should never remove already present new line characters, as otherwise it is hard to structure large code statements. The automatic formatting should also not add new line symbols, as this makes it harder to structure flowing text, where long lines are more acceptable. In most cases, during automatic formatting only whitespaces (without new line symbols) between symbols should be normalized.

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, signal overhaul execution progress for the log inspector should be shown. Log code should be separated from the actual as much as possible, in order to reduce noise of regular program code. This is especially the case for trace logging.

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.

Logging has to provide a form of double entry bookkeeping. Especially for the programs configuration, inputs and outputs.

Therefore, the log has to signal for every thing, where the thing is coming from, what has happened to the thing and where the thing is going to. Where is a config value coming from, how is it interpreted and what component is using the config value.

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.