This article presents a Java/C++ design pattern which I call
Submodes in which a single class is split into two classes so
that control of setting and getting of properties can be managed.
This is useful if a class has properties that can be meaningfully
setted or getted if other properties have specific values. For
example in a game, a timer variable explode_time may only be
meaningful if another boolean (in Java) or bool (in C++)
property explode_mode is set to true. In C++ variables of
type bool, char, int, float, double and
pointers are initialised to no specific value, just whatever is the
contents of memory at the time the variable is constructed. Using
Submodes, errors for uninitialised properties can be found at
debug-time (when the symbol NDEBUG is not set), and the overhead
of the extra testing code can be optimised away into nothing in
release versions (when NDEBUG is set) for the same level of
performance as if Submodes were not used.
1. The design pattern in Java
In complicated classes, some properties may only be meaningfully
getted or setted if certain other variables are certain values.
Consider the following class where the comments indicate which values
the properties may have before they can be getted or setted.
// The following property is meaningful if a1 is 0
// The following property is meaningful if a3 is 0
public X a4;
Here is how the above class can be split into two classes:
In the above the macros SUBMODES_INNER_VAR, SUBMODES_OUTER_GET
and SUBMODES_OUTER_SET should be used for types that can be passed
and returned by value. The macros SUBMODES_INNER_VAR_STAR,
SUBMODES_OUTER_GET_STAR and SUBMODES_OUTER_SET_STAR should by used
for types that are to be passed and returned by pointer.
Here is the definition of a class that is useful for debugging
uninitialised properties. This class differs from the bool type in
that safe_bool objects are initialised to false, compared with
no specific value for bool objects.
value = false;
/// Needed for assignment sb = b
value = b;
ASSERT(this != null);
Here is the definition of the macros for the A_Inner class:
I have inspected assembler code generated by GNU C++ from source code
that uses Submodes and have found that if the setting/getting tests
are dropped when NDEBUG is set as is the case for the above macro
definitions, then the resulting code is just as efficient as if
Submodes were not used.