Skip to content

Extensive Compile Time Checking

Bruno Medeiros edited this page Jul 12, 2016 · 1 revision

MelnormeEclipse follows a design principle of extensive compile-time type/contract checking. This means designing APIs and data types so as to catch errors at compile-time, whenever possible, and codify the underlying contracts in the type system.

Now, we all should know about Contract Programming, in which one uses assertion checks to verify contracts in one's code. This is a good practice, but a limitation is that these are run-time checks. An even better option is to have the checks done at compile-time, if possible. A lot of checks are conceptually feasible at compile-time, but in practice not all languages support certain checks (like null-ability checks). For example, Rust supports a lot more compile-time checks than Java. That said, even in Java there are many things that can be done to follow this principle. This might sometimes mean forsaking types from the Java standard library, and using variants instead.

For example, in Melnorme we have:

  • Avoidance of unchecked exceptions. Unchecked exceptions should only be thrown for situations that signal a bug in the code (assertion failure and similar errors). This is despite some "conventional wisdom" in the Java community and elsewhere that it should be otherwise, for example as touted in Bruce Eckel's often quote article "Does Java need Checked Exception", the link to which is no longer available... take that as a sign.
  • This means we avoid the use of for example: java.nio.file.InvalidPathException, java.util.concurrent.CancellationException, org.eclipse.core.runtime.OperationCanceledException, etc. .
  • Indexable: Substitute for java.util.List because it exposes both read and write operations - there is no way to expose list access in a read-only way at compile-time (Collections.unmodifiableList() is a run-time check). So Indexable addresses that, and similarly it is a substitute for uses of arrays. In the same style there is Collection2 for ready-only access to Collection, MapAccess for Map, etc.
  • PathUtil: Constructors for java.nio.file.Path that throw a checked exception instead of an unchecked one if the Path is invalid (see first point above). Who was it that thought throwing a runtime exception for validating user data was a good idea?? 😧 😠
    • Similarly, there is Location for a path that is guaranteed to be absolute, and normalized.
  • CallableX: Variant of java.util.concurrent.Callable, allow specifying the thrown exception as a type parameter. In the same style: FunctionX for java.util.concurrent.Function.
  • FutureX: Variant of java.util.concurrent.Future, with a safer and more precise API, with regards to exception throwing. In the same style: RunnableFutureX for RunnableFuture, FutureTaskX for FutureTask.
Clone this wiki locally