-
Notifications
You must be signed in to change notification settings - Fork 3
Extensive Compile Time Checking
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 forjava.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). SoIndexable
addresses that, and similarly it is a substitute for uses of arrays. In the same style there isCollection2
for ready-only access toCollection
,MapAccess
forMap
, etc. -
PathUtil
: Constructors forjava.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.
- Similarly, there is
-
CallableX
: Variant ofjava.util.concurrent.Callable
, allow specifying the thrown exception as a type parameter. In the same style:FunctionX
forjava.util.concurrent.Function
. -
FutureX
: Variant ofjava.util.concurrent.Future
, with a safer and more precise API, with regards to exception throwing. In the same style:RunnableFutureX
forRunnableFuture
,FutureTaskX
forFutureTask
.