Preprocessing is the execution of simple logic statements at build time and usually results in multiple target builds. Preprocessing is a fixed compile time optimisation, not a dynamic runtime adaptation like the other patterns presented in this document. This means that the IDE will create two or more different versions of your application, each tailored for some specific family of devices. You can create all of these preprocessor JAR variants at once by telling NetBeans to “Batch Clean and Build” from the project menu.
Preprocessing has an advantage of resulting in smaller application JAR sizes than any runtime pattern. Only the supported functionality and resources are included in the JAR package, rather than all possible resources (like all language variants and all screen size image variants). Resources here could also be device or screen specific graphics, allowing for much smaller .jar sizes while still providing the best possible graphics for the user.
Runtime adaptation is almost always preferred over preprocessing
when targeting multiple phones. Preprocessing commands are issued
not as code but as Java “comment” lines such as //#debug
, //#ifdef FullTouchBuild
, or //#ifndef
Arabic
. The IDE’s build scripts use these to comment out
sections of code before compiling as you create multiple “build profiles”.
Unfortunately, NetBeans and Nokia IDE for Java ME (Eclipse) have slightly different preprocessor directives, so you cannot easily change your IDE without updating all the directives. Another drawback is that the increased number of different .jar files that are produced, reduces developer productivity. Multiple JARs means slower batch build cycles and the need to test each variant separately.
Even though we would use runtime adaptation to target different phones, preprocessing is a very useful technique for creating different debug, profile and release builds, each with optimal settings or firing up a different Nokia SDK emulator (as shown in the figure below).
You can also use preprocessing within your debug profile(s) to make running tests easier. Below is an example of preprocessing in order to produce a different code snippet for development and release packages. In this case, we are adding debug and testing commands to the application which will automatically be removed from the production release. This example has been tested with NetBeans IDE currently.
public Command[] getCommands() { //#ifdef Release //# return new Command[]{updateCommand, exitCommand}; //#else return new Command[]{updateCommand, exitCommand, clearCacheCommand, prefetchImagesCommand}; //#endif }
We can similarly vary the application for different language variants and different phone models, if runtime code modification patterns do not work as well for a special need.
Figure: IDE build profiles can be referenced in preprocessor directives to aid in debugging and testing with multiple Nokia emulators